ttcMD: allow for typing metadata

This commit is contained in:
Emmaline Autumn 2024-03-15 10:02:46 -06:00
parent 1b0d39f7a3
commit 3c7ef5a185
2 changed files with 29 additions and 29 deletions

View File

@ -11,27 +11,27 @@ type SearchFunction = (s: string, start: number, end: number) => {
lastIndex: number; lastIndex: number;
}; };
type TokenIdentifier = { type TokenIdentifier<M> = {
rx: RegExp; rx: RegExp;
parse: (s: string) => Token; parse: (s: string) => Token<M>;
search?: SearchFunction; search?: SearchFunction;
}; };
type TokenIdentifierMap = Map< type TokenIdentifierMap = Map<
string, string,
TokenIdentifier TokenIdentifier<any>
>; >;
export const TokenRenderers = new Map< export const TokenRenderers = new Map<
string, string,
TokenRenderer TokenRenderer<any>
>(); >();
type IdentifierRegistration = ( type IdentifierRegistration = <N = Record<string, string>>(
type: string, type: string,
match: RegExp, match: RegExp,
parseFunction: (s: string, rx: RegExp) => IdentifiedToken, parseFunction: (s: string, rx: RegExp) => IdentifiedToken<N>,
renderFunction: TokenRenderer, renderFunction: TokenRenderer<N>,
openTagRx?: RegExp, openTagRx?: RegExp,
closeTagRx?: RegExp, closeTagRx?: RegExp,
) => void; ) => void;
@ -42,28 +42,28 @@ export function buildIdentifierMap(): [
] { ] {
const TokenIdentifiers = new Map< const TokenIdentifiers = new Map<
string, string,
TokenIdentifier TokenIdentifier<any>
>(); >();
function registerIdentifier( function registerIdentifier<M>(
type: string, type: string,
match: RegExp, match: RegExp,
parseFunction: (s: string, rx: RegExp) => IdentifiedToken, parseFunction: (s: string, rx: RegExp) => IdentifiedToken<M>,
renderFunction: TokenRenderer, renderFunction: TokenRenderer<M>,
): void; ): void;
function registerIdentifier( function registerIdentifier<M>(
type: string, type: string,
match: RegExp, match: RegExp,
parseFunction: (s: string, rx: RegExp) => IdentifiedToken, parseFunction: (s: string, rx: RegExp) => IdentifiedToken<M>,
renderFunction: TokenRenderer, renderFunction: TokenRenderer<M>,
openTagRx: RegExp, openTagRx: RegExp,
closeTagRx: RegExp, closeTagRx: RegExp,
): void; ): void;
function registerIdentifier( function registerIdentifier<M = Record<string, string>>(
type: string, type: string,
match: RegExp, match: RegExp,
parseFunction: (s: string, rx: RegExp) => IdentifiedToken, parseFunction: (s: string, rx: RegExp) => IdentifiedToken<M>,
renderFunction: TokenRenderer, renderFunction: TokenRenderer<M>,
openTagRx?: RegExp, openTagRx?: RegExp,
closeTagRx?: RegExp, closeTagRx?: RegExp,
) { ) {
@ -76,7 +76,7 @@ export function buildIdentifierMap(): [
type, type,
}; };
return { ...token, ...identifiedToken }; return { ...token, ...identifiedToken } as Token<M>;
}, },
search: (openTagRx && closeTagRx) search: (openTagRx && closeTagRx)
? (s, start, end) => { ? (s, start, end) => {
@ -99,7 +99,7 @@ export function buildIdentifierMap(): [
export const buildOnlyDefaultElements = () => { export const buildOnlyDefaultElements = () => {
const [TokenIdentifiers, registerIdentifier] = buildIdentifierMap(); const [TokenIdentifiers, registerIdentifier] = buildIdentifierMap();
TokenRenderers.set("text", (t) => { TokenRenderers.set("text", (t: Token<any>) => {
debugger; debugger;
return ( return (
<span className="whitespace-pre-wrap"> <span className="whitespace-pre-wrap">
@ -114,7 +114,7 @@ export const buildOnlyDefaultElements = () => {
const rendersChildrenOnly = true; const rendersChildrenOnly = true;
// grid // grid
registerIdentifier( registerIdentifier<{ columns: string }>(
"grid", "grid",
/(?<!\/)(?:\[\])+\n+((?:.|\n)*?)\n+\/\[\]/g, /(?<!\/)(?:\[\])+\n+((?:.|\n)*?)\n+\/\[\]/g,
(s) => { (s) => {
@ -140,7 +140,7 @@ export const buildOnlyDefaultElements = () => {
} as React.CSSProperties} } as React.CSSProperties}
className="grid grid-cols-dynamic gap-x-8 gap-y-6 mb-6" className="grid grid-cols-dynamic gap-x-8 gap-y-6 mb-6"
> >
{children?.map((c, i) => ( {children?.map((c) => (
<div key={c.uuid}> <div key={c.uuid}>
{c.render(c)} {c.render(c)}
</div> </div>
@ -240,7 +240,7 @@ export const buildOnlyDefaultElements = () => {
key={c.uuid} key={c.uuid}
data-depth={metadata.initialDepth} data-depth={metadata.initialDepth}
> >
{c.children?.map((c) => ( {c.children?.map((c: Token<any>) => (
<Fragment key={c.uuid}>{c.render(c)}</Fragment> <Fragment key={c.uuid}>{c.render(c)}</Fragment>
))} ))}
</li> </li>
@ -463,7 +463,7 @@ export const buildOnlyDefaultElements = () => {
content={children?.map((c) => ( content={children?.map((c) => (
<Fragment key={uuid}>{c.render(c)}</Fragment> <Fragment key={uuid}>{c.render(c)}</Fragment>
)) || )) ||
metadata.content} token.content}
preferredAlign="centered" preferredAlign="centered"
preferredEdge="bottom" preferredEdge="bottom"
className="cursor-pointer mx-2" className="cursor-pointer mx-2"

12
types.d.ts vendored
View File

@ -1,5 +1,5 @@
type IdentifiedToken = { type IdentifiedToken<M> = {
metadata: Record<string, string>; metadata: M;
children?: Token[]; children?: Token[];
uuid: string; uuid: string;
raw: string; raw: string;
@ -8,21 +8,21 @@ type IdentifiedToken = {
rendersContentOnly?: boolean; rendersContentOnly?: boolean;
}; };
type TokenRenderer = (t: Token) => ReactNode; type TokenRenderer<M> = (t: Token<M>) => ReactNode;
type TokenAttributes = { type TokenAttributes = {
type: string; type: string;
render: TokenRenderer; render: TokenRenderer;
}; };
type Token = IdentifiedToken & TokenAttributes; type Token<M = Record<string, string>> = IdentifiedToken<M> & TokenAttributes;
type TokenMarker = { type TokenMarker<M = Record<string, string>> = {
start: number; start: number;
end: number; end: number;
type: string; type: string;
parent?: TokenMarker; parent?: TokenMarker;
token: Token; token: Token<M>;
}; };
type FrontMatter = Record<string, string>; type FrontMatter = Record<string, string>;