Lexicon:
{
"lexicon": 1,
"id": "sh.weaver.notebook.defs",
"defs": {
"notebookView": {
"type": "object",
"required": ["uri", "cid", "authors", "record", "indexedAt"],
"properties": {
"title": { "type": "ref", "ref": "#title" },
"path": { "type": "ref", "ref": "#path" },
"tags": { "type": "ref", "ref": "#tags" },
"uri": { "type": "string", "format": "at-uri" },
"cid": { "type": "string", "format": "cid" },
"authors": {
"type": "array",
"items": { "type": "ref", "ref": "#authorListView" }
},
"permissions": {
"type": "ref",
"ref": "#permissionsState"
},
"record": { "type": "unknown" },
"indexedAt": { "type": "string", "format": "datetime" },
"likeCount": { "type": "integer" },
"bookmarkCount": { "type": "integer" },
"subscriberCount": { "type": "integer" },
"entryCount": { "type": "integer" },
"viewerLike": { "type": "string", "format": "at-uri" },
"viewerBookmark": { "type": "string", "format": "at-uri" },
"viewerSubscription": { "type": "string", "format": "at-uri" },
"viewerReadingProgress": { "type": "ref", "ref": "#readingProgress" }
}
},
"entryView": {
"type": "object",
"required": ["uri", "cid", "authors", "record", "indexedAt"],
"properties": {
"title": { "type": "ref", "ref": "#title" },
"path": { "type": "ref", "ref": "#path" },
"tags": { "type": "ref", "ref": "#tags" },
"uri": { "type": "string", "format": "at-uri" },
"cid": { "type": "string", "format": "cid" },
"authors": {
"type": "array",
"items": { "type": "ref", "ref": "#authorListView" }
},
"permissions": {
"type": "ref",
"ref": "#permissionsState"
},
"record": { "type": "unknown" },
"renderedView": {
"type": "ref",
"ref": "#renderedView"
},
"indexedAt": { "type": "string", "format": "datetime" },
"likeCount": { "type": "integer" },
"bookmarkCount": { "type": "integer" },
"viewerLike": { "type": "string", "format": "at-uri" },
"viewerBookmark": { "type": "string", "format": "at-uri" },
"viewerReadingProgress": { "type": "ref", "ref": "#readingProgress" }
}
},
"renderedView": {
"type": "object",
"required": ["html"],
"properties": {
"html": {
"type": "blob",
"accept": ["text/html"],
"maxSize": 1000000
},
"css": {
"type": "blob",
"accept": ["text/css"],
"maxSize": 1000000
}
},
"description": "View of a rendered and cached notebook entry"
},
"authorListView": {
"type": "object",
"required": ["record", "index"],
"properties": {
"uri": { "type": "string", "format": "at-uri" },
"record": {
"type": "ref",
"ref": "sh.weaver.actor.defs#profileDataView"
},
"index": { "type": "integer" }
}
},
"bookEntryView": {
"type": "object",
"description": "An ordered entry in a Weaver notebook.",
"required": ["entry", "index"],
"properties": {
"entry": {
"type": "ref",
"ref": "#entryView"
},
"index": { "type": "integer" },
"next": {
"type": "ref",
"ref": "#bookEntryRef"
},
"prev": {
"type": "ref",
"ref": "#bookEntryRef"
}
}
},
"bookEntryRef": {
"type": "object",
"required": ["entry"],
"properties": {
"entry": {
"type": "ref",
"ref": "#entryView"
}
}
},
"title": {
"type": "string",
"maxLength": 300,
"description": "The title of the notebook entry."
},
"path": {
"type": "string",
"maxLength": 100,
"description": "The path of the notebook."
},
"tags": {
"type": "array",
"items": {
"type": "string",
"maxLength": 64
},
"maxLength": 10,
"description": "An array of tags associated with the notebook entry. Tags can help categorize and organize entries."
},
"contentFormat": {
"type": "object",
"description": "The format of the content. This is used to determine how to render the content.",
"properties": {
"markdown": {
"type": "string",
"description": "The format of the content. This is used to determine how to render the content.",
"enum": ["commonmark", "gfm", "obsidian", "weaver"],
"default": "weaver"
}
}
},
"permissionsState": {
"type": "object",
"description": "ACL-style permissions for a resource. Separate from authors (who contributed).",
"required": ["editors"],
"properties": {
"editors": {
"type": "array",
"description": "DIDs that can edit this resource",
"items": { "type": "ref", "ref": "#permissionGrant" }
},
"viewers": {
"type": "array",
"description": "DIDs that can view (future use)",
"items": { "type": "ref", "ref": "#permissionGrant" }
}
}
},
"permissionGrant": {
"type": "object",
"description": "A single permission grant. For resource authority: source=resource URI, grantedAt=createdAt. For invitees: source=invite URI, grantedAt=accept createdAt.",
"required": ["did", "scope", "source", "grantedAt"],
"properties": {
"did": { "type": "string", "format": "did" },
"scope": {
"type": "string",
"knownValues": ["direct", "inherited"],
"description": "direct = this resource (includes authority), inherited = via notebook invite"
},
"source": {
"type": "string",
"format": "at-uri",
"description": "For authority: resource URI. For invitees: invite URI"
},
"grantedAt": {
"type": "string",
"format": "datetime",
"description": "For authority: record createdAt. For invitees: accept createdAt"
}
}
},
"feedEntryView": {
"type": "object",
"description": "Entry with feed-specific context (discovery reason, notebook context).",
"required": ["entry"],
"properties": {
"entry": { "type": "ref", "ref": "#entryView" },
"reason": { "type": "ref", "ref": "#feedReason" },
"notebookContext": { "type": "ref", "ref": "#feedNotebookContext" }
}
},
"feedNotebookContext": {
"type": "object",
"description": "Minimal notebook context for feed display.",
"required": ["uri", "title"],
"properties": {
"uri": { "type": "string", "format": "at-uri" },
"title": { "type": "string" },
"path": { "type": "string" }
}
},
"feedReason": {
"type": "union",
"description": "Why this entry appeared in the feed.",
"refs": ["#reasonLike", "#reasonBookmark", "#reasonSubscription"]
},
"reasonLike": {
"type": "object",
"required": ["by", "indexedAt"],
"properties": {
"by": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" },
"indexedAt": { "type": "string", "format": "datetime" }
}
},
"reasonBookmark": {
"type": "object",
"required": ["by", "indexedAt"],
"properties": {
"by": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" },
"indexedAt": { "type": "string", "format": "datetime" }
}
},
"reasonSubscription": {
"type": "object",
"required": ["indexedAt"],
"properties": {
"indexedAt": { "type": "string", "format": "datetime" }
}
},
"publishedVersionView": {
"type": "object",
"description": "A published version of an entry in a collaborator's repo.",
"required": ["uri", "cid", "publisher", "publishedAt"],
"properties": {
"uri": { "type": "string", "format": "at-uri" },
"cid": { "type": "string", "format": "cid" },
"publisher": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" },
"publishedAt": { "type": "string", "format": "datetime" },
"updatedAt": { "type": "string", "format": "datetime" },
"isCanonical": {
"type": "boolean",
"description": "True if this is the 'primary' version (owner's repo)"
},
"divergedFrom": {
"type": "ref",
"ref": "com.atproto.repo.strongRef",
"description": "If content differs, the version it diverged from"
}
}
},
"contentWarning": {
"type": "string",
"description": "Author-applied content warning.",
"knownValues": [
"violence",
"graphic-violence",
"death",
"major-character-death",
"sexual-content",
"explicit-sexual-content",
"language",
"substance-use",
"self-harm",
"abuse",
"disturbing-imagery"
]
},
"contentWarnings": {
"type": "array",
"description": "Author-applied content warnings.",
"maxLength": 10,
"items": { "type": "ref", "ref": "#contentWarning" }
},
"contentRating": {
"type": "string",
"description": "Author-applied content rating.",
"knownValues": ["general", "teen", "mature", "explicit"]
},
"chapterView": {
"type": "object",
"description": "Hydrated view of a chapter.",
"required": ["uri", "cid", "notebook", "authors", "record", "indexedAt"],
"properties": {
"uri": { "type": "string", "format": "at-uri" },
"cid": { "type": "string", "format": "cid" },
"title": { "type": "ref", "ref": "#title" },
"tags": { "type": "ref", "ref": "#tags" },
"notebook": { "type": "ref", "ref": "#notebookView" },
"authors": {
"type": "array",
"items": { "type": "ref", "ref": "#authorListView" }
},
"record": { "type": "unknown" },
"entryCount": { "type": "integer" },
"indexedAt": { "type": "string", "format": "datetime" }
}
},
"chapterEntryView": {
"type": "object",
"description": "An entry within a chapter context.",
"required": ["entry", "index"],
"properties": {
"entry": { "type": "ref", "ref": "#entryView" },
"index": { "type": "integer" },
"next": { "type": "ref", "ref": "#bookEntryRef" },
"prev": { "type": "ref", "ref": "#bookEntryRef" }
}
},
"pageView": {
"type": "object",
"description": "Hydrated view of a page (entries displayed together).",
"required": ["uri", "cid", "notebook", "record", "indexedAt"],
"properties": {
"uri": { "type": "string", "format": "at-uri" },
"cid": { "type": "string", "format": "cid" },
"title": { "type": "ref", "ref": "#title" },
"tags": { "type": "ref", "ref": "#tags" },
"notebook": { "type": "ref", "ref": "#notebookView" },
"record": { "type": "unknown" },
"entryCount": { "type": "integer" },
"indexedAt": { "type": "string", "format": "datetime" }
}
},
"readingProgress": {
"type": "object",
"description": "Viewer's reading progress (appview-side state, not a record).",
"properties": {
"status": {
"type": "string",
"knownValues": ["reading", "finished", "abandoned", "want-to-read"]
},
"currentEntry": {
"type": "string",
"format": "at-uri",
"description": "Last entry the viewer was reading."
},
"percentComplete": {
"type": "integer",
"minimum": 0,
"maximum": 100
},
"lastReadAt": { "type": "string", "format": "datetime" },
"startedAt": { "type": "string", "format": "datetime" },
"finishedAt": { "type": "string", "format": "datetime" }
}
}
}
}
Generated output:
///Why this entry appeared in the feed.
#[jacquard_derive::open_union]
#[derive(
serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, jacquard_derive::IntoStatic,
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
pub enum FeedReason<'a> {
#[serde(rename = "sh.weaver.notebook.defs#reasonLike")]
ReasonLike(Box<crate::sh_weaver::notebook::ReasonLike<'a>>),
#[serde(rename = "sh.weaver.notebook.defs#reasonBookmark")]
ReasonBookmark(Box<crate::sh_weaver::notebook::ReasonBookmark<'a>>),
#[serde(rename = "sh.weaver.notebook.defs#reasonSubscription")]
ReasonSubscription(Box<crate::sh_weaver::notebook::ReasonSubscription<'a>>),
}
...
/// Entry with feed-specific context (discovery reason, notebook context).
#[jacquard_derive::lexicon]
#[derive(
serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, jacquard_derive::IntoStatic,
)]
#[serde(rename_all = "camelCase")]
pub struct FeedEntryView<'a> {
#[serde(borrow)]
pub entry: crate::sh_weaver::notebook::EntryView<'a>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
pub notebook_context: std::option::Option<crate::sh_weaver::notebook::FeedNotebookContext<'a>>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
pub reason: std::option::Option<crate::sh_weaver::notebook::FeedReason>,
}