@ewanc26/svelte-standard-site 0.2.3 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ActionBar.svelte +85 -0
- package/dist/components/ActionBar.svelte.d.ts +13 -0
- package/dist/components/Avatar.svelte +104 -0
- package/dist/components/Avatar.svelte.d.ts +19 -0
- package/dist/components/Comment.svelte +172 -0
- package/dist/components/Comment.svelte.d.ts +22 -0
- package/dist/components/CommentsSection.svelte +89 -0
- package/dist/components/DocumentCard.svelte +126 -56
- package/dist/components/DocumentCard.svelte.d.ts +51 -0
- package/dist/components/Footnotes.svelte +72 -0
- package/dist/components/Footnotes.svelte.d.ts +13 -0
- package/dist/components/RecommendButton.svelte +153 -0
- package/dist/components/RecommendButton.svelte.d.ts +17 -0
- package/dist/components/ThemeProvider.svelte +92 -0
- package/dist/components/ThemeProvider.svelte.d.ts +13 -0
- package/dist/components/Toast.svelte +177 -0
- package/dist/components/Toast.svelte.d.ts +32 -0
- package/dist/components/Watermark.svelte +100 -0
- package/dist/components/Watermark.svelte.d.ts +17 -0
- package/dist/components/common/ThemedCard.svelte +15 -15
- package/dist/components/common/ThemedCard.svelte.d.ts +5 -0
- package/dist/components/document/BlockRenderer.svelte +3 -0
- package/dist/components/document/DocumentRenderer.svelte +41 -1
- package/dist/components/document/RichText.svelte +87 -2
- package/dist/components/document/RichText.svelte.d.ts +2 -0
- package/dist/components/document/blocks/OrderedListBlock.svelte +152 -0
- package/dist/components/document/blocks/UnorderedListBlock.svelte +1 -1
- package/dist/components/index.d.ts +28 -0
- package/dist/components/index.js +30 -0
- package/dist/index.d.ts +5 -4
- package/dist/index.js +6 -4
- package/dist/publisher.d.ts +73 -0
- package/dist/publisher.js +185 -0
- package/dist/schemas.d.ts +1162 -2
- package/dist/schemas.js +316 -0
- package/dist/types.d.ts +393 -2
- package/dist/types.js +1 -1
- package/dist/utils/native-comments.d.ts +68 -0
- package/dist/utils/native-comments.js +149 -0
- package/dist/utils/theme-helpers.d.ts +41 -1
- package/dist/utils/theme-helpers.js +98 -1
- package/dist/utils/theme.d.ts +48 -1
- package/dist/utils/theme.js +158 -0
- package/package.json +20 -20
- package/src/lib/components/ActionBar.svelte +85 -0
- package/src/lib/components/Avatar.svelte +104 -0
- package/src/lib/components/Comment.svelte +172 -0
- package/src/lib/components/CommentsSection.svelte +89 -0
- package/src/lib/components/DocumentCard.svelte +126 -56
- package/src/lib/components/Footnotes.svelte +72 -0
- package/src/lib/components/RecommendButton.svelte +153 -0
- package/src/lib/components/ThemeProvider.svelte +92 -0
- package/src/lib/components/Toast.svelte +177 -0
- package/src/lib/components/Watermark.svelte +100 -0
- package/src/lib/components/common/ThemedCard.svelte +15 -15
- package/src/lib/components/document/BlockRenderer.svelte +3 -0
- package/src/lib/components/document/DocumentRenderer.svelte +41 -1
- package/src/lib/components/document/RichText.svelte +87 -2
- package/src/lib/components/document/blocks/OrderedListBlock.svelte +152 -0
- package/src/lib/components/document/blocks/UnorderedListBlock.svelte +1 -1
- package/src/lib/components/index.ts +32 -0
- package/src/lib/index.ts +119 -5
- package/src/lib/publisher.ts +251 -0
- package/src/lib/schemas.ts +411 -0
- package/src/lib/types.ts +506 -2
- package/src/lib/utils/native-comments.ts +197 -0
- package/src/lib/utils/theme-helpers.ts +136 -3
- package/src/lib/utils/theme.ts +189 -1
- package/dist/components/document/blocks/UnorderedListBlock.svelte.d.ts +0 -9
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Core types for site.standard.* lexicons
|
|
2
|
+
* Core types for site.standard.* and pub.leaflet.* lexicons
|
|
3
3
|
*/
|
|
4
4
|
/**
|
|
5
5
|
* AT Protocol blob reference
|
|
@@ -27,6 +27,28 @@ export interface RGBColor {
|
|
|
27
27
|
g: number;
|
|
28
28
|
b: number;
|
|
29
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* RGBA Color (with alpha)
|
|
32
|
+
*/
|
|
33
|
+
export interface RGBAColor {
|
|
34
|
+
r: number;
|
|
35
|
+
g: number;
|
|
36
|
+
b: number;
|
|
37
|
+
a: number;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Color union (RGB or RGBA)
|
|
41
|
+
*/
|
|
42
|
+
export type Color = RGBColor | RGBAColor;
|
|
43
|
+
/**
|
|
44
|
+
* Background image configuration
|
|
45
|
+
*/
|
|
46
|
+
export interface BackgroundImage {
|
|
47
|
+
$type?: 'pub.leaflet.theme.backgroundImage';
|
|
48
|
+
url: string;
|
|
49
|
+
opacity?: number;
|
|
50
|
+
blur?: number;
|
|
51
|
+
}
|
|
30
52
|
/**
|
|
31
53
|
* Basic theme for publications
|
|
32
54
|
*/
|
|
@@ -37,6 +59,22 @@ export interface BasicTheme {
|
|
|
37
59
|
accent: RGBColor;
|
|
38
60
|
accentForeground: RGBColor;
|
|
39
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Extended theme for publications (pub.leaflet.publication#theme)
|
|
64
|
+
*/
|
|
65
|
+
export interface ExtendedTheme {
|
|
66
|
+
$type?: 'pub.leaflet.theme';
|
|
67
|
+
backgroundColor?: Color;
|
|
68
|
+
pageBackground?: Color;
|
|
69
|
+
showPageBackground?: boolean;
|
|
70
|
+
primary?: Color;
|
|
71
|
+
accentBackground?: Color;
|
|
72
|
+
accentText?: Color;
|
|
73
|
+
headingFont?: string;
|
|
74
|
+
bodyFont?: string;
|
|
75
|
+
pageWidth?: number;
|
|
76
|
+
backgroundImage?: BackgroundImage;
|
|
77
|
+
}
|
|
40
78
|
/**
|
|
41
79
|
* Publication preferences
|
|
42
80
|
*/
|
|
@@ -57,6 +95,7 @@ export interface Publication {
|
|
|
57
95
|
icon?: string;
|
|
58
96
|
description?: string;
|
|
59
97
|
basicTheme?: BasicTheme;
|
|
98
|
+
theme?: ExtendedTheme;
|
|
60
99
|
preferences?: PublicationPreferences;
|
|
61
100
|
}
|
|
62
101
|
/**
|
|
@@ -69,14 +108,366 @@ export interface Document {
|
|
|
69
108
|
path?: string;
|
|
70
109
|
description?: string;
|
|
71
110
|
coverImage?: string;
|
|
72
|
-
content?:
|
|
111
|
+
content?: Content;
|
|
73
112
|
textContent?: string;
|
|
74
113
|
bskyPostRef?: StrongRef;
|
|
75
114
|
tags?: string[];
|
|
76
115
|
publishedAt: string;
|
|
77
116
|
updatedAt?: string;
|
|
117
|
+
theme?: ExtendedTheme;
|
|
78
118
|
preferences?: PublicationPreferences;
|
|
79
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Byte slice for facet index
|
|
122
|
+
*/
|
|
123
|
+
export interface ByteSlice {
|
|
124
|
+
byteStart: number;
|
|
125
|
+
byteEnd: number;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Link facet feature
|
|
129
|
+
*/
|
|
130
|
+
export interface LinkFeature {
|
|
131
|
+
$type: 'pub.leaflet.richtext.facet#link';
|
|
132
|
+
uri: string;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* DID Mention facet feature
|
|
136
|
+
*/
|
|
137
|
+
export interface DidMentionFeature {
|
|
138
|
+
$type: 'pub.leaflet.richtext.facet#didMention';
|
|
139
|
+
did: string;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* AT URI Mention facet feature
|
|
143
|
+
*/
|
|
144
|
+
export interface AtMentionFeature {
|
|
145
|
+
$type: 'pub.leaflet.richtext.facet#atMention';
|
|
146
|
+
atURI: string;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Code facet feature (inline code)
|
|
150
|
+
*/
|
|
151
|
+
export interface CodeFeature {
|
|
152
|
+
$type: 'pub.leaflet.richtext.facet#code';
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Highlight facet feature
|
|
156
|
+
*/
|
|
157
|
+
export interface HighlightFeature {
|
|
158
|
+
$type: 'pub.leaflet.richtext.facet#highlight';
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Underline facet feature
|
|
162
|
+
*/
|
|
163
|
+
export interface UnderlineFeature {
|
|
164
|
+
$type: 'pub.leaflet.richtext.facet#underline';
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Strikethrough facet feature
|
|
168
|
+
*/
|
|
169
|
+
export interface StrikethroughFeature {
|
|
170
|
+
$type: 'pub.leaflet.richtext.facet#strikethrough';
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Bold facet feature
|
|
174
|
+
*/
|
|
175
|
+
export interface BoldFeature {
|
|
176
|
+
$type: 'pub.leaflet.richtext.facet#bold';
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Italic facet feature
|
|
180
|
+
*/
|
|
181
|
+
export interface ItalicFeature {
|
|
182
|
+
$type: 'pub.leaflet.richtext.facet#italic';
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* ID facet feature (for anchor links)
|
|
186
|
+
*/
|
|
187
|
+
export interface IdFeature {
|
|
188
|
+
$type: 'pub.leaflet.richtext.facet#id';
|
|
189
|
+
id: string;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Footnote facet feature
|
|
193
|
+
*/
|
|
194
|
+
export interface FootnoteFeature {
|
|
195
|
+
$type: 'pub.leaflet.richtext.facet#footnote';
|
|
196
|
+
footnoteId: string;
|
|
197
|
+
contentPlaintext: string;
|
|
198
|
+
contentFacets?: Facet[];
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Facet feature union
|
|
202
|
+
*/
|
|
203
|
+
export type FacetFeature = LinkFeature | DidMentionFeature | AtMentionFeature | CodeFeature | HighlightFeature | UnderlineFeature | StrikethroughFeature | BoldFeature | ItalicFeature | IdFeature | FootnoteFeature;
|
|
204
|
+
/**
|
|
205
|
+
* Rich Text Facet
|
|
206
|
+
*/
|
|
207
|
+
export interface Facet {
|
|
208
|
+
index: ByteSlice;
|
|
209
|
+
features: FacetFeature[];
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Text Block
|
|
213
|
+
*/
|
|
214
|
+
export interface TextBlock {
|
|
215
|
+
$type: 'pub.leaflet.blocks.text';
|
|
216
|
+
plaintext: string;
|
|
217
|
+
textSize?: 'default' | 'small' | 'large';
|
|
218
|
+
facets?: Facet[];
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Header Block
|
|
222
|
+
*/
|
|
223
|
+
export interface HeaderBlock {
|
|
224
|
+
$type: 'pub.leaflet.blocks.header';
|
|
225
|
+
plaintext: string;
|
|
226
|
+
level?: number;
|
|
227
|
+
facets?: Facet[];
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Blockquote Block
|
|
231
|
+
*/
|
|
232
|
+
export interface BlockquoteBlock {
|
|
233
|
+
$type: 'pub.leaflet.blocks.blockquote';
|
|
234
|
+
plaintext: string;
|
|
235
|
+
facets?: Facet[];
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Image Block
|
|
239
|
+
*/
|
|
240
|
+
export interface ImageBlock {
|
|
241
|
+
$type: 'pub.leaflet.blocks.image';
|
|
242
|
+
image: AtProtoBlob;
|
|
243
|
+
alt?: string;
|
|
244
|
+
aspectRatio?: {
|
|
245
|
+
width: number;
|
|
246
|
+
height: number;
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Code Block
|
|
251
|
+
*/
|
|
252
|
+
export interface CodeBlock {
|
|
253
|
+
$type: 'pub.leaflet.blocks.code';
|
|
254
|
+
code: string;
|
|
255
|
+
language?: string;
|
|
256
|
+
filename?: string;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Math Block
|
|
260
|
+
*/
|
|
261
|
+
export interface MathBlock {
|
|
262
|
+
$type: 'pub.leaflet.blocks.math';
|
|
263
|
+
tex: string;
|
|
264
|
+
display?: boolean;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Ordered List Item
|
|
268
|
+
*/
|
|
269
|
+
export interface OrderedListItem {
|
|
270
|
+
content?: TextBlock | HeaderBlock | ImageBlock;
|
|
271
|
+
checked?: boolean;
|
|
272
|
+
children?: OrderedListItem[];
|
|
273
|
+
unorderedListChildren?: UnorderedListBlock;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Ordered List Block
|
|
277
|
+
*/
|
|
278
|
+
export interface OrderedListBlock {
|
|
279
|
+
$type: 'pub.leaflet.blocks.orderedList';
|
|
280
|
+
children: OrderedListItem[];
|
|
281
|
+
startIndex?: number;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Unordered List Item
|
|
285
|
+
*/
|
|
286
|
+
export interface UnorderedListItem {
|
|
287
|
+
content?: TextBlock | HeaderBlock | ImageBlock;
|
|
288
|
+
children?: UnorderedListItem[];
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Unordered List Block
|
|
292
|
+
*/
|
|
293
|
+
export interface UnorderedListBlock {
|
|
294
|
+
$type: 'pub.leaflet.blocks.unorderedList';
|
|
295
|
+
children: UnorderedListItem[];
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Horizontal Rule Block
|
|
299
|
+
*/
|
|
300
|
+
export interface HorizontalRuleBlock {
|
|
301
|
+
$type: 'pub.leaflet.blocks.horizontalRule';
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Iframe Block
|
|
305
|
+
*/
|
|
306
|
+
export interface IframeBlock {
|
|
307
|
+
$type: 'pub.leaflet.blocks.iframe';
|
|
308
|
+
src: string;
|
|
309
|
+
title?: string;
|
|
310
|
+
width?: number;
|
|
311
|
+
height?: number;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Website Embed Block
|
|
315
|
+
*/
|
|
316
|
+
export interface WebsiteBlock {
|
|
317
|
+
$type: 'pub.leaflet.blocks.website';
|
|
318
|
+
url: string;
|
|
319
|
+
title?: string;
|
|
320
|
+
description?: string;
|
|
321
|
+
image?: AtProtoBlob;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Button Block
|
|
325
|
+
*/
|
|
326
|
+
export interface ButtonBlock {
|
|
327
|
+
$type: 'pub.leaflet.blocks.button';
|
|
328
|
+
text: string;
|
|
329
|
+
href: string;
|
|
330
|
+
variant?: 'primary' | 'secondary' | 'outline';
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Bluesky Post Block
|
|
334
|
+
*/
|
|
335
|
+
export interface BskyPostBlock {
|
|
336
|
+
$type: 'pub.leaflet.blocks.bskyPost';
|
|
337
|
+
uri: string;
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Poll Block
|
|
341
|
+
*/
|
|
342
|
+
export interface PollBlock {
|
|
343
|
+
$type: 'pub.leaflet.blocks.poll';
|
|
344
|
+
question: string;
|
|
345
|
+
options: Array<{
|
|
346
|
+
text: string;
|
|
347
|
+
votes?: number;
|
|
348
|
+
}>;
|
|
349
|
+
endsAt?: string;
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Page Block (internal page reference)
|
|
353
|
+
*/
|
|
354
|
+
export interface PageBlock {
|
|
355
|
+
$type: 'pub.leaflet.blocks.page';
|
|
356
|
+
pageId: string;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Block union type
|
|
360
|
+
*/
|
|
361
|
+
export type Block = TextBlock | HeaderBlock | BlockquoteBlock | ImageBlock | CodeBlock | MathBlock | OrderedListBlock | UnorderedListBlock | HorizontalRuleBlock | IframeBlock | WebsiteBlock | ButtonBlock | BskyPostBlock | PollBlock | PageBlock;
|
|
362
|
+
/**
|
|
363
|
+
* Position for quotes
|
|
364
|
+
*/
|
|
365
|
+
export interface Position {
|
|
366
|
+
block: number[];
|
|
367
|
+
offset: number;
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Quote reference
|
|
371
|
+
*/
|
|
372
|
+
export interface Quote {
|
|
373
|
+
start: Position;
|
|
374
|
+
end: Position;
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Linear Document Page Block Wrapper
|
|
378
|
+
*/
|
|
379
|
+
export interface LinearDocumentBlockWrapper {
|
|
380
|
+
$type: 'pub.leaflet.pages.linearDocument#block';
|
|
381
|
+
block: Block;
|
|
382
|
+
alignment?: '#textAlignLeft' | '#textAlignCenter' | '#textAlignRight' | '#textAlignJustify';
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Linear Document Page
|
|
386
|
+
*/
|
|
387
|
+
export interface LinearDocumentPage {
|
|
388
|
+
$type: 'pub.leaflet.pages.linearDocument';
|
|
389
|
+
id?: string;
|
|
390
|
+
blocks: LinearDocumentBlockWrapper[];
|
|
391
|
+
quote?: Quote;
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Canvas Page Block Wrapper
|
|
395
|
+
*/
|
|
396
|
+
export interface CanvasBlockWrapper {
|
|
397
|
+
$type: 'pub.leaflet.pages.canvas#block';
|
|
398
|
+
block: Block;
|
|
399
|
+
x: number;
|
|
400
|
+
y: number;
|
|
401
|
+
width: number;
|
|
402
|
+
height?: number;
|
|
403
|
+
rotation?: number;
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Canvas Page
|
|
407
|
+
*/
|
|
408
|
+
export interface CanvasPage {
|
|
409
|
+
$type: 'pub.leaflet.pages.canvas';
|
|
410
|
+
id?: string;
|
|
411
|
+
blocks: CanvasBlockWrapper[];
|
|
412
|
+
quote?: Quote;
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Content (pub.leaflet.content)
|
|
416
|
+
*/
|
|
417
|
+
export interface Content {
|
|
418
|
+
$type: 'pub.leaflet.content';
|
|
419
|
+
pages: (LinearDocumentPage | CanvasPage)[];
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Linear Document Quote (for comment attachments)
|
|
423
|
+
*/
|
|
424
|
+
export interface LinearDocumentQuote {
|
|
425
|
+
$type?: 'pub.leaflet.comment#linearDocumentQuote';
|
|
426
|
+
document: string;
|
|
427
|
+
quote?: Quote;
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Comment Reply Reference
|
|
431
|
+
*/
|
|
432
|
+
export interface CommentReplyRef {
|
|
433
|
+
$type?: 'pub.leaflet.comment#replyRef';
|
|
434
|
+
parent: string;
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Comment record
|
|
438
|
+
*/
|
|
439
|
+
export interface CommentRecord {
|
|
440
|
+
$type: 'pub.leaflet.comment';
|
|
441
|
+
subject: string;
|
|
442
|
+
plaintext: string;
|
|
443
|
+
createdAt: string;
|
|
444
|
+
reply?: CommentReplyRef;
|
|
445
|
+
facets?: Facet[];
|
|
446
|
+
onPage?: string;
|
|
447
|
+
attachment?: LinearDocumentQuote;
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Recommend record
|
|
451
|
+
*/
|
|
452
|
+
export interface RecommendRecord {
|
|
453
|
+
$type: 'pub.leaflet.interactions.recommend';
|
|
454
|
+
subject: string;
|
|
455
|
+
createdAt: string;
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* Subscription record (site.standard.graph.subscription)
|
|
459
|
+
*/
|
|
460
|
+
export interface SubscriptionRecord {
|
|
461
|
+
$type: 'site.standard.graph.subscription';
|
|
462
|
+
publication: string;
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Leaflet Subscription record (pub.leaflet.graph.subscription)
|
|
466
|
+
*/
|
|
467
|
+
export interface LeafletSubscriptionRecord {
|
|
468
|
+
$type: 'pub.leaflet.graph.subscription';
|
|
469
|
+
publication: string;
|
|
470
|
+
}
|
|
80
471
|
/**
|
|
81
472
|
* AT Protocol record response
|
|
82
473
|
*/
|
package/dist/types.js
CHANGED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native Comments utilities for pub.leaflet.comment records
|
|
3
|
+
*/
|
|
4
|
+
import type { CommentRecord, Facet, LinearDocumentQuote } from '../types.js';
|
|
5
|
+
/** Collection name for comments */
|
|
6
|
+
export declare const COMMENTS_COLLECTION = "pub.leaflet.comment";
|
|
7
|
+
/**
|
|
8
|
+
* Create a comment record
|
|
9
|
+
*/
|
|
10
|
+
export declare function createCommentRecord(params: {
|
|
11
|
+
subject: string;
|
|
12
|
+
plaintext: string;
|
|
13
|
+
reply?: {
|
|
14
|
+
parent: string;
|
|
15
|
+
};
|
|
16
|
+
facets?: Facet[];
|
|
17
|
+
onPage?: string;
|
|
18
|
+
attachment?: LinearDocumentQuote;
|
|
19
|
+
}): CommentRecord;
|
|
20
|
+
/**
|
|
21
|
+
* Parse a comment AT-URI to extract components
|
|
22
|
+
*/
|
|
23
|
+
export declare function parseCommentUri(uri: string): {
|
|
24
|
+
did: string;
|
|
25
|
+
collection: string;
|
|
26
|
+
rkey: string;
|
|
27
|
+
} | null;
|
|
28
|
+
/**
|
|
29
|
+
* Build a comment AT-URI
|
|
30
|
+
*/
|
|
31
|
+
export declare function buildCommentUri(did: string, rkey: string): string;
|
|
32
|
+
/**
|
|
33
|
+
* Fetch comments for a document
|
|
34
|
+
*/
|
|
35
|
+
export declare function fetchComments(subject: string, service?: string): Promise<Array<CommentRecord & {
|
|
36
|
+
uri: string;
|
|
37
|
+
cid: string;
|
|
38
|
+
author: {
|
|
39
|
+
did: string;
|
|
40
|
+
};
|
|
41
|
+
}>>;
|
|
42
|
+
/**
|
|
43
|
+
* Organize comments into a threaded structure
|
|
44
|
+
*/
|
|
45
|
+
export declare function organizeCommentsIntoThreads(comments: Array<CommentRecord & {
|
|
46
|
+
uri: string;
|
|
47
|
+
cid: string;
|
|
48
|
+
author: {
|
|
49
|
+
did: string;
|
|
50
|
+
};
|
|
51
|
+
}>): Array<CommentRecord & {
|
|
52
|
+
uri: string;
|
|
53
|
+
cid: string;
|
|
54
|
+
author: {
|
|
55
|
+
did: string;
|
|
56
|
+
};
|
|
57
|
+
replies: any[];
|
|
58
|
+
}>;
|
|
59
|
+
/**
|
|
60
|
+
* Count total comments in a thread
|
|
61
|
+
*/
|
|
62
|
+
export declare function countThreadComments(thread: {
|
|
63
|
+
replies: any[];
|
|
64
|
+
}): number;
|
|
65
|
+
/**
|
|
66
|
+
* Get quoted text from a document
|
|
67
|
+
*/
|
|
68
|
+
export declare function extractQuotedText(document: any, quote: LinearDocumentQuote['quote']): string | null;
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native Comments utilities for pub.leaflet.comment records
|
|
3
|
+
*/
|
|
4
|
+
/** Collection name for comments */
|
|
5
|
+
export const COMMENTS_COLLECTION = 'pub.leaflet.comment';
|
|
6
|
+
/**
|
|
7
|
+
* Create a comment record
|
|
8
|
+
*/
|
|
9
|
+
export function createCommentRecord(params) {
|
|
10
|
+
const record = {
|
|
11
|
+
$type: 'pub.leaflet.comment',
|
|
12
|
+
subject: params.subject,
|
|
13
|
+
plaintext: params.plaintext,
|
|
14
|
+
createdAt: new Date().toISOString()
|
|
15
|
+
};
|
|
16
|
+
if (params.reply) {
|
|
17
|
+
record.reply = {
|
|
18
|
+
$type: 'pub.leaflet.comment#replyRef',
|
|
19
|
+
parent: params.reply.parent
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
if (params.facets) {
|
|
23
|
+
record.facets = params.facets;
|
|
24
|
+
}
|
|
25
|
+
if (params.onPage) {
|
|
26
|
+
record.onPage = params.onPage;
|
|
27
|
+
}
|
|
28
|
+
if (params.attachment) {
|
|
29
|
+
record.attachment = {
|
|
30
|
+
$type: 'pub.leaflet.comment#linearDocumentQuote',
|
|
31
|
+
...params.attachment
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
return record;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Parse a comment AT-URI to extract components
|
|
38
|
+
*/
|
|
39
|
+
export function parseCommentUri(uri) {
|
|
40
|
+
const match = uri.match(/^at:\/\/([^/]+)\/([^/]+)\/([^/]+)$/);
|
|
41
|
+
if (!match)
|
|
42
|
+
return null;
|
|
43
|
+
return {
|
|
44
|
+
did: match[1],
|
|
45
|
+
collection: match[2],
|
|
46
|
+
rkey: match[3]
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Build a comment AT-URI
|
|
51
|
+
*/
|
|
52
|
+
export function buildCommentUri(did, rkey) {
|
|
53
|
+
return `at://${did}/${COMMENTS_COLLECTION}/${rkey}`;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Fetch comments for a document
|
|
57
|
+
*/
|
|
58
|
+
export async function fetchComments(subject, service = 'https://public.api.bsky.app') {
|
|
59
|
+
try {
|
|
60
|
+
const response = await fetch(`${service}/xrpc/com.atproto.repo.listRecords?collection=${COMMENTS_COLLECTION}&limit=100`);
|
|
61
|
+
if (!response.ok) {
|
|
62
|
+
throw new Error(`Failed to fetch comments: ${response.status}`);
|
|
63
|
+
}
|
|
64
|
+
const data = await response.json();
|
|
65
|
+
// Filter comments for this subject
|
|
66
|
+
const comments = data.records
|
|
67
|
+
?.filter((record) => record.value?.subject === subject)
|
|
68
|
+
?.map((record) => ({
|
|
69
|
+
...record.value,
|
|
70
|
+
uri: record.uri,
|
|
71
|
+
cid: record.cid,
|
|
72
|
+
author: { did: record.uri.split('/')[2] }
|
|
73
|
+
})) ?? [];
|
|
74
|
+
return comments;
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
console.error('Error fetching comments:', error);
|
|
78
|
+
return [];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Organize comments into a threaded structure
|
|
83
|
+
*/
|
|
84
|
+
export function organizeCommentsIntoThreads(comments) {
|
|
85
|
+
const byId = new Map();
|
|
86
|
+
const rootComments = [];
|
|
87
|
+
// First pass: create all comment objects
|
|
88
|
+
for (const comment of comments) {
|
|
89
|
+
byId.set(comment.uri, { ...comment, replies: [] });
|
|
90
|
+
}
|
|
91
|
+
// Second pass: organize into threads
|
|
92
|
+
for (const comment of comments) {
|
|
93
|
+
const node = byId.get(comment.uri);
|
|
94
|
+
if (!node)
|
|
95
|
+
continue;
|
|
96
|
+
if (comment.reply?.parent) {
|
|
97
|
+
const parent = byId.get(comment.reply.parent);
|
|
98
|
+
if (parent) {
|
|
99
|
+
parent.replies.push(node);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
// Parent not found, treat as root
|
|
103
|
+
rootComments.push(node);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
rootComments.push(node);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// Sort root comments by date (newest first)
|
|
111
|
+
rootComments.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
|
|
112
|
+
return rootComments;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Count total comments in a thread
|
|
116
|
+
*/
|
|
117
|
+
export function countThreadComments(thread) {
|
|
118
|
+
let count = 1;
|
|
119
|
+
for (const reply of thread.replies) {
|
|
120
|
+
count += countThreadComments(reply);
|
|
121
|
+
}
|
|
122
|
+
return count;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Get quoted text from a document
|
|
126
|
+
*/
|
|
127
|
+
export function extractQuotedText(document, quote) {
|
|
128
|
+
if (!quote || !document?.content?.pages)
|
|
129
|
+
return null;
|
|
130
|
+
// Find the linear document page
|
|
131
|
+
const page = document.content.pages.find((p) => quote.start.block.every((b, i) => b === p.id || i === 0));
|
|
132
|
+
if (!page)
|
|
133
|
+
return null;
|
|
134
|
+
// Extract text based on block indices
|
|
135
|
+
const blocks = page.blocks || [];
|
|
136
|
+
const startBlockIndex = quote.start.block[quote.start.block.length - 1];
|
|
137
|
+
const endBlockIndex = quote.end.block[quote.end.block.length - 1];
|
|
138
|
+
if (startBlockIndex === undefined || endBlockIndex === undefined)
|
|
139
|
+
return null;
|
|
140
|
+
// For simplicity, return the text from the first block
|
|
141
|
+
// In a real implementation, you'd handle multi-block quotes
|
|
142
|
+
const startBlock = blocks[startBlockIndex]?.block;
|
|
143
|
+
if (!startBlock)
|
|
144
|
+
return null;
|
|
145
|
+
if (startBlock.plaintext) {
|
|
146
|
+
return startBlock.plaintext.slice(quote.start.offset, quote.end.offset);
|
|
147
|
+
}
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BasicTheme } from '../types.js';
|
|
1
|
+
import type { BasicTheme, ExtendedTheme, BackgroundImage } from '../types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Generate color-mix CSS for theme colors with transparency
|
|
4
4
|
*/
|
|
@@ -28,7 +28,47 @@ export declare function getThemedAccent(hasTheme: boolean, opacity?: number): {
|
|
|
28
28
|
color?: string;
|
|
29
29
|
backgroundColor?: string;
|
|
30
30
|
};
|
|
31
|
+
/**
|
|
32
|
+
* Get theme-aware page background
|
|
33
|
+
*/
|
|
34
|
+
export declare function getThemedPageBackground(hasTheme: boolean, showPageBackground?: boolean): {
|
|
35
|
+
backgroundColor?: string;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Get background image styles
|
|
39
|
+
*/
|
|
40
|
+
export declare function getBackgroundImageStyles(bgImage: BackgroundImage | undefined): {
|
|
41
|
+
backgroundImage?: string;
|
|
42
|
+
backgroundSize?: string;
|
|
43
|
+
backgroundPosition?: string;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Get font styles from theme
|
|
47
|
+
*/
|
|
48
|
+
export declare function getFontStyles(theme: ExtendedTheme | undefined): {
|
|
49
|
+
fontFamily?: string;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Get heading font styles from theme
|
|
53
|
+
*/
|
|
54
|
+
export declare function getHeadingFontStyles(theme: ExtendedTheme | undefined): {
|
|
55
|
+
fontFamily?: string;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Get page width styles from theme
|
|
59
|
+
*/
|
|
60
|
+
export declare function getPageWidthStyles(theme: ExtendedTheme | undefined): {
|
|
61
|
+
maxWidth?: string;
|
|
62
|
+
};
|
|
31
63
|
/**
|
|
32
64
|
* Convert BasicTheme to CSS custom properties
|
|
33
65
|
*/
|
|
34
66
|
export declare function themeToCssVars(theme?: BasicTheme): Record<string, string>;
|
|
67
|
+
/**
|
|
68
|
+
* Convert ExtendedTheme to CSS custom properties
|
|
69
|
+
*/
|
|
70
|
+
export declare function extendedThemeToCssVars(theme?: ExtendedTheme): Record<string, string>;
|
|
71
|
+
/**
|
|
72
|
+
* Convert any theme to CSS custom properties
|
|
73
|
+
*/
|
|
74
|
+
export declare function anyThemeToCssVars(theme?: BasicTheme | ExtendedTheme): Record<string, string>;
|