@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.
Files changed (69) hide show
  1. package/dist/components/ActionBar.svelte +85 -0
  2. package/dist/components/ActionBar.svelte.d.ts +13 -0
  3. package/dist/components/Avatar.svelte +104 -0
  4. package/dist/components/Avatar.svelte.d.ts +19 -0
  5. package/dist/components/Comment.svelte +172 -0
  6. package/dist/components/Comment.svelte.d.ts +22 -0
  7. package/dist/components/CommentsSection.svelte +89 -0
  8. package/dist/components/DocumentCard.svelte +126 -56
  9. package/dist/components/DocumentCard.svelte.d.ts +51 -0
  10. package/dist/components/Footnotes.svelte +72 -0
  11. package/dist/components/Footnotes.svelte.d.ts +13 -0
  12. package/dist/components/RecommendButton.svelte +153 -0
  13. package/dist/components/RecommendButton.svelte.d.ts +17 -0
  14. package/dist/components/ThemeProvider.svelte +92 -0
  15. package/dist/components/ThemeProvider.svelte.d.ts +13 -0
  16. package/dist/components/Toast.svelte +177 -0
  17. package/dist/components/Toast.svelte.d.ts +32 -0
  18. package/dist/components/Watermark.svelte +100 -0
  19. package/dist/components/Watermark.svelte.d.ts +17 -0
  20. package/dist/components/common/ThemedCard.svelte +15 -15
  21. package/dist/components/common/ThemedCard.svelte.d.ts +5 -0
  22. package/dist/components/document/BlockRenderer.svelte +3 -0
  23. package/dist/components/document/DocumentRenderer.svelte +41 -1
  24. package/dist/components/document/RichText.svelte +87 -2
  25. package/dist/components/document/RichText.svelte.d.ts +2 -0
  26. package/dist/components/document/blocks/OrderedListBlock.svelte +152 -0
  27. package/dist/components/document/blocks/UnorderedListBlock.svelte +1 -1
  28. package/dist/components/index.d.ts +28 -0
  29. package/dist/components/index.js +30 -0
  30. package/dist/index.d.ts +5 -4
  31. package/dist/index.js +6 -4
  32. package/dist/publisher.d.ts +73 -0
  33. package/dist/publisher.js +185 -0
  34. package/dist/schemas.d.ts +1162 -2
  35. package/dist/schemas.js +316 -0
  36. package/dist/types.d.ts +393 -2
  37. package/dist/types.js +1 -1
  38. package/dist/utils/native-comments.d.ts +68 -0
  39. package/dist/utils/native-comments.js +149 -0
  40. package/dist/utils/theme-helpers.d.ts +41 -1
  41. package/dist/utils/theme-helpers.js +98 -1
  42. package/dist/utils/theme.d.ts +48 -1
  43. package/dist/utils/theme.js +158 -0
  44. package/package.json +20 -20
  45. package/src/lib/components/ActionBar.svelte +85 -0
  46. package/src/lib/components/Avatar.svelte +104 -0
  47. package/src/lib/components/Comment.svelte +172 -0
  48. package/src/lib/components/CommentsSection.svelte +89 -0
  49. package/src/lib/components/DocumentCard.svelte +126 -56
  50. package/src/lib/components/Footnotes.svelte +72 -0
  51. package/src/lib/components/RecommendButton.svelte +153 -0
  52. package/src/lib/components/ThemeProvider.svelte +92 -0
  53. package/src/lib/components/Toast.svelte +177 -0
  54. package/src/lib/components/Watermark.svelte +100 -0
  55. package/src/lib/components/common/ThemedCard.svelte +15 -15
  56. package/src/lib/components/document/BlockRenderer.svelte +3 -0
  57. package/src/lib/components/document/DocumentRenderer.svelte +41 -1
  58. package/src/lib/components/document/RichText.svelte +87 -2
  59. package/src/lib/components/document/blocks/OrderedListBlock.svelte +152 -0
  60. package/src/lib/components/document/blocks/UnorderedListBlock.svelte +1 -1
  61. package/src/lib/components/index.ts +32 -0
  62. package/src/lib/index.ts +119 -5
  63. package/src/lib/publisher.ts +251 -0
  64. package/src/lib/schemas.ts +411 -0
  65. package/src/lib/types.ts +506 -2
  66. package/src/lib/utils/native-comments.ts +197 -0
  67. package/src/lib/utils/theme-helpers.ts +136 -3
  68. package/src/lib/utils/theme.ts +189 -1
  69. package/dist/components/document/blocks/UnorderedListBlock.svelte.d.ts +0 -9
@@ -0,0 +1,152 @@
1
+ <script lang="ts">
2
+ import RichText from '../RichText.svelte';
3
+ import OrderedListBlock from './OrderedListBlock.svelte';
4
+ import UnorderedListBlock from './UnorderedListBlock.svelte';
5
+ import HeaderBlock from './HeaderBlock.svelte';
6
+ import ImageBlock from './ImageBlock.svelte';
7
+
8
+ interface OrderedListContent {
9
+ plaintext: string;
10
+ facets?: any[];
11
+ textSize?: 'default' | 'small' | 'large';
12
+ level?: number;
13
+ image?: {
14
+ $type?: 'blob';
15
+ ref?: { $link: string };
16
+ mimeType?: string;
17
+ size?: number;
18
+ };
19
+ alt?: string;
20
+ aspectRatio?: { width: number; height: number };
21
+ }
22
+
23
+ interface OrderedListItem {
24
+ content?: OrderedListContent;
25
+ checked?: boolean;
26
+ children?: OrderedListItem[];
27
+ unorderedListChildren?: {
28
+ children: Array<{
29
+ content?: { plaintext: string; facets?: any[] };
30
+ children?: OrderedListItem[];
31
+ }>;
32
+ };
33
+ }
34
+
35
+ interface Props {
36
+ block: {
37
+ children: OrderedListItem[];
38
+ startIndex?: number;
39
+ };
40
+ hasTheme?: boolean;
41
+ did?: string;
42
+ pds?: string;
43
+ }
44
+
45
+ const { block, hasTheme = false, did = '', pds = '' }: Props = $props();
46
+
47
+ function isTextContent(content: OrderedListContent): boolean {
48
+ return !!(content?.plaintext && content.level === undefined && !content.image);
49
+ }
50
+
51
+ function isHeaderContent(content: OrderedListContent): boolean {
52
+ return !!(content?.level !== undefined);
53
+ }
54
+
55
+ function isImageContent(content: OrderedListContent): boolean {
56
+ return !!(content?.image);
57
+ }
58
+ </script>
59
+
60
+ <ol class="ordered-list pb-2" start={block.startIndex}>
61
+ {#each block.children as item, i}
62
+ <li class="flex flex-row gap-2 pb-0">
63
+ {#if item.checked !== undefined}
64
+ <!-- Checklist item -->
65
+ <div
66
+ class="checkbox-marker z-1 mx-2 mt-3.5 h-4 w-4 shrink-0 rounded border-2 flex items-center justify-center"
67
+ class:themed={hasTheme}
68
+ class:checked={item.checked}
69
+ >
70
+ {#if item.checked}
71
+ <svg class="h-3 w-3" viewBox="0 0 12 12" fill="currentColor">
72
+ <path d="M10.28 2.28L4.5 8.06 1.72 5.28 1 6l3.5 3.5 6.5-6.5-.72-.72z" />
73
+ </svg>
74
+ {/if}
75
+ </div>
76
+ {:else}
77
+ <!-- Regular numbered item -->
78
+ <div
79
+ class="list-number z-1 mx-2 mt-1 h-6 w-6 shrink-0 flex items-center justify-center text-sm font-medium"
80
+ class:themed={hasTheme}
81
+ >
82
+ {(block.startIndex || 1) + i}
83
+ </div>
84
+ {/if}
85
+
86
+ <div class="flex w-full flex-col">
87
+ {#if item.content}
88
+ <div class="textBlock mt-1 mb-2">
89
+ {#if isTextContent(item.content)}
90
+ <RichText plaintext={item.content.plaintext} facets={item.content.facets} {hasTheme} />
91
+ {:else if isHeaderContent(item.content)}
92
+ <HeaderBlock block={item.content as any} {hasTheme} />
93
+ {:else if isImageContent(item.content)}
94
+ <ImageBlock block={item.content as any} {did} {pds} {hasTheme} />
95
+ {/if}
96
+ </div>
97
+ {/if}
98
+
99
+ {#if item.children && item.children.length > 0}
100
+ <OrderedListBlock block={{ children: item.children }} {hasTheme} {did} {pds} />
101
+ {/if}
102
+
103
+ {#if item.unorderedListChildren && item.unorderedListChildren.children.length > 0}
104
+ <UnorderedListBlock block={{ children: item.unorderedListChildren.children }} {hasTheme} />
105
+ {/if}
106
+ </div>
107
+ </li>
108
+ {/each}
109
+ </ol>
110
+
111
+ <style>
112
+ .ordered-list {
113
+ list-style: none;
114
+ padding-left: 0;
115
+ margin-left: -1px;
116
+ counter-reset: item;
117
+ }
118
+
119
+ @media (min-width: 640px) {
120
+ .ordered-list {
121
+ margin-left: 9px;
122
+ }
123
+ }
124
+
125
+ .list-number {
126
+ color: rgb(107 114 128);
127
+ }
128
+
129
+ .list-number.themed {
130
+ color: var(--theme-accent);
131
+ }
132
+
133
+ .checkbox-marker {
134
+ border-color: rgb(107 114 128);
135
+ background-color: transparent;
136
+ }
137
+
138
+ .checkbox-marker.themed {
139
+ border-color: var(--theme-accent);
140
+ }
141
+
142
+ .checkbox-marker.checked {
143
+ background-color: rgb(107 114 128);
144
+ border-color: rgb(107 114 128);
145
+ color: white;
146
+ }
147
+
148
+ .checkbox-marker.checked.themed {
149
+ background-color: var(--theme-accent);
150
+ border-color: var(--theme-accent);
151
+ }
152
+ </style>
@@ -2,7 +2,7 @@
2
2
  import RichText from '../RichText.svelte';
3
3
  import UnorderedListBlock from './UnorderedListBlock.svelte';
4
4
 
5
- export interface ListItem {
5
+ interface ListItem {
6
6
  content?: {
7
7
  plaintext: string;
8
8
  facets?: any[];
@@ -9,3 +9,31 @@ export { default as ThemedText } from './common/ThemedText.svelte';
9
9
  export { default as ThemedCard } from './common/ThemedCard.svelte';
10
10
  export { default as DocumentRenderer } from './document/DocumentRenderer.svelte';
11
11
  export { default as MarkdownRenderer } from './document/MarkdownRenderer.svelte';
12
+ export { default as LinearDocumentRenderer } from './document/LinearDocumentRenderer.svelte';
13
+ export { default as CanvasRenderer } from './document/CanvasRenderer.svelte';
14
+ export { default as BlockRenderer } from './document/BlockRenderer.svelte';
15
+ export { default as RichText } from './document/RichText.svelte';
16
+ export { default as TextBlock } from './document/blocks/TextBlock.svelte';
17
+ export { default as HeaderBlock } from './document/blocks/HeaderBlock.svelte';
18
+ export { default as BlockquoteBlock } from './document/blocks/BlockquoteBlock.svelte';
19
+ export { default as ImageBlock } from './document/blocks/ImageBlock.svelte';
20
+ export { default as CodeBlock } from './document/blocks/CodeBlock.svelte';
21
+ export { default as MathBlock } from './document/blocks/MathBlock.svelte';
22
+ export { default as UnorderedListBlock } from './document/blocks/UnorderedListBlock.svelte';
23
+ export { default as OrderedListBlock } from './document/blocks/OrderedListBlock.svelte';
24
+ export { default as HorizontalRuleBlock } from './document/blocks/HorizontalRuleBlock.svelte';
25
+ export { default as IframeBlock } from './document/blocks/IframeBlock.svelte';
26
+ export { default as WebsiteBlock } from './document/blocks/WebsiteBlock.svelte';
27
+ export { default as ButtonBlock } from './document/blocks/ButtonBlock.svelte';
28
+ export { default as BskyPostBlock } from './document/blocks/BskyPostBlock.svelte';
29
+ export { default as PollBlock } from './document/blocks/PollBlock.svelte';
30
+ export { default as PageBlock } from './document/blocks/PageBlock.svelte';
31
+ export { default as Avatar } from './Avatar.svelte';
32
+ export { default as Toast } from './Toast.svelte';
33
+ export { default as Watermark } from './Watermark.svelte';
34
+ export { default as ActionBar } from './ActionBar.svelte';
35
+ export { default as RecommendButton } from './RecommendButton.svelte';
36
+ export { default as ThemeProvider } from './ThemeProvider.svelte';
37
+ export { default as Footnotes } from './Footnotes.svelte';
38
+ export { default as Comment } from './Comment.svelte';
39
+ export { default as CommentsSection } from './CommentsSection.svelte';
@@ -11,3 +11,33 @@ export { default as ThemedCard } from './common/ThemedCard.svelte';
11
11
  // Document rendering
12
12
  export { default as DocumentRenderer } from './document/DocumentRenderer.svelte';
13
13
  export { default as MarkdownRenderer } from './document/MarkdownRenderer.svelte';
14
+ export { default as LinearDocumentRenderer } from './document/LinearDocumentRenderer.svelte';
15
+ export { default as CanvasRenderer } from './document/CanvasRenderer.svelte';
16
+ export { default as BlockRenderer } from './document/BlockRenderer.svelte';
17
+ export { default as RichText } from './document/RichText.svelte';
18
+ // Block components
19
+ export { default as TextBlock } from './document/blocks/TextBlock.svelte';
20
+ export { default as HeaderBlock } from './document/blocks/HeaderBlock.svelte';
21
+ export { default as BlockquoteBlock } from './document/blocks/BlockquoteBlock.svelte';
22
+ export { default as ImageBlock } from './document/blocks/ImageBlock.svelte';
23
+ export { default as CodeBlock } from './document/blocks/CodeBlock.svelte';
24
+ export { default as MathBlock } from './document/blocks/MathBlock.svelte';
25
+ export { default as UnorderedListBlock } from './document/blocks/UnorderedListBlock.svelte';
26
+ export { default as OrderedListBlock } from './document/blocks/OrderedListBlock.svelte';
27
+ export { default as HorizontalRuleBlock } from './document/blocks/HorizontalRuleBlock.svelte';
28
+ export { default as IframeBlock } from './document/blocks/IframeBlock.svelte';
29
+ export { default as WebsiteBlock } from './document/blocks/WebsiteBlock.svelte';
30
+ export { default as ButtonBlock } from './document/blocks/ButtonBlock.svelte';
31
+ export { default as BskyPostBlock } from './document/blocks/BskyPostBlock.svelte';
32
+ export { default as PollBlock } from './document/blocks/PollBlock.svelte';
33
+ export { default as PageBlock } from './document/blocks/PageBlock.svelte';
34
+ // UI components
35
+ export { default as Avatar } from './Avatar.svelte';
36
+ export { default as Toast } from './Toast.svelte';
37
+ export { default as Watermark } from './Watermark.svelte';
38
+ export { default as ActionBar } from './ActionBar.svelte';
39
+ export { default as RecommendButton } from './RecommendButton.svelte';
40
+ export { default as ThemeProvider } from './ThemeProvider.svelte';
41
+ export { default as Footnotes } from './Footnotes.svelte';
42
+ export { default as Comment } from './Comment.svelte';
43
+ export { default as CommentsSection } from './CommentsSection.svelte';
package/dist/index.d.ts CHANGED
@@ -1,20 +1,21 @@
1
1
  export { SiteStandardClient, createClient } from './client.js';
2
2
  export { StandardSitePublisher } from './publisher.js';
3
- export { DocumentCard, PublicationCard, ThemeToggle, StandardSiteLayout, DateDisplay, TagList, ThemedContainer, ThemedText, ThemedCard, DocumentRenderer, MarkdownRenderer } from './components/index.js';
3
+ export { DocumentCard, PublicationCard, ThemeToggle, StandardSiteLayout, DateDisplay, TagList, ThemedContainer, ThemedText, ThemedCard, DocumentRenderer, MarkdownRenderer, LinearDocumentRenderer, CanvasRenderer, BlockRenderer, RichText, TextBlock, HeaderBlock, BlockquoteBlock, ImageBlock, CodeBlock, MathBlock, UnorderedListBlock, OrderedListBlock, HorizontalRuleBlock, IframeBlock, WebsiteBlock, ButtonBlock, BskyPostBlock, PollBlock, PageBlock, Avatar, Toast, Watermark, ActionBar, RecommendButton, ThemeProvider, Footnotes, Comment, CommentsSection } from './components/index.js';
4
4
  export { default as Comments } from './components/Comments.svelte';
5
5
  export { themeStore } from './stores/index.js';
6
- export type { AtProtoBlob, StrongRef, RGBColor, BasicTheme, PublicationPreferences, Publication, Document, AtProtoRecord, ResolvedIdentity, SiteStandardConfig } from './types.js';
6
+ export type { AtProtoBlob, StrongRef, RGBColor, RGBAColor, Color, BackgroundImage, BasicTheme, ExtendedTheme, PublicationPreferences, Publication, Document, AtProtoRecord, ResolvedIdentity, SiteStandardConfig, ByteSlice, LinkFeature, DidMentionFeature, AtMentionFeature, CodeFeature, HighlightFeature, UnderlineFeature, StrikethroughFeature, BoldFeature, ItalicFeature, IdFeature, FootnoteFeature, FacetFeature, Facet, TextBlock, HeaderBlock, BlockquoteBlock, ImageBlock, CodeBlock, MathBlock, OrderedListItem, OrderedListBlock, UnorderedListItem, UnorderedListBlock, HorizontalRuleBlock, IframeBlock, WebsiteBlock, ButtonBlock, BskyPostBlock, PollBlock, PageBlock, Block, Position, Quote, LinearDocumentPage, CanvasPage, Content, LinearDocumentQuote, CommentReplyRef, CommentRecord, RecommendRecord, SubscriptionRecord, LeafletSubscriptionRecord } from './types.js';
7
7
  export type { PublisherConfig, ReaderConfig, LoaderConfig } from './schemas.js';
8
8
  export { COLLECTIONS } from './schemas.js';
9
9
  export { parseAtUri, atUriToHttps, buildAtUri, extractRkey, isAtUri } from './utils/at-uri.js';
10
10
  export { resolveIdentity, buildPdsBlobUrl } from './utils/agents.js';
11
11
  export { cache } from './utils/cache.js';
12
- export { rgbToCSS, rgbToHex, getThemeVars } from './utils/theme.js';
13
- export { mixThemeColor, getThemedTextColor, getThemedBackground, getThemedBorder, getThemedAccent, themeToCssVars } from './utils/theme-helpers.js';
12
+ export { rgbToCSS, rgbaToCSS, colorToCSS, rgbToHex, rgbaToHex, getThemeVars, isRGBA, basicThemeToCssVars, extendedThemeToCssVars, themeToCssVars as anyThemeToCssVars, getFontFamilyCSS, getGoogleFontsUrl, getAllThemeVars } from './utils/theme.js';
13
+ export { mixThemeColor, getThemedTextColor, getThemedBackground, getThemedBorder, getThemedAccent, getThemedPageBackground, getBackgroundImageStyles, getFontStyles, getHeadingFontStyles, getPageWidthStyles, themeToCssVars, extendedThemeToCssVars, anyThemeToCssVars } from './utils/theme-helpers.js';
14
14
  export { getDocumentSlug, getDocumentUrl, extractRkey as extractRkeyFromUri } from './utils/document.js';
15
15
  export { transformContent, convertSidenotes, convertComplexSidenotes, resolveRelativeLinks, stripToPlainText, countWords, calculateReadingTime } from './utils/content.js';
16
16
  export type { TransformOptions, TransformResult } from './utils/content.js';
17
17
  export { fetchComments, fetchMentionComments, formatRelativeTime } from './utils/comments.js';
18
18
  export type { Comment, CommentAuthor, FetchCommentsOptions } from './utils/comments.js';
19
+ export { COMMENTS_COLLECTION, createCommentRecord, parseCommentUri, buildCommentUri, fetchComments as fetchNativeComments, organizeCommentsIntoThreads, countThreadComments, extractQuotedText } from './utils/native-comments.js';
19
20
  export { generatePublicationWellKnown, generateDocumentLinkTag, generatePublicationLinkTag, getDocumentAtUri, getPublicationAtUri, verifyPublicationWellKnown, extractDocumentLinkFromHtml, extractPublicationLinkFromHtml } from './utils/verification.js';
20
21
  export type { PublishDocumentInput, PublishPublicationInput, PublishResult } from './publisher.js';
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  export { SiteStandardClient, createClient } from './client.js';
3
3
  export { StandardSitePublisher } from './publisher.js';
4
4
  // Component exports
5
- export { DocumentCard, PublicationCard, ThemeToggle, StandardSiteLayout, DateDisplay, TagList, ThemedContainer, ThemedText, ThemedCard, DocumentRenderer, MarkdownRenderer } from './components/index.js';
5
+ export { DocumentCard, PublicationCard, ThemeToggle, StandardSiteLayout, DateDisplay, TagList, ThemedContainer, ThemedText, ThemedCard, DocumentRenderer, MarkdownRenderer, LinearDocumentRenderer, CanvasRenderer, BlockRenderer, RichText, TextBlock, HeaderBlock, BlockquoteBlock, ImageBlock, CodeBlock, MathBlock, UnorderedListBlock, OrderedListBlock, HorizontalRuleBlock, IframeBlock, WebsiteBlock, ButtonBlock, BskyPostBlock, PollBlock, PageBlock, Avatar, Toast, Watermark, ActionBar, RecommendButton, ThemeProvider, Footnotes, Comment, CommentsSection } from './components/index.js';
6
6
  // Comments component
7
7
  export { default as Comments } from './components/Comments.svelte';
8
8
  // Store exports
@@ -12,12 +12,14 @@ export { COLLECTIONS } from './schemas.js';
12
12
  export { parseAtUri, atUriToHttps, buildAtUri, extractRkey, isAtUri } from './utils/at-uri.js';
13
13
  export { resolveIdentity, buildPdsBlobUrl } from './utils/agents.js';
14
14
  export { cache } from './utils/cache.js';
15
- export { rgbToCSS, rgbToHex, getThemeVars } from './utils/theme.js';
16
- export { mixThemeColor, getThemedTextColor, getThemedBackground, getThemedBorder, getThemedAccent, themeToCssVars } from './utils/theme-helpers.js';
15
+ export { rgbToCSS, rgbaToCSS, colorToCSS, rgbToHex, rgbaToHex, getThemeVars, isRGBA, basicThemeToCssVars, extendedThemeToCssVars, themeToCssVars as anyThemeToCssVars, getFontFamilyCSS, getGoogleFontsUrl, getAllThemeVars } from './utils/theme.js';
16
+ export { mixThemeColor, getThemedTextColor, getThemedBackground, getThemedBorder, getThemedAccent, getThemedPageBackground, getBackgroundImageStyles, getFontStyles, getHeadingFontStyles, getPageWidthStyles, themeToCssVars, extendedThemeToCssVars, anyThemeToCssVars } from './utils/theme-helpers.js';
17
17
  export { getDocumentSlug, getDocumentUrl, extractRkey as extractRkeyFromUri } from './utils/document.js';
18
18
  // Content transformation exports
19
19
  export { transformContent, convertSidenotes, convertComplexSidenotes, resolveRelativeLinks, stripToPlainText, countWords, calculateReadingTime } from './utils/content.js';
20
- // Comments exports
20
+ // Comments exports (Bluesky replies)
21
21
  export { fetchComments, fetchMentionComments, formatRelativeTime } from './utils/comments.js';
22
+ // Native comments exports
23
+ export { COMMENTS_COLLECTION, createCommentRecord, parseCommentUri, buildCommentUri, fetchComments as fetchNativeComments, organizeCommentsIntoThreads, countThreadComments, extractQuotedText } from './utils/native-comments.js';
22
24
  // Verification exports
23
25
  export { generatePublicationWellKnown, generateDocumentLinkTag, generatePublicationLinkTag, getDocumentAtUri, getPublicationAtUri, verifyPublicationWellKnown, extractDocumentLinkFromHtml, extractPublicationLinkFromHtml } from './utils/verification.js';
@@ -189,5 +189,78 @@ export declare class StandardSitePublisher {
189
189
  * Get the underlying ATP agent for advanced operations
190
190
  */
191
191
  getAtpAgent(): AtpAgent;
192
+ /**
193
+ * Publish a comment on a document
194
+ */
195
+ publishComment(input: {
196
+ /** AT-URI of the document being commented on */
197
+ subject: string;
198
+ /** Comment text */
199
+ plaintext: string;
200
+ /** Facets for rich text */
201
+ facets?: any[];
202
+ /** Parent comment AT-URI if replying */
203
+ parent?: string;
204
+ /** Page ID if commenting on a specific page */
205
+ onPage?: string;
206
+ /** Quote attachment */
207
+ attachment?: {
208
+ document: string;
209
+ quote?: {
210
+ start: {
211
+ block: number[];
212
+ offset: number;
213
+ };
214
+ end: {
215
+ block: number[];
216
+ offset: number;
217
+ };
218
+ };
219
+ };
220
+ }): Promise<PublishResult>;
221
+ /**
222
+ * Delete a comment
223
+ */
224
+ deleteComment(rkey: string): Promise<void>;
225
+ /**
226
+ * Recommend a document
227
+ */
228
+ recommendDocument(subject: string): Promise<PublishResult>;
229
+ /**
230
+ * Remove a recommendation
231
+ */
232
+ unrecommendDocument(rkey: string): Promise<void>;
233
+ /**
234
+ * Check if the current user has recommended a document
235
+ */
236
+ hasRecommended(subject: string): Promise<{
237
+ recommended: boolean;
238
+ rkey?: string;
239
+ }>;
240
+ /**
241
+ * Subscribe to a publication
242
+ */
243
+ subscribeToPublication(publication: string): Promise<PublishResult>;
244
+ /**
245
+ * Unsubscribe from a publication
246
+ */
247
+ unsubscribeFromPublication(rkey: string): Promise<void>;
248
+ /**
249
+ * List subscriptions for the current user
250
+ */
251
+ listSubscriptions(limit?: number): Promise<Array<{
252
+ uri: string;
253
+ cid: string;
254
+ value: {
255
+ publication: string;
256
+ };
257
+ }>>;
258
+ /**
259
+ * Check if subscribed to a publication
260
+ */
261
+ isSubscribed(publication: string): Promise<{
262
+ subscribed: boolean;
263
+ rkey?: string;
264
+ }>;
192
265
  }
193
266
  export type { PublisherConfig };
package/dist/publisher.js CHANGED
@@ -346,4 +346,189 @@ export class StandardSitePublisher {
346
346
  getAtpAgent() {
347
347
  return this.getAgent();
348
348
  }
349
+ // ============================================
350
+ // Comment Methods (pub.leaflet.comment)
351
+ // ============================================
352
+ /**
353
+ * Publish a comment on a document
354
+ */
355
+ async publishComment(input) {
356
+ const did = this.getDid();
357
+ const agent = this.getAgent();
358
+ const record = {
359
+ $type: 'pub.leaflet.comment',
360
+ subject: input.subject,
361
+ plaintext: input.plaintext,
362
+ createdAt: new Date().toISOString()
363
+ };
364
+ if (input.parent) {
365
+ record.reply = {
366
+ $type: 'pub.leaflet.comment#replyRef',
367
+ parent: input.parent
368
+ };
369
+ }
370
+ if (input.facets) {
371
+ record.facets = input.facets;
372
+ }
373
+ if (input.onPage) {
374
+ record.onPage = input.onPage;
375
+ }
376
+ if (input.attachment) {
377
+ record.attachment = {
378
+ $type: 'pub.leaflet.comment#linearDocumentQuote',
379
+ ...input.attachment
380
+ };
381
+ }
382
+ const rkey = generateTid();
383
+ const response = await agent.api.com.atproto.repo.createRecord({
384
+ repo: did,
385
+ collection: 'pub.leaflet.comment',
386
+ rkey,
387
+ record
388
+ });
389
+ return {
390
+ uri: response.data.uri,
391
+ cid: response.data.cid
392
+ };
393
+ }
394
+ /**
395
+ * Delete a comment
396
+ */
397
+ async deleteComment(rkey) {
398
+ const did = this.getDid();
399
+ const agent = this.getAgent();
400
+ await agent.api.com.atproto.repo.deleteRecord({
401
+ repo: did,
402
+ collection: 'pub.leaflet.comment',
403
+ rkey
404
+ });
405
+ }
406
+ // ============================================
407
+ // Recommend Methods (pub.leaflet.interactions.recommend)
408
+ // ============================================
409
+ /**
410
+ * Recommend a document
411
+ */
412
+ async recommendDocument(subject) {
413
+ const did = this.getDid();
414
+ const agent = this.getAgent();
415
+ const record = {
416
+ $type: 'pub.leaflet.interactions.recommend',
417
+ subject,
418
+ createdAt: new Date().toISOString()
419
+ };
420
+ const rkey = generateTid();
421
+ const response = await agent.api.com.atproto.repo.createRecord({
422
+ repo: did,
423
+ collection: 'pub.leaflet.interactions.recommend',
424
+ rkey,
425
+ record
426
+ });
427
+ return {
428
+ uri: response.data.uri,
429
+ cid: response.data.cid
430
+ };
431
+ }
432
+ /**
433
+ * Remove a recommendation
434
+ */
435
+ async unrecommendDocument(rkey) {
436
+ const did = this.getDid();
437
+ const agent = this.getAgent();
438
+ await agent.api.com.atproto.repo.deleteRecord({
439
+ repo: did,
440
+ collection: 'pub.leaflet.interactions.recommend',
441
+ rkey
442
+ });
443
+ }
444
+ /**
445
+ * Check if the current user has recommended a document
446
+ */
447
+ async hasRecommended(subject) {
448
+ const did = this.getDid();
449
+ const agent = this.getAgent();
450
+ const response = await agent.api.com.atproto.repo.listRecords({
451
+ repo: did,
452
+ collection: 'pub.leaflet.interactions.recommend',
453
+ limit: 100
454
+ });
455
+ const record = response.data.records.find((r) => r.value?.subject === subject);
456
+ if (record) {
457
+ const rkey = record.uri.split('/').pop();
458
+ return { recommended: true, rkey };
459
+ }
460
+ return { recommended: false };
461
+ }
462
+ // ============================================
463
+ // Subscription Methods (site.standard.graph.subscription)
464
+ // ============================================
465
+ /**
466
+ * Subscribe to a publication
467
+ */
468
+ async subscribeToPublication(publication) {
469
+ const did = this.getDid();
470
+ const agent = this.getAgent();
471
+ const record = {
472
+ $type: 'site.standard.graph.subscription',
473
+ publication
474
+ };
475
+ const rkey = generateTid();
476
+ const response = await agent.api.com.atproto.repo.createRecord({
477
+ repo: did,
478
+ collection: 'site.standard.graph.subscription',
479
+ rkey,
480
+ record
481
+ });
482
+ return {
483
+ uri: response.data.uri,
484
+ cid: response.data.cid
485
+ };
486
+ }
487
+ /**
488
+ * Unsubscribe from a publication
489
+ */
490
+ async unsubscribeFromPublication(rkey) {
491
+ const did = this.getDid();
492
+ const agent = this.getAgent();
493
+ await agent.api.com.atproto.repo.deleteRecord({
494
+ repo: did,
495
+ collection: 'site.standard.graph.subscription',
496
+ rkey
497
+ });
498
+ }
499
+ /**
500
+ * List subscriptions for the current user
501
+ */
502
+ async listSubscriptions(limit = 100) {
503
+ const did = this.getDid();
504
+ const agent = this.getAgent();
505
+ const response = await agent.api.com.atproto.repo.listRecords({
506
+ repo: did,
507
+ collection: 'site.standard.graph.subscription',
508
+ limit
509
+ });
510
+ return response.data.records.map((r) => ({
511
+ uri: r.uri,
512
+ cid: r.cid,
513
+ value: r.value
514
+ }));
515
+ }
516
+ /**
517
+ * Check if subscribed to a publication
518
+ */
519
+ async isSubscribed(publication) {
520
+ const did = this.getDid();
521
+ const agent = this.getAgent();
522
+ const response = await agent.api.com.atproto.repo.listRecords({
523
+ repo: did,
524
+ collection: 'site.standard.graph.subscription',
525
+ limit: 100
526
+ });
527
+ const record = response.data.records.find((r) => r.value?.publication === publication);
528
+ if (record) {
529
+ const rkey = record.uri.split('/').pop();
530
+ return { subscribed: true, rkey };
531
+ }
532
+ return { subscribed: false };
533
+ }
349
534
  }