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.

render-article: opt-in syntax highlighting before sanitise

+32 -3
+18
src/lib/reader/render-article.test.ts
··· 121 121 expect( html ).toBe( '' ); 122 122 expect( text ).toBe( '' ); 123 123 } ); 124 + 125 + it( 'highlights code blocks only when opted in', () => { 126 + const doc = { 127 + content: { 128 + blocks: [ { name: 'core/code', attributes: { content: 'const answer = 42;' } } ], 129 + }, 130 + }; 131 + const off = renderArticle( doc, AUTHOR ); 132 + const on = renderArticle( doc, AUTHOR, { highlight: true } ); 133 + 134 + // Default (RSS path) stays plain. 135 + expect( off.html ).toContain( '<pre class="wp-block-code"><code>' ); 136 + expect( off.html ).not.toContain( 'hljs' ); 137 + 138 + // Opt-in produces sanitiser-safe token spans. 139 + expect( on.html ).toContain( 'class="hljs' ); 140 + expect( on.html ).toContain( '<span class="hljs-' ); 141 + } ); 124 142 } );
+14 -3
src/lib/reader/render-article.ts
··· 14 14 import { renderBlocks, blocksToText } from '../blocks/render'; 15 15 import { resolveBlobImageUrls } from '../media/blob'; 16 16 import { sanitizeArticleHtml } from './sanitize'; 17 + import { highlightCodeBlocks } from './highlight'; 17 18 import type { BlockNode } from '../blocks/render'; 18 19 19 20 /** The slice of a `site.standard.document` value the renderer consumes. */ ··· 29 30 text: string; 30 31 } 31 32 33 + export interface RenderOptions { 34 + /** Syntax-highlight code blocks (web page only — RSS stays plain). */ 35 + highlight?: boolean; 36 + } 37 + 32 38 /** 33 39 * Render a document's blocks to sanitised HTML and plain text. `author` is the 34 40 * document's writer (current PDS + DID) — blob-backed image URLs are rebuilt 35 - * against it before rendering, so images survive a PDS migration. 41 + * against it before rendering, so images survive a PDS migration. Pass 42 + * `{ highlight: true }` to syntax-highlight code blocks (web page only; the 43 + * highlight step runs before sanitise, so its token markup is sanitiser-checked). 36 44 */ 37 45 export function renderArticle( 38 46 doc: RenderableDocument, 39 - author: { pdsUrl: string; did: string } 47 + author: { pdsUrl: string; did: string }, 48 + options: RenderOptions = {} 40 49 ): RenderedArticle { 41 50 const blocks = resolveBlobImageUrls( doc.content?.blocks ?? [], author ); 51 + const rendered = renderBlocks( blocks ); 52 + const highlighted = options.highlight ? highlightCodeBlocks( rendered ) : rendered; 42 53 return { 43 - html: sanitizeArticleHtml( renderBlocks( blocks ) ), 54 + html: sanitizeArticleHtml( highlighted ), 44 55 text: doc.textContent || blocksToText( blocks ), 45 56 }; 46 57 }