···11package site
2233-import "time"
33+import (
44+ "encoding/json"
55+ "strings"
66+ "time"
77+)
4859const LexiconDocument = LexiconBase + ".document"
610···2428 // Max graphemes: 3000.
2529 Description *string `json:"description,omitempty"`
2630 // CoverImage to used for thumbnail or cover.
2727- // Less than 1MB is size.
2828- CoverImage any `json:"-"`
2929- // Content is an open union used to define the [Document]'s content.
3030- // Each entry must specify a `$type`.
3131- Content []any `json:"-"`
3131+ // Less than 1MB in size.
3232+ CoverImage *Blob `json:"coverImage,omitempty"`
3333+ // Content is a custom [Lexicon] used to define the [Document]'s content.
3434+ Content *LexiconJSON `json:"content,omitempty"`
3235 // TextContent is a plaintext representation of the [Document.Content].
3336 // Should not contain markdown or other formatting.
3437 TextContent string `json:"textContent,omitempty"`
3538 // BlueskyPostRef is a strong reference to a Bluesky post.
3639 // Useful to keep track of comments off-platform.
4040+ //
4141+ // Currently, the type is [any], because I don't understand how I should represent it.
4242+ // It looks like to be a strong ref, but a record generated by `leaflet.pub`:
4343+ // 1. doesn't include a `$type`
4444+ // 2. has more info than required by the lexicon used
3745 BlueskyPostRef any `json:"bskyPostRef,omitempty"`
3846 // Tags is an array of strings used to tag or categorize the [Document].
3947 // Avoid prepending tags with hashtags.
···4755func (d *Document) Type() string {
4856 return LexiconDocument
4957}
5858+5959+func (d *Document) MarshalMap() (map[string]any, error) {
6060+ type t Document
6161+ mp, err := MarshalToMap(t(*d))
6262+ if err != nil {
6363+ return nil, err
6464+ }
6565+ if v, ok := mp["path"]; ok && !strings.HasPrefix(v.(string), "/") {
6666+ mp["path"] = "/" + v.(string)
6767+ }
6868+ mp["publishedAt"] = d.PublishedAt.UTC().Format(TimeFormat)
6969+ if d.UpdatedAt != nil {
7070+ tn := d.UpdatedAt.UTC().Format(TimeFormat)
7171+ mp["updatedAt"] = &tn
7272+ }
7373+ return mp, nil
7474+}
7575+7676+func (d *Document) UnmarshalJSON(b []byte) error {
7777+ type t Document
7878+ var v struct {
7979+ t
8080+ PublishedAt string `json:"publishedAt"`
8181+ UpdatedAt *string `json:"updatedAt,omitempty"`
8282+ }
8383+ err := json.Unmarshal(b, &v)
8484+ if err != nil {
8585+ return err
8686+ }
8787+ v.t.PublishedAt, err = time.Parse(TimeFormat, v.PublishedAt)
8888+ if err != nil {
8989+ return err
9090+ }
9191+ if v.UpdatedAt != nil {
9292+ v.t.PublishedAt, err = time.Parse(TimeFormat, *v.UpdatedAt)
9393+ if err != nil {
9494+ return err
9595+ }
9696+ }
9797+ *d = Document(v.t)
9898+ return nil
9999+}
···11package site
2233+import "strings"
44+35const LexiconPublication = LexiconBase + ".publication"
4657// Publication represents a collection of documents published to the web.
···1113 // Base URL of the [Publication].
1214 // This value will be combined with the [Document.Path] to construct a full URL for the document.
1315 // Avoid trailing slashes.
1414- URL string `json:"string"`
1616+ URL string `json:"url"`
1517 // Name of the [Publication].
1618 // Max length: 5000.
1719 // Max graphemes: 500.
1820 Name string `json:"name"`
1921 // Icon to identify the [Publication].
2022 // Must be a square image and should be at least 256x256.
2121- Icon any `json:"-"`
2323+ Icon *Blob `json:"icon,omitempty"`
2224 // Description of the [Publication].
2325 // Max length: 30000.
2426 // Max graphemes: 3000.
2527 Description *string `json:"description,omitempty"`
2628 // Simplified theme for tools and apps to utilize when displaying content.
2727- // Ref to `site.standard.theme.basic`.
2828- BasicTheme any `json:"basicTheme,omitempty"`
2929+ BasicTheme *Theme `json:"basicTheme,omitempty"`
2930 // Platform-specific [Preferences] for the [Publication], including discovery and visibility settings.
3031 Preferences *Preferences `json:"preferences,omitempty"`
3132}
32333434+func (p *Publication) Type() string {
3535+ return LexiconPublication
3636+}
3737+3838+func (p *Publication) MarshalMap() (map[string]any, error) {
3939+ type t Publication
4040+ pp := t(*p)
4141+ pp.URL = strings.TrimSuffix(pp.URL, "/")
4242+ return MarshalToMap(pp)
4343+}
4444+3345// Preferences of the [Publication].
3446type Preferences struct {
3547 // ShowInDiscover decides whether the [Publication] should appear in discovery feeds.
3648 ShowInDiscover bool `json:"showInDiscover"`
3749}
3838-3939-func (p *Publication) Type() string {
4040- return LexiconPublication
4141-}