A calm place to write long-form, and publish it to the open social web. skypress.blog/
0

Configure Feed

Select the types of activity you want to include in your feed.

Store flat mentions list in blog.skypress.content.gutenberg

+35 -3
+14
src/lib/publish/records.test.ts
··· 122 122 } ); 123 123 } ); 124 124 125 + describe( 'buildContentObject — mentions', () => { 126 + it( 'omits the mentions field when there are none', () => { 127 + const content = buildContentObject( BLOCKS ); 128 + expect( 'mentions' in content ).toBe( false ); 129 + } ); 130 + 131 + it( 'stores a flat {did, handle} list when mentions are passed', () => { 132 + const content = buildContentObject( BLOCKS, [ 133 + { did: 'did:plc:a', handle: 'alice.bsky.social', displayText: '@alice.bsky.social' }, 134 + ] ); 135 + expect( content.mentions ).toEqual( [ { did: 'did:plc:a', handle: 'alice.bsky.social' } ] ); 136 + } ); 137 + } ); 138 + 125 139 describe( 'buildPublicationRecord', () => { 126 140 it( 'bakes the slug into the required url + name', () => { 127 141 const pub = buildPublicationRecord( {
+21 -3
src/lib/publish/records.ts
··· 138 138 $type: typeof CONTENT_TYPE; 139 139 version: number; 140 140 blocks: BlockNode[]; 141 + /** 142 + * Optional flat list of accounts this document mentions, derived from the inline 143 + * `<a data-did>` anchors. Additive interop hint for other appviews (Decision 0013); 144 + * SkyPress's own reader resolves mentions from the anchors, not this field. 145 + */ 146 + mentions?: Array< { did: string; handle: string } >; 141 147 } 142 148 143 149 /** Wrap the block tree as the document's `content` union member. */ 144 - export function buildContentObject( blocks: BlockNode[] ): GutenbergContent { 145 - return { $type: CONTENT_TYPE, version: CONTENT_VERSION, blocks }; 150 + export function buildContentObject( 151 + blocks: BlockNode[], 152 + mentions: Mention[] = [] 153 + ): GutenbergContent { 154 + return { 155 + $type: CONTENT_TYPE, 156 + version: CONTENT_VERSION, 157 + blocks, 158 + ...( mentions.length 159 + ? { mentions: mentions.map( ( m ) => ( { did: m.did, handle: m.handle } ) ) } 160 + : {} ), 161 + }; 146 162 } 147 163 148 164 export interface PublicationRecord { ··· 208 224 bskyPostRef?: StrongRef; 209 225 /** Set on edit (Decision 0008); preserves publishedAt + bskyPostRef. */ 210 226 updatedAt?: string; 227 + /** Flat mention list to record on the content object (additive interop hint). */ 228 + mentions?: Mention[]; 211 229 } ): DocumentRecord { 212 230 return { 213 231 $type: 'site.standard.document', ··· 216 234 path: articlePath( input.rkey ), 217 235 publishedAt: input.publishedAt, 218 236 textContent: input.textContent, 219 - content: buildContentObject( input.blocks ), 237 + content: buildContentObject( input.blocks, input.mentions ), 220 238 ...( input.coverImage ? { coverImage: input.coverImage } : {} ), 221 239 ...( input.description ? { description: input.description } : {} ), 222 240 ...( input.bskyPostRef ? { bskyPostRef: input.bskyPostRef } : {} ),