Monorepo for Tangled
Something went wrong. Try again.
Go
at sl/md-editor
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160package models
import ( "errors" "fmt" "time" "unicode/utf8"
"github.com/bluesky-social/indigo/atproto/syntax" lexutil "github.com/bluesky-social/indigo/lex/util" "tangled.org/core/api/tangled")
type String struct { Did syntax.DID Rkey syntax.RecordKey Cid *syntax.CID
// String_File will remain, and we will still use it. // We just use `FileContent` when fetching the file.
// after that, change lexicon, start migrating to blobs // when string is migrated, clear FileName and FileContent. // when they are cleared, fetch the blob on page load.
Title *string Description *string Files []String_File Created time.Time Edited *time.Time
// legacy string data FileName string FileContent string
// optionally, populate this when querying for reverse mappings Stats *StringStats}
// String_File is [tangled.String_File] with optional prefetched & decompressed text blob contenttype String_File struct { Name string Content lexutil.LexBlob}
func (s *String) AtUri() syntax.ATURI { return syntax.ATURI(fmt.Sprintf("at://%s/%s/%s", s.Did, tangled.StringNSID, s.Rkey))}
func (s *String) AsRecord() *tangled.String { var files []*tangled.String_File for _, f := range s.Files { files = append(files, &tangled.String_File{ Name: f.Name, Content: &f.Content, }) } return &tangled.String{ Title: s.Title, Description: s.Description, Files: files, CreatedAt: s.Created.Format(time.RFC3339), }}
func (s *String) Validate() error { var err error if s.FileName == "" && len(s.Files) == 0 { err = errors.Join(err, fmt.Errorf("string should have more than one files")) } // legacy record check if utf8.RuneCountInString(s.FileName) > 140 { err = errors.Join(err, fmt.Errorf("filename too long")) } for i, file := range s.Files { if utf8.RuneCountInString(file.Name) > 140 { err = errors.Join(err, fmt.Errorf("filename too long at files[%d]", i)) } } if s.Title != nil { if utf8.RuneCountInString(*s.Title) > 140 { err = errors.Join(err, fmt.Errorf("title too long")) } } if s.Description != nil { if utf8.RuneCountInString(*s.Description) > 280 { err = errors.Join(err, fmt.Errorf("description too long")) } } return err}
func (s String) RenderTitle() string { if s.Title != nil { return *s.Title } if len(s.Files) > 0 { return s.Files[0].Name } return s.FileName}
// FileByName returns first item in files with given filenamefunc (s *String) FileByName(name string) (String_File, bool) { for _, file := range s.Files { if file.Name == name { return file, true } } return String_File{}, false}
func (s String) IsLegacySingleFile() bool { return len(s.Files) == 0}
// StringFromRecord creates [String] from [tangled.String].// NOTE: This won't prefetch blobsfunc StringFromRecord(did syntax.DID, rkey syntax.RecordKey, cid syntax.CID, record tangled.String) (String, error) { created, err := time.Parse(time.RFC3339, record.CreatedAt) if err != nil { return String{}, fmt.Errorf("invalid createdAt: %w", err) } var files []String_File for _, f := range record.Files { files = append(files, String_File{ Name: f.Name, Content: *f.Content, }) } return String{ Did: did, Rkey: rkey, Cid: &cid, Title: record.Title, Description: record.Description, Files: files, Created: created, FileName: stringPtr(record.Filename), FileContent: stringPtr(record.Contents), }, nil}
type StringStats struct { StarCount int // CommentCount int}
type StringFileStats struct { LineCount int ByteCount int}
func stringPtr(s *string) string { if s == nil { return "" } return *s}