Something went wrong. Try again.
a tool for shared writing and social publishing
Something went wrong. Try again.
12 kB · 543 lines
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544import type { AppBskyFeedGetPostThread } from "@atproto/api";import type { DeepAsReadonlyJSONValue } from "./utils";
const RootAttributes = { "root/page": { type: "ordered-reference", cardinality: "many", }, // Links a standalone cover image (uploaded from the publish page, not an // in-document image block) to the root so it's reachable by get_facts and // its blob gets uploaded on publish. "root/cover-image": { type: "reference", cardinality: "one", },} as const;const PageAttributes = { "card/block": { type: "ordered-reference", cardinality: "many", }, "page/type": { type: "page-type-union", cardinality: "one", }, // Publication nav state: root/page entries carry a route and tab title; // entries with page/external-url instead are external link tabs. "page/route": { type: "string", cardinality: "one", }, "page/title": { type: "string", cardinality: "one", }, "page/external-url": { type: "string", cardinality: "one", }, "canvas/block": { type: "spatial-reference", cardinality: "many", }, "canvas/block/width": { type: "number", cardinality: "one", }, "canvas/block/rotation": { type: "number", cardinality: "one", }, "canvas/narrow-width": { type: "boolean", cardinality: "one", }, "canvas/background-pattern": { type: "canvas-pattern-union", cardinality: "one", },} as const;
const BlockAttributes = { "block/type": { type: "block-type-union", cardinality: "one", }, "block/is-list": { type: "boolean", cardinality: "one", }, "block/is-locked": { type: "boolean", cardinality: "one", }, "block/check-list": { type: "boolean", cardinality: "one", }, "block/text-alignment": { type: "text-alignment-type-union", cardinality: "one", }, "block/date-time": { type: "date-time", cardinality: "one", }, "block/text": { type: "text", cardinality: "one", }, "block/heading-level": { type: "number", cardinality: "one", }, "block/text-size": { type: "text-size-union", cardinality: "one", }, "block/image": { type: "image", cardinality: "one", }, "block/card": { type: "reference", cardinality: "one", }, "block/bluesky-post": { type: "bluesky-post", cardinality: "one", }, "block/standard-site-post": { type: "string", cardinality: "one", }, "standard-site-post/size": { type: "standard-site-post-size-union", cardinality: "one", }, "standard-site-post/show-publication-theme": { type: "boolean", cardinality: "one", }, "block/standard-site-publication": { type: "string", cardinality: "one", }, "standard-site-publication/show-publication-theme": { type: "boolean", cardinality: "one", }, "block/math": { type: "string", cardinality: "one", }, "block/code": { type: "string", cardinality: "one", }, "block/code-language": { type: "string", cardinality: "one", }, "block/list-style": { type: "list-style-union", cardinality: "one", }, "block/list-number": { type: "number", cardinality: "one", }, "block/footnote": { type: "ordered-reference", cardinality: "many", }, "block/comment": { type: "ordered-reference", cardinality: "many", },} as const;
// Comments are authored by authenticated users; their facts carry an// author_did so the server can gate writes to the comment's author.// Comment content is stored as a YJS doc in a "block/text" fact on the// comment entity, like footnotes.const CommentAttributes = { "comment/reply": { type: "ordered-reference", cardinality: "many", }, "comment/author": { type: "string", cardinality: "one", }, "comment/created-at": { type: "string", cardinality: "one", }, // Snapshot of the anchor range in the block's text at creation time. The // live anchor is the comment mark in the block's YJS doc, which moves with // edits; these are kept as a fallback record of where the comment started. "comment/anchor-start": { type: "number", cardinality: "one", }, "comment/anchor-end": { type: "number", cardinality: "one", },} as const;
const MailboxAttributes = { "mailbox/draft": { type: "reference", cardinality: "one", }, "mailbox/archive": { type: "reference", cardinality: "one", }, "mailbox/subscriber-count": { type: "number", cardinality: "one", },} as const;
const LinkBlockAttributes = { "link/preview": { type: "image", cardinality: "one", }, "link/url": { type: "string", cardinality: "one", }, "link/description": { type: "string", cardinality: "one", }, "link/title": { type: "string", cardinality: "one", },} as const;
const EmbedBlockAttributes = { "embed/url": { type: "string", cardinality: "one", }, "embed/height": { type: "number", cardinality: "one", }, "embed/aspect-ratio": { type: "string", cardinality: "one", },} as const;
const BlueskyPostBlockAttributes = { "bluesky-post/url": { type: "string", cardinality: "one", }, "bluesky-post/host": { type: "string", cardinality: "one", },} as const;
const ButtonBlockAttributes = { "button/text": { type: "string", cardinality: "one", }, "button/url": { type: "string", cardinality: "one", },} as const;
const ImageBlockAttributes = { "image/full-bleed": { type: "boolean", cardinality: "one", }, "image/alt": { type: "string", cardinality: "one", }, // Original filename, shown in the gallery's Edit Images list. "image/name": { type: "string", cardinality: "one", },} as const;
const GalleryBlockAttributes = { // Child image entities, each carrying their own block/image, image/alt and // image/name facts — mirrors poll/options. "gallery/image": { type: "ordered-reference", cardinality: "many", }, "gallery/format": { type: "gallery-format-union", cardinality: "one", }, "gallery/gap": { type: "number", cardinality: "one", }, // Max width per image in grid view (px); drives how many columns fit. "gallery/max-width": { type: "number", cardinality: "one", },} as const;
const PollBlockAttributes = { "poll/options": { type: "ordered-reference", cardinality: "many", }, "poll-option/name": { type: "string", cardinality: "one", },} as const;
const PostsListBlockAttributes = { "posts-list/view": { type: "posts-list-view-union", cardinality: "one", }, "posts-list/highlight-first-post": { type: "boolean", cardinality: "one", }, "posts-list/filter-tag": { type: "string", cardinality: "many", }, "posts-list/limit": { type: "number", cardinality: "one", },} as const;
const ThemeAttributes = { "theme/heading-font": { type: "string", cardinality: "one", }, "theme/body-font": { type: "string", cardinality: "one", }, "theme/page-leaflet-watermark": { type: "boolean", cardinality: "one", }, "theme/page-width": { type: "number", cardinality: "one", }, "theme/page-background": { type: "color", cardinality: "one", }, "theme/background-image": { type: "image", cardinality: "one", }, "theme/background-image-repeat": { type: "number", cardinality: "one", }, "theme/wordmark-image": { type: "image", cardinality: "one", }, "theme/wordmark-width": { type: "number", cardinality: "one", }, "theme/card-background": { type: "color", cardinality: "one", }, "theme/card-background-image": { type: "image", cardinality: "one", }, "theme/card-background-image-repeat": { type: "number", cardinality: "one", }, "theme/card-background-image-opacity": { type: "number", cardinality: "one", }, "theme/card-border-hidden": { type: "boolean", cardinality: "one", }, "theme/primary": { type: "color", cardinality: "one", }, "theme/accent-background": { type: "color", cardinality: "one", }, "theme/accent-text": { type: "color", cardinality: "one", }, "theme/highlight-1": { type: "color", cardinality: "one", }, "theme/highlight-2": { type: "color", cardinality: "one", }, "theme/highlight-3": { type: "color", cardinality: "one", }, "theme/code-theme": { type: "string", cardinality: "one", },} as const;
export const Attributes = { ...RootAttributes, ...PageAttributes, ...BlockAttributes, ...CommentAttributes, ...LinkBlockAttributes, ...ThemeAttributes, ...MailboxAttributes, ...EmbedBlockAttributes, ...BlueskyPostBlockAttributes, ...ButtonBlockAttributes, ...ImageBlockAttributes, ...GalleryBlockAttributes, ...PollBlockAttributes, ...PostsListBlockAttributes,};export type Attributes = typeof Attributes;export type Attribute = keyof Attributes;export type Data<A extends keyof typeof Attributes> = { text: { type: "text"; value: string }; string: { type: "string"; value: string }; "spatial-reference": { type: "spatial-reference"; position: { x: number; y: number }; value: string; }; "date-time": { type: "date-time"; value: string; originalTimezone: string; dateOnly?: boolean; }; "ordered-reference": { type: "ordered-reference"; position: string; value: string; }; "bluesky-post": { type: "bluesky-post"; value: DeepAsReadonlyJSONValue< AppBskyFeedGetPostThread.OutputSchema["thread"] >; }; image: { type: "image"; fallback: string; src: string; height: number; width: number; local?: string; }; boolean: { type: "boolean"; value: boolean; }; number: { type: "number"; value: number; }; awareness: { type: "awareness"; value: string; }; reference: { type: "reference"; value: string }; "text-alignment-type-union": { type: "text-alignment-type-union"; value: "right" | "left" | "center" | "justify"; }; "text-size-union": { type: "text-size-union"; value: "default" | "small" | "large"; }; "page-type-union": { type: "page-type-union"; value: "doc" | "canvas" }; "block-type-union": { type: "block-type-union"; value: | "datetime" | "rsvp" | "text" | "image" | "card" | "heading" | "link" | "mailbox" | "embed" | "button" | "poll" | "bluesky-post" | "standard-site-post" | "standard-site-publication" | "math" | "code" | "blockquote" | "horizontal-rule" | "members-only-delimiter" | "posts-list" | "signup" | "image-gallery"; }; "canvas-pattern-union": { type: "canvas-pattern-union"; value: "dot" | "grid" | "plain"; }; "list-style-union": { type: "list-style-union"; value: "ordered" | "unordered"; }; "gallery-format-union": { type: "gallery-format-union"; value: "grid" | "carousel" | "strip"; }; "posts-list-view-union": { type: "posts-list-view-union"; value: "small" | "medium"; }; "standard-site-post-size-union": { type: "standard-site-post-size-union"; value: "large" | "medium" | "small"; }; color: { type: "color"; value: string };}[(typeof Attributes)[A]["type"]];export type FilterAttributes<F extends Partial<Attributes[keyof Attributes]>> = { [A in keyof Attributes as Attributes[A] extends F ? A : never]: Attributes[A]; };