From 5c899b4a5c2c07398151960b2b86d238b49d5bf4 Mon Sep 17 00:00:00 2001 From: Volpeon Date: Sun, 26 Jul 2026 11:57:13 +0200 Subject: Better Strapi integration --- src/deps/strapi/blocks.tsx | 125 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 src/deps/strapi/blocks.tsx (limited to 'src/deps/strapi/blocks.tsx') diff --git a/src/deps/strapi/blocks.tsx b/src/deps/strapi/blocks.tsx new file mode 100644 index 0000000..bb60f71 --- /dev/null +++ b/src/deps/strapi/blocks.tsx @@ -0,0 +1,125 @@ +import { ContentImage } from "$/ui/objects/ContentImage.tsx"; + +import { type Node, type DefaultInlineNode } from "./schema.ts"; + +export function walkBlocks( + content: (Node | DefaultInlineNode)[], + fn: (_: Node | DefaultInlineNode) => unknown, +): void { + for (const node of content) { + fn(node); + + switch (node.type) { + case "heading": + case "code": + case "quote": + case "paragraph": + case "list": + case "list-item": + case "link": { + return walkBlocks(node.children, fn); + } + } + } +} + +function blocksNodeToTSX(node: Node | DefaultInlineNode) { + switch (true) { + case node.type === "heading": { + switch (node.level) { + case 1: + return

{blocksToTSX(node.children)}

; + case 2: + return

{blocksToTSX(node.children)}

; + case 3: + return

{blocksToTSX(node.children)}

; + case 4: + return

{blocksToTSX(node.children)}

; + case 5: + return
{blocksToTSX(node.children)}
; + default: + return
{blocksToTSX(node.children)}
; + } + } + + case node.type === "image" && !!node.image.caption: { + return ( +
+ +
{node.image.caption}
+
+ ); + } + + case node.type === "image": { + return ; + } + + case node.type === "code": { + return ( +
+					{blocksToTSX(node.children)}
+				
+ ); + } + + case node.type === "quote": { + return
{blocksToTSX(node.children)}
; + } + + case node.type === "paragraph" && + node.children.length === 1 && + node.children[0]?.type === "text" && + node.children[0].text === "---": { + return
; + } + + case node.type === "paragraph": { + return

{blocksToTSX(node.children)}

; + } + + case node.type === "list" && node.format === "ordered": { + return
    ${blocksToTSX(node.children)}
; + } + + case node.type === "list": { + return ; + } + + case node.type === "list-item": { + return
  • ${blocksToTSX(node.children)}
  • ; + } + + case node.type === "link": { + return {blocksToTSX(node.children)}; + } + + case node.type === "text": { + return [ + node.bold ? "strong" : undefined, + node.code ? "code" : undefined, + node.italic ? "em" : undefined, + node.strikethrough ? "del" : undefined, + node.underline ? "u" : undefined, + ].reduce((res: JSX.Element, Tag) => (Tag ? {res} : res), node.text); + } + } +} + +export function blocksToTSX( + content: (Node | DefaultInlineNode)[], + filter: (node: Node | DefaultInlineNode) => boolean = () => true, +): JSX.Element { + return content + .filter(filter) + .map(blocksNodeToTSX) + .filter((s) => s !== undefined); +} + +export const Blocks = ({ + content, + filter = () => true, +}: { + content: (Node | DefaultInlineNode)[]; + filter?: (node: Node | DefaultInlineNode) => boolean; +}) => blocksToTSX(content, filter); -- cgit v1.3.1