MD handlers for resolvers

This commit is contained in:
2024-08-05 06:25:55 -06:00
parent 3656fc42ac
commit 2b2b88f970
7 changed files with 193 additions and 25 deletions

55
lib/tcmd/Resolver.tsx Normal file
View File

@@ -0,0 +1,55 @@
import { PublicationAtom } from "@/recoil/atoms/publication";
import { useState, useEffect, useCallback, useRef } from "react";
import { useRecoilValue } from "recoil";
import { TTCQueryResolver } from "../ttcQuery/TTCResolvers";
export function Resolver({ resolver }: { resolver: string }) {
const parser = useRecoilValue(PublicationAtom);
const [res] = useState(new TTCQueryResolver(parser));
const [content, setContent] = useState("");
useEffect(() => {
setContent(res.resolve(resolver));
}, [resolver, res]);
return <span>{content}</span>;
}
export function OnDemandResolver({
resolver,
template,
title,
}: {
resolver: string;
template: string;
title?: string;
}) {
const parser = useRecoilValue(PublicationAtom);
const res = useRef(new TTCQueryResolver(parser));
const [content, setContent] = useState("");
const generateContent = useCallback(() => {
let content = template;
const stackIdxs = Array.from(new Set(template.match(/\$\d/g)));
for (const idx of stackIdxs) {
let thing = res.current.getFromStack(idx);
debugger;
if (Array.isArray(thing)) thing = thing.at(0);
if (typeof thing === "function") thing = thing();
content = content.replaceAll(idx, thing as string);
}
setContent(content);
}, [res, template]);
const resolve = useCallback(() => {
res.current.resolve(resolver, true);
generateContent();
}, [res, resolver, generateContent]);
return (
<>
<button onMouseDown={() => setContent("")} onClick={resolve}>
{title ?? "Resolve"}
</button>
<br />
{!!content && <span>{content}</span>}
</>
);
}

View File

@@ -3,6 +3,7 @@ import Link from "next/link";
import React, { Fragment } from "react";
import { Poppable } from "../poppables/components/poppable";
import { Accordion, AccordionContent } from "../accordion";
import { OnDemandResolver, Resolver } from "./Resolver";
export const TokenRenderers = new Map<string, TokenRenderer<any>>();
@@ -123,7 +124,7 @@ export const buildOnlyDefaultElements = () => {
</div>
);
},
/(?<!\/)(?:\[\])+/g,
/(?<![\/\?])(?:\[\])+/g,
/\/\[\]/g
);
@@ -517,6 +518,7 @@ export const buildOnlyDefaultElements = () => {
}
);
// accordion
registerIdentifier(
"accordion",
/\[accordion(\s.*?)?]\n+((?:.|\n)*?)\n+\[\/accordion\]/g,
@@ -546,6 +548,7 @@ export const buildOnlyDefaultElements = () => {
}
);
// paragraph
registerIdentifier(
"p",
/(?<=\n\n)([\s\S]*?)(?=\n\n)/g,
@@ -570,6 +573,7 @@ export const buildOnlyDefaultElements = () => {
}
);
// horizontal rule
registerIdentifier(
"hr",
/^-{3,}$/gm,
@@ -587,6 +591,7 @@ export const buildOnlyDefaultElements = () => {
}
);
// comment
registerIdentifier(
"comment",
/<!--[\s\S]+?-->/g,
@@ -604,6 +609,7 @@ export const buildOnlyDefaultElements = () => {
}
);
// frontmatter
registerIdentifier(
"frontmatter",
/^---([\s\S]*?)---/g,
@@ -622,6 +628,7 @@ export const buildOnlyDefaultElements = () => {
}
);
// table
registerIdentifier(
"table",
/(?<=\n|^)\| [\s\S]*? \|(?=(\n|$)(?!\|))/g,
@@ -767,6 +774,75 @@ export const buildOnlyDefaultElements = () => {
}
);
// resolver
registerIdentifier(
"resolver",
/\?\?<<(.*?)>>/g,
(s) => {
const inp = s.match(/(?<=<<)(.*?)(?=>>)/)![0];
if (inp == undefined)
return {
content: "Error parsing resolver: " + s,
metadata: {},
raw: "ERROR",
uuid: crypto.randomUUID(),
};
return {
content: inp,
metadata: {},
raw: s,
uuid: crypto.randomUUID(),
};
},
(t) => {
if (t.content.startsWith("Error"))
return <span className="red-500">{t.content}</span>;
return <Resolver resolver={t.content} />;
}
);
// on-demand resolver
registerIdentifier(
"on-demand resolver",
/\?\?\[.*?\](\(.*?\))?<<(.*?)>>/g,
(s) => {
const inp = s.match(/(?<=<<)(.*?)(?=>>)/)![0];
const template = s.match(/(?<=\?\?\[)(.*?)(?=\])/)![0];
const title = s.match(/(?<=\]\()(.*?)(?=\))/)?.at(0);
if (inp == undefined)
return {
content: "Error parsing resolver: " + s,
metadata: {
title: "",
template: "",
},
raw: "ERROR",
uuid: crypto.randomUUID(),
};
return {
content: inp,
metadata: {
title,
template,
},
raw: s,
uuid: crypto.randomUUID(),
};
},
(t) => {
if (t.content.startsWith("Error"))
return <span className="red-500">{t.content}</span>;
return (
<OnDemandResolver
resolver={t.content}
template={t.metadata.template}
title={t.metadata.title}
/>
);
}
);
return TokenIdentifiers;
};
@@ -840,7 +916,8 @@ function search(
closeRx
);
if (newEnd === null) throw Error("There was an issue finding a closing tag");
if (newEnd === null)
throw Error("There was an issue finding a closing tag for ");
end = newEnd + start;

View File

@@ -5,7 +5,6 @@ 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);
};