feat: add support for blockquote block

Changed files
+58 -46
lib
+58 -46
lib/utils.ts
··· 4 4 import katex from "katex"; 5 5 import sanitizeHTML from "sanitize-html"; 6 6 import { 7 + PubLeafletBlocksBlockquote, 7 8 PubLeafletBlocksCode, 8 9 PubLeafletBlocksHeader, 9 10 PubLeafletBlocksHorizontalRule, ··· 182 183 "hr", 183 184 "div", 184 185 "span", 186 + "blockquote", 185 187 ], 186 188 selfClosing: ["img"], 187 189 }); ··· 242 244 }; 243 245 } 244 246 } 247 + } 248 + 249 + function parseTextBlock(block: PubLeafletBlocksText.Main) { 250 + let html = ""; 251 + const rt = new RichText({ 252 + text: block.plaintext, 253 + facets: block.facets || [], 254 + }); 255 + const children = []; 256 + for (const segment of rt.segments()) { 257 + const link = segment.facet?.find( 258 + (segment) => segment.$type === "pub.leaflet.richtext.facet#link", 259 + ); 260 + const isBold = segment.facet?.find( 261 + (segment) => segment.$type === "pub.leaflet.richtext.facet#bold", 262 + ); 263 + const isCode = segment.facet?.find( 264 + (segment) => segment.$type === "pub.leaflet.richtext.facet#code", 265 + ); 266 + const isStrikethrough = segment.facet?.find( 267 + (segment) => segment.$type === "pub.leaflet.richtext.facet#strikethrough", 268 + ); 269 + const isUnderline = segment.facet?.find( 270 + (segment) => segment.$type === "pub.leaflet.richtext.facet#underline", 271 + ); 272 + const isItalic = segment.facet?.find( 273 + (segment) => segment.$type === "pub.leaflet.richtext.facet#italic", 274 + ); 275 + if (isCode) { 276 + children.push(`<pre><code>${segment.text}</code></pre>`); 277 + } else if (link) { 278 + children.push( 279 + `<a href="${link.uri}" target="_blank" rel="noopener noreferrer">${segment.text}</a>`, 280 + ); 281 + } else if (isBold) { 282 + children.push(`<b>${segment.text}</b>`); 283 + } else if (isStrikethrough) { 284 + children.push(`<s>${segment.text}</s>`); 285 + } else if (isUnderline) { 286 + children.push( 287 + `<span style="text-decoration:underline;">${segment.text}</span>`, 288 + ); 289 + } else if (isItalic) { 290 + children.push(`<i>${segment.text}</i>`); 291 + } else { 292 + children.push(`${segment.text}`); 293 + } 294 + } 295 + html += `<p>${children.join("")}</p>`; 296 + 297 + return html.trim(); 245 298 } 246 299 247 300 function parseBlocks({ ··· 254 307 let html = ""; 255 308 256 309 if (is(PubLeafletBlocksText.mainSchema, block.block)) { 257 - const rt = new RichText({ 258 - text: block.block.plaintext, 259 - facets: block.block.facets || [], 260 - }); 261 - const children = []; 262 - for (const segment of rt.segments()) { 263 - const link = segment.facet?.find( 264 - (segment) => segment.$type === "pub.leaflet.richtext.facet#link", 265 - ); 266 - const isBold = segment.facet?.find( 267 - (segment) => segment.$type === "pub.leaflet.richtext.facet#bold", 268 - ); 269 - const isCode = segment.facet?.find( 270 - (segment) => segment.$type === "pub.leaflet.richtext.facet#code", 271 - ); 272 - const isStrikethrough = segment.facet?.find( 273 - (segment) => 274 - segment.$type === "pub.leaflet.richtext.facet#strikethrough", 275 - ); 276 - const isUnderline = segment.facet?.find( 277 - (segment) => segment.$type === "pub.leaflet.richtext.facet#underline", 278 - ); 279 - const isItalic = segment.facet?.find( 280 - (segment) => segment.$type === "pub.leaflet.richtext.facet#italic", 281 - ); 282 - if (isCode) { 283 - children.push(`<pre><code>${segment.text}</code></pre>`); 284 - } else if (link) { 285 - children.push( 286 - `<a href="${link.uri}" target="_blank" rel="noopener noreferrer">${segment.text}</a>`, 287 - ); 288 - } else if (isBold) { 289 - children.push(`<b>${segment.text}</b>`); 290 - } else if (isStrikethrough) { 291 - children.push(`<s>${segment.text}</s>`); 292 - } else if (isUnderline) { 293 - children.push( 294 - `<span style="text-decoration:underline;">${segment.text}</span>`, 295 - ); 296 - } else if (isItalic) { 297 - children.push(`<i>${segment.text}</i>`); 298 - } else { 299 - children.push(`${segment.text}`); 300 - } 301 - } 302 - html += `<p>${children.join("")}</p>`; 310 + html += parseTextBlock(block.block); 303 311 } 304 312 305 313 if (is(PubLeafletBlocksHeader.mainSchema, block.block)) { ··· 341 349 if (is(PubLeafletBlocksImage.mainSchema, block.block)) { 342 350 // @ts-ignore 343 351 html += `<div><img src="https://cdn.bsky.app/img/feed_fullsize/plain/${did}/${block.block.image.ref.$link}@jpeg" height="${block.block.aspectRatio.height}" width="${block.block.aspectRatio.width}" alt="${block.block.alt}" /></div>`; 352 + } 353 + 354 + if (is(PubLeafletBlocksBlockquote.mainSchema, block.block)) { 355 + html += `<blockquote>${parseTextBlock(block.block)}</blockquote>`; 344 356 } 345 357 346 358 return html.trim();