From 71bf62b6220e973ce8e4c327b05b696d9ccd6c90 Mon Sep 17 00:00:00 2001 From: Emma Date: Tue, 11 Jun 2024 05:07:08 -0600 Subject: [PATCH] ttcMD: fixes for lists, adds ordered lists --- lib/tcmd/TokenIdentifiers.tsx | 199 ++++++++++++++++++++++------------ lib/tcmd/index.ts | 58 +++++----- 2 files changed, 157 insertions(+), 100 deletions(-) diff --git a/lib/tcmd/TokenIdentifiers.tsx b/lib/tcmd/TokenIdentifiers.tsx index c4372f9..b81372b 100644 --- a/lib/tcmd/TokenIdentifiers.tsx +++ b/lib/tcmd/TokenIdentifiers.tsx @@ -8,7 +8,7 @@ export const TokenRenderers = new Map>(); export function buildIdentifierMap(): [ TokenIdentifierMap, - IdentifierRegistration, + IdentifierRegistration ] { const TokenIdentifiers = new Map>(); @@ -16,7 +16,7 @@ export function buildIdentifierMap(): [ type: string, match: RegExp, parseFunction: (s: string, rx: RegExp) => IdentifiedToken, - renderFunction: TokenRenderer, + renderFunction: TokenRenderer ): void; function registerIdentifier( type: string, @@ -24,7 +24,7 @@ export function buildIdentifierMap(): [ parseFunction: (s: string, rx: RegExp) => IdentifiedToken, renderFunction: TokenRenderer, openTagRx: RegExp, - closeTagRx: RegExp, + closeTagRx: RegExp ): void; function registerIdentifier>( type: string, @@ -32,7 +32,7 @@ export function buildIdentifierMap(): [ parseFunction: (s: string, rx: RegExp) => IdentifiedToken, renderFunction: TokenRenderer, openTagRx?: RegExp, - closeTagRx?: RegExp, + closeTagRx?: RegExp ) { TokenIdentifiers.set(type, { rx: match, @@ -45,17 +45,18 @@ export function buildIdentifierMap(): [ return { ...token, ...identifiedToken } as Token; }, - search: openTagRx && closeTagRx - ? (s, start, end) => { - return search( - s, - start, - end, - new RegExp(openTagRx, "g"), - new RegExp(closeTagRx, "g"), - ); - } - : undefined, + search: + openTagRx && closeTagRx + ? (s, start, end) => { + return search( + s, + start, + end, + new RegExp(openTagRx, "g"), + new RegExp(closeTagRx, "g") + ); + } + : undefined, }); TokenRenderers.set(type, renderFunction); } @@ -67,7 +68,6 @@ export const buildOnlyDefaultElements = () => { const [TokenIdentifiers, registerIdentifier] = buildIdentifierMap(); TokenRenderers.set("text", (t: Token) => { - debugger; return ( {t.content.replaceAll(/\\n ?/g, "\n")} @@ -105,20 +105,26 @@ export const buildOnlyDefaultElements = () => { const { children, metadata } = token; return (
{children?.map((c) => { const Comp = c.metadata.span ? Fragment : "div"; - return {c.render(c)}; + return ( + + {c.render(c)} + + ); })}
); }, /(? { return (
- {children?.map((e) => {e.render(e)} - )} + {children?.map((e) => ( + {e.render(e)} + ))}
); }, /\[\[/g, - /\]\]/g, + /\]\]/g ); // fenced code block @@ -182,16 +191,16 @@ export const buildOnlyDefaultElements = () => { {token.content} ); - }, + } ); // list registerIdentifier( "list", - /^\s*-\s([\s\S]*?)\n\n/gm, + /(?<=\n\n|^) *-\s([\s\S]*?)(?=\n\n|$)/g, (s, rx) => { return { - content: s.match(new RegExp(rx, ""))?.at(1) || "Unable to parse list", + content: s.match(new RegExp(rx, ""))?.at(0) || "Unable to parse list", raw: s, metadata: { initialDepth: @@ -221,17 +230,60 @@ export const buildOnlyDefaultElements = () => { ); - }, + } ); + // ordered-list + registerIdentifier( + "ordered-list", + /(?<=\n\n|^)\s*\d+\.\s([\s\S]*?)(?=\n\n|$)/g, + (s, rx) => { + // debugger; + return { + content: + s.match(new RegExp(rx, ""))?.at(0) || "Unable to parse ordered list", + raw: s, + metadata: { + // initialDepth: + // s.replace("\n", "").split(/\d+\./).at(0)?.length.toString() || "1", + }, + uuid: crypto.randomUUID(), + rendersChildrenOnly, + }; + }, + (token) => { + const { children } = token; + debugger; + return ( + <> +
    + {children?.map((c) => { + return ( +
  1. + {c.children?.map((c: Token) => ( + {c.render(c)} + ))} +
  2. + ); + })} +
+ + ); + } + ); + + // ordered list-item // list-item registerIdentifier( "list-item", - /^\s*-\s(.*?)$/gm, + /(?<=^|\n) *(?:-|\d+\.)\s(.*?)(?=\n|$)/g, (s, rx) => { return { - content: s.match(new RegExp(rx, ""))?.at(1) || - "Unable to parse list-item", + content: + s.match(new RegExp(rx, ""))?.at(1) || "Unable to parse list-item", raw: s, metadata: { initialDepth: @@ -245,13 +297,11 @@ export const buildOnlyDefaultElements = () => { return (
  • {children?.map((c) => ( - - (c.render(c)) - + {c.render(c)} ))}
  • ); - }, + } ); // heading @@ -259,8 +309,8 @@ export const buildOnlyDefaultElements = () => { "heading", /^#+\s(.*?)$/gm, (s, rx) => { - const content = s.match(new RegExp(rx, ""))?.at(1) || - "Unable to parse heading"; + const content = + s.match(new RegExp(rx, ""))?.at(1) || "Unable to parse heading"; return { content: content, raw: s, @@ -287,7 +337,7 @@ export const buildOnlyDefaultElements = () => { {token.content} ); - }, + } ); // image @@ -319,13 +369,12 @@ export const buildOnlyDefaultElements = () => { USE_PROFILES: { svg: true }, }), }} - > - + > ); } // eslint-disable-next-line @next/next/no-img-element return {token.content}; - }, + } ); // anchor @@ -360,14 +409,16 @@ export const buildOnlyDefaultElements = () => { const { metadata } = token; return ( {token.content} ); - }, + } ); // inline-code @@ -376,8 +427,8 @@ export const buildOnlyDefaultElements = () => { /(?<=\s|^)`(.*?)`(?=[\s,.!?)]|$)/gi, (s, rx) => { return { - content: s.match(new RegExp(rx, "i"))?.at(1) || - "Unable to parse inline-code", + content: + s.match(new RegExp(rx, "i"))?.at(1) || "Unable to parse inline-code", raw: s, metadata: {}, uuid: crypto.randomUUID(), @@ -390,7 +441,7 @@ export const buildOnlyDefaultElements = () => { {token.content}
    ); - }, + } ); // bold @@ -408,7 +459,7 @@ export const buildOnlyDefaultElements = () => { }, (token) => { return {token.content}; - }, + } ); // italic @@ -417,8 +468,8 @@ export const buildOnlyDefaultElements = () => { /(? { return { - content: s.match(new RegExp(rx, "i"))?.at(1) || - "Unable to parse italic", + content: + s.match(new RegExp(rx, "i"))?.at(1) || "Unable to parse italic", raw: s, metadata: {}, uuid: crypto.randomUUID(), @@ -427,7 +478,7 @@ export const buildOnlyDefaultElements = () => { }, (token) => { return {token.content}; - }, + } ); // popover @@ -449,9 +500,11 @@ export const buildOnlyDefaultElements = () => { const { children, metadata, uuid } = token; return ( ( - {c.render(c)} - )) || token.content} + content={ + children?.map((c) => ( + {c.render(c)} + )) || token.content + } preferredAlign="centered" preferredEdge="bottom" className="cursor-pointer mx-2" @@ -461,7 +514,7 @@ export const buildOnlyDefaultElements = () => { ); - }, + } ); registerIdentifier( @@ -490,7 +543,7 @@ export const buildOnlyDefaultElements = () => { ); - }, + } ); registerIdentifier( @@ -507,8 +560,6 @@ export const buildOnlyDefaultElements = () => { (token) => { const { children } = token; - debugger; - return (
    {children?.map((e) => { @@ -516,7 +567,7 @@ export const buildOnlyDefaultElements = () => { })}
    ); - }, + } ); registerIdentifier( @@ -533,7 +584,7 @@ export const buildOnlyDefaultElements = () => { }, () => { return
    ; - }, + } ); registerIdentifier( @@ -550,7 +601,7 @@ export const buildOnlyDefaultElements = () => { }, () => { return <>; - }, + } ); registerIdentifier( @@ -568,7 +619,7 @@ export const buildOnlyDefaultElements = () => { }, (token) => { return <>{token.raw}; - }, + } ); registerIdentifier( @@ -622,7 +673,7 @@ export const buildOnlyDefaultElements = () => { } const maxColumns = Math.max( - ...[...headerRows, ...bodyRows, ...footerRows].map((r) => r.length), + ...[...headerRows, ...bodyRows, ...footerRows].map((r) => r.length) ); return { @@ -680,8 +731,12 @@ export const buildOnlyDefaultElements = () => { {child?.render(child) || c} @@ -709,7 +764,7 @@ export const buildOnlyDefaultElements = () => { )} ); - }, + } ); return TokenIdentifiers; @@ -718,7 +773,7 @@ export const buildOnlyDefaultElements = () => { function findMatchingClosedParenthesis( str: string, openRegex: RegExp, - closedRegex: RegExp, + closedRegex: RegExp ): number | null { let openings = 0; let closings = 0; @@ -774,7 +829,7 @@ function search( start: number, end: number, openRx: RegExp, - closeRx: RegExp, + closeRx: RegExp ): SearchResult { const oldEnd = end; @@ -782,7 +837,7 @@ function search( s, // s.substring(0, end - start), openRx, - closeRx, + closeRx ); if (newEnd === null) throw Error("There was an issue finding a closing tag"); diff --git a/lib/tcmd/index.ts b/lib/tcmd/index.ts index 8003c2c..7da4f4d 100644 --- a/lib/tcmd/index.ts +++ b/lib/tcmd/index.ts @@ -5,6 +5,7 @@ import { buildOnlyDefaultElements, TokenRenderers } from "./TokenIdentifiers"; export const createElements = (body: string): Token[] => { const tokens = tokenize(body); + console.log(tokens); return buildAbstractSyntaxTree(tokens).map((t) => t.token); }; @@ -109,7 +110,7 @@ type ParentChildMap = { }; const parentChildMap: ParentChildMap = { - "list": ["list-item"], + list: ["list-item"], // Add more mappings as needed... }; @@ -128,10 +129,8 @@ function filterOverlappingPBlocks(blocks: TokenMarker[]): TokenMarker[] { for (const otherBlock of blocks) { if ( otherBlock !== block && - ( - otherBlock.start === block.start || - (otherBlock.end === block.end && otherBlock.start < block.start) - ) + (otherBlock.start === block.start || + (otherBlock.end === block.end && otherBlock.start < block.start)) ) { return false; } @@ -155,29 +154,32 @@ const contentToChildren = (token: Token) => { } token.children = zipArrays( - content.split(splitMarker).map((c): Token => ({ - content: c.replaceAll("\n", " "), - metadata: {}, - raw: c, - type: token.rendersChildrenOnly ? "p" : "text", - uuid: crypto.randomUUID(), - rendersContentOnly: token.rendersChildrenOnly ? false : true, - render: TokenRenderers.get(token.rendersChildrenOnly ? "p" : "text")!, - children: token.rendersChildrenOnly && c.replaceAll("\n", "") - ? [ - { - content: c.replaceAll("\n", " "), - metadata: {}, - raw: c, - type: "text", - uuid: crypto.randomUUID(), - render: TokenRenderers.get("text")!, - rendersContentOnly: true, - }, - ] - : undefined, - })), - token.children || [], + content.split(splitMarker).map( + (c): Token => ({ + content: c.replaceAll("\n", " "), + metadata: {}, + raw: c, + type: token.rendersChildrenOnly ? "p" : "text", + uuid: crypto.randomUUID(), + rendersContentOnly: token.rendersChildrenOnly ? false : true, + render: TokenRenderers.get(token.rendersChildrenOnly ? "p" : "text")!, + children: + token.rendersChildrenOnly && c.replaceAll("\n", "") + ? [ + { + content: c.replaceAll("\n", " "), + metadata: {}, + raw: c, + type: "text", + uuid: crypto.randomUUID(), + render: TokenRenderers.get("text")!, + rendersContentOnly: true, + }, + ] + : undefined, + }) + ), + token.children || [] ).filter((c) => c.children?.length || (c.rendersContentOnly && c.content)); };