a tool for shared writing and social publishing
1import type { AppBskyFeedGetPostThread } from "@atproto/api";
2import type { DeepAsReadonlyJSONValue } from "./utils";
3
4const RootAttributes = {
5 "root/page": {
6 type: "ordered-reference",
7 cardinality: "many",
8 },
9} as const;
10const PageAttributes = {
11 "card/block": {
12 type: "ordered-reference",
13 cardinality: "many",
14 },
15 "page/type": {
16 type: "page-type-union",
17 cardinality: "one",
18 },
19 "canvas/block": {
20 type: "spatial-reference",
21 cardinality: "many",
22 },
23 "canvas/block/width": {
24 type: "number",
25 cardinality: "one",
26 },
27 "canvas/block/rotation": {
28 type: "number",
29 cardinality: "one",
30 },
31 "canvas/narrow-width": {
32 type: "boolean",
33 cardinality: "one",
34 },
35 "canvas/background-pattern": {
36 type: "canvas-pattern-union",
37 cardinality: "one",
38 },
39} as const;
40
41const BlockAttributes = {
42 "block/type": {
43 type: "block-type-union",
44 cardinality: "one",
45 },
46 "block/is-list": {
47 type: "boolean",
48 cardinality: "one",
49 },
50 "block/is-locked": {
51 type: "boolean",
52 cardinality: "one",
53 },
54 "block/check-list": {
55 type: "boolean",
56 cardinality: "one",
57 },
58 "block/text-alignment": {
59 type: "text-alignment-type-union",
60 cardinality: "one",
61 },
62 "block/date-time": {
63 type: "date-time",
64 cardinality: "one",
65 },
66 "block/text": {
67 type: "text",
68 cardinality: "one",
69 },
70 "block/heading-level": {
71 type: "number",
72 cardinality: "one",
73 },
74 "block/text-size": {
75 type: "text-size-union",
76 cardinality: "one",
77 },
78 "block/image": {
79 type: "image",
80 cardinality: "one",
81 },
82 "block/card": {
83 type: "reference",
84 cardinality: "one",
85 },
86 "block/bluesky-post": {
87 type: "bluesky-post",
88 cardinality: "one",
89 },
90 "block/math": {
91 type: "string",
92 cardinality: "one",
93 },
94 "block/code": {
95 type: "string",
96 cardinality: "one",
97 },
98 "block/code-language": {
99 type: "string",
100 cardinality: "one",
101 },
102 "block/list-style": {
103 type: "list-style-union",
104 cardinality: "one",
105 },
106 "block/list-number": {
107 type: "number",
108 cardinality: "one",
109 },
110} as const;
111
112const MailboxAttributes = {
113 "mailbox/draft": {
114 type: "reference",
115 cardinality: "one",
116 },
117 "mailbox/archive": {
118 type: "reference",
119 cardinality: "one",
120 },
121 "mailbox/subscriber-count": {
122 type: "number",
123 cardinality: "one",
124 },
125} as const;
126
127const LinkBlockAttributes = {
128 "link/preview": {
129 type: "image",
130 cardinality: "one",
131 },
132 "link/url": {
133 type: "string",
134 cardinality: "one",
135 },
136 "link/description": {
137 type: "string",
138 cardinality: "one",
139 },
140 "link/title": {
141 type: "string",
142 cardinality: "one",
143 },
144} as const;
145
146const EmbedBlockAttributes = {
147 "embed/url": {
148 type: "string",
149 cardinality: "one",
150 },
151 "embed/height": {
152 type: "number",
153 cardinality: "one",
154 },
155} as const;
156
157const BlueskyPostBlockAttributes = {
158 "bluesky-post/url": {
159 type: "string",
160 cardinality: "one",
161 },
162 "bluesky-post/host": {
163 type: "string",
164 cardinality: "one",
165 },
166} as const;
167
168const ButtonBlockAttributes = {
169 "button/text": {
170 type: "string",
171 cardinality: "one",
172 },
173 "button/url": {
174 type: "string",
175 cardinality: "one",
176 },
177} as const;
178
179const ImageBlockAttributes = {
180 "image/full-bleed": {
181 type: "boolean",
182 cardinality: "one",
183 },
184 "image/alt": {
185 type: "string",
186 cardinality: "one",
187 },
188} as const;
189
190const PollBlockAttributes = {
191 "poll/options": {
192 type: "ordered-reference",
193 cardinality: "many",
194 },
195 "poll-option/name": {
196 type: "string",
197 cardinality: "one",
198 },
199} as const;
200
201export const ThemeAttributes = {
202 "theme/heading-font": {
203 type: "string",
204 cardinality: "one",
205 },
206 "theme/body-font": {
207 type: "string",
208 cardinality: "one",
209 },
210 "theme/page-leaflet-watermark": {
211 type: "boolean",
212 cardinality: "one",
213 },
214 "theme/page-width": {
215 type: "number",
216 cardinality: "one",
217 },
218 "theme/page-background": {
219 type: "color",
220 cardinality: "one",
221 },
222 "theme/background-image": {
223 type: "image",
224 cardinality: "one",
225 },
226 "theme/background-image-repeat": {
227 type: "number",
228 cardinality: "one",
229 },
230 "theme/card-background": {
231 type: "color",
232 cardinality: "one",
233 },
234 "theme/card-background-image": {
235 type: "image",
236 cardinality: "one",
237 },
238 "theme/card-background-image-repeat": {
239 type: "number",
240 cardinality: "one",
241 },
242 "theme/card-background-image-opacity": {
243 type: "number",
244 cardinality: "one",
245 },
246 "theme/card-border-hidden": {
247 type: "boolean",
248 cardinality: "one",
249 },
250 "theme/primary": {
251 type: "color",
252 cardinality: "one",
253 },
254 "theme/accent-background": {
255 type: "color",
256 cardinality: "one",
257 },
258 "theme/accent-text": {
259 type: "color",
260 cardinality: "one",
261 },
262 "theme/highlight-1": {
263 type: "color",
264 cardinality: "one",
265 },
266 "theme/highlight-2": {
267 type: "color",
268 cardinality: "one",
269 },
270 "theme/highlight-3": {
271 type: "color",
272 cardinality: "one",
273 },
274 "theme/code-theme": {
275 type: "string",
276 cardinality: "one",
277 },
278} as const;
279
280export const Attributes = {
281 ...RootAttributes,
282 ...PageAttributes,
283 ...BlockAttributes,
284 ...LinkBlockAttributes,
285 ...ThemeAttributes,
286 ...MailboxAttributes,
287 ...EmbedBlockAttributes,
288 ...BlueskyPostBlockAttributes,
289 ...ButtonBlockAttributes,
290 ...ImageBlockAttributes,
291 ...PollBlockAttributes,
292};
293export type Attributes = typeof Attributes;
294export type Attribute = keyof Attributes;
295export type Data<A extends keyof typeof Attributes> = {
296 text: { type: "text"; value: string };
297 string: { type: "string"; value: string };
298 "spatial-reference": {
299 type: "spatial-reference";
300 position: { x: number; y: number };
301 value: string;
302 };
303 "date-time": {
304 type: "date-time";
305 value: string;
306 originalTimezone: string;
307 dateOnly?: boolean;
308 };
309 "ordered-reference": {
310 type: "ordered-reference";
311 position: string;
312 value: string;
313 };
314 "bluesky-post": {
315 type: "bluesky-post";
316 value: DeepAsReadonlyJSONValue<
317 AppBskyFeedGetPostThread.OutputSchema["thread"]
318 >;
319 };
320 image: {
321 type: "image";
322 fallback: string;
323 src: string;
324 height: number;
325 width: number;
326 local?: string;
327 };
328 boolean: {
329 type: "boolean";
330 value: boolean;
331 };
332 number: {
333 type: "number";
334 value: number;
335 };
336 awareness: {
337 type: "awareness";
338 value: string;
339 };
340 reference: { type: "reference"; value: string };
341 "text-alignment-type-union": {
342 type: "text-alignment-type-union";
343 value: "right" | "left" | "center" | "justify";
344 };
345 "text-size-union": {
346 type: "text-size-union";
347 value: "default" | "small" | "large";
348 };
349 "page-type-union": { type: "page-type-union"; value: "doc" | "canvas" };
350 "block-type-union": {
351 type: "block-type-union";
352 value:
353 | "datetime"
354 | "rsvp"
355 | "text"
356 | "image"
357 | "card"
358 | "heading"
359 | "link"
360 | "mailbox"
361 | "embed"
362 | "button"
363 | "poll"
364 | "bluesky-post"
365 | "math"
366 | "code"
367 | "blockquote"
368 | "horizontal-rule";
369 };
370 "canvas-pattern-union": {
371 type: "canvas-pattern-union";
372 value: "dot" | "grid" | "plain";
373 };
374 "list-style-union": {
375 type: "list-style-union";
376 value: "ordered" | "unordered";
377 };
378 color: { type: "color"; value: string };
379}[(typeof Attributes)[A]["type"]];
380export type FilterAttributes<F extends Partial<Attributes[keyof Attributes]>> =
381 {
382 [A in keyof Attributes as Attributes[A] extends F
383 ? A
384 : never]: Attributes[A];
385 };