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 "block/footnote": {
111 type: "ordered-reference",
112 cardinality: "many",
113 },
114} as const;
115
116const MailboxAttributes = {
117 "mailbox/draft": {
118 type: "reference",
119 cardinality: "one",
120 },
121 "mailbox/archive": {
122 type: "reference",
123 cardinality: "one",
124 },
125 "mailbox/subscriber-count": {
126 type: "number",
127 cardinality: "one",
128 },
129} as const;
130
131const LinkBlockAttributes = {
132 "link/preview": {
133 type: "image",
134 cardinality: "one",
135 },
136 "link/url": {
137 type: "string",
138 cardinality: "one",
139 },
140 "link/description": {
141 type: "string",
142 cardinality: "one",
143 },
144 "link/title": {
145 type: "string",
146 cardinality: "one",
147 },
148} as const;
149
150const EmbedBlockAttributes = {
151 "embed/url": {
152 type: "string",
153 cardinality: "one",
154 },
155 "embed/height": {
156 type: "number",
157 cardinality: "one",
158 },
159} as const;
160
161const BlueskyPostBlockAttributes = {
162 "bluesky-post/url": {
163 type: "string",
164 cardinality: "one",
165 },
166 "bluesky-post/host": {
167 type: "string",
168 cardinality: "one",
169 },
170} as const;
171
172const ButtonBlockAttributes = {
173 "button/text": {
174 type: "string",
175 cardinality: "one",
176 },
177 "button/url": {
178 type: "string",
179 cardinality: "one",
180 },
181} as const;
182
183const ImageBlockAttributes = {
184 "image/full-bleed": {
185 type: "boolean",
186 cardinality: "one",
187 },
188 "image/alt": {
189 type: "string",
190 cardinality: "one",
191 },
192} as const;
193
194const PollBlockAttributes = {
195 "poll/options": {
196 type: "ordered-reference",
197 cardinality: "many",
198 },
199 "poll-option/name": {
200 type: "string",
201 cardinality: "one",
202 },
203} as const;
204
205export const ThemeAttributes = {
206 "theme/heading-font": {
207 type: "string",
208 cardinality: "one",
209 },
210 "theme/body-font": {
211 type: "string",
212 cardinality: "one",
213 },
214 "theme/page-leaflet-watermark": {
215 type: "boolean",
216 cardinality: "one",
217 },
218 "theme/page-width": {
219 type: "number",
220 cardinality: "one",
221 },
222 "theme/page-background": {
223 type: "color",
224 cardinality: "one",
225 },
226 "theme/background-image": {
227 type: "image",
228 cardinality: "one",
229 },
230 "theme/background-image-repeat": {
231 type: "number",
232 cardinality: "one",
233 },
234 "theme/card-background": {
235 type: "color",
236 cardinality: "one",
237 },
238 "theme/card-background-image": {
239 type: "image",
240 cardinality: "one",
241 },
242 "theme/card-background-image-repeat": {
243 type: "number",
244 cardinality: "one",
245 },
246 "theme/card-background-image-opacity": {
247 type: "number",
248 cardinality: "one",
249 },
250 "theme/card-border-hidden": {
251 type: "boolean",
252 cardinality: "one",
253 },
254 "theme/primary": {
255 type: "color",
256 cardinality: "one",
257 },
258 "theme/accent-background": {
259 type: "color",
260 cardinality: "one",
261 },
262 "theme/accent-text": {
263 type: "color",
264 cardinality: "one",
265 },
266 "theme/highlight-1": {
267 type: "color",
268 cardinality: "one",
269 },
270 "theme/highlight-2": {
271 type: "color",
272 cardinality: "one",
273 },
274 "theme/highlight-3": {
275 type: "color",
276 cardinality: "one",
277 },
278 "theme/code-theme": {
279 type: "string",
280 cardinality: "one",
281 },
282} as const;
283
284export const Attributes = {
285 ...RootAttributes,
286 ...PageAttributes,
287 ...BlockAttributes,
288 ...LinkBlockAttributes,
289 ...ThemeAttributes,
290 ...MailboxAttributes,
291 ...EmbedBlockAttributes,
292 ...BlueskyPostBlockAttributes,
293 ...ButtonBlockAttributes,
294 ...ImageBlockAttributes,
295 ...PollBlockAttributes,
296};
297export type Attributes = typeof Attributes;
298export type Attribute = keyof Attributes;
299export type Data<A extends keyof typeof Attributes> = {
300 text: { type: "text"; value: string };
301 string: { type: "string"; value: string };
302 "spatial-reference": {
303 type: "spatial-reference";
304 position: { x: number; y: number };
305 value: string;
306 };
307 "date-time": {
308 type: "date-time";
309 value: string;
310 originalTimezone: string;
311 dateOnly?: boolean;
312 };
313 "ordered-reference": {
314 type: "ordered-reference";
315 position: string;
316 value: string;
317 };
318 "bluesky-post": {
319 type: "bluesky-post";
320 value: DeepAsReadonlyJSONValue<
321 AppBskyFeedGetPostThread.OutputSchema["thread"]
322 >;
323 };
324 image: {
325 type: "image";
326 fallback: string;
327 src: string;
328 height: number;
329 width: number;
330 local?: string;
331 };
332 boolean: {
333 type: "boolean";
334 value: boolean;
335 };
336 number: {
337 type: "number";
338 value: number;
339 };
340 awareness: {
341 type: "awareness";
342 value: string;
343 };
344 reference: { type: "reference"; value: string };
345 "text-alignment-type-union": {
346 type: "text-alignment-type-union";
347 value: "right" | "left" | "center" | "justify";
348 };
349 "text-size-union": {
350 type: "text-size-union";
351 value: "default" | "small" | "large";
352 };
353 "page-type-union": { type: "page-type-union"; value: "doc" | "canvas" };
354 "block-type-union": {
355 type: "block-type-union";
356 value:
357 | "datetime"
358 | "rsvp"
359 | "text"
360 | "image"
361 | "card"
362 | "heading"
363 | "link"
364 | "mailbox"
365 | "embed"
366 | "button"
367 | "poll"
368 | "bluesky-post"
369 | "math"
370 | "code"
371 | "blockquote"
372 | "horizontal-rule";
373 };
374 "canvas-pattern-union": {
375 type: "canvas-pattern-union";
376 value: "dot" | "grid" | "plain";
377 };
378 "list-style-union": {
379 type: "list-style-union";
380 value: "ordered" | "unordered";
381 };
382 color: { type: "color"; value: string };
383}[(typeof Attributes)[A]["type"]];
384export type FilterAttributes<F extends Partial<Attributes[keyof Attributes]>> =
385 {
386 [A in keyof Attributes as Attributes[A] extends F
387 ? A
388 : never]: Attributes[A];
389 };