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);
};

View File

@@ -147,13 +147,3 @@ export class TTCQueryParser {
}
}
}
// Example usage:
// const
// const parser = new TTCQueryParser(data);
// // Example queries
// console.log(parser.search("$weapon_abilities[name=Rapid Fire].body")); // Example output
// // console.log(parser.search("^weapon_abilities[name=Rapid Fire]", data)); // Example output
// console.log(parser.search("$weapon_abilities[name=Rapid Fire].body", data)); // Example output

View File

@@ -26,12 +26,14 @@ export class TTCQueryResolver {
}
const last = this.stack.at(-1);
if (typeof last === "function" && !onDemand) return last();
if (onDemand) debugger;
return last;
}
private parseResolver(resolver: string) {
if (this.isArithmetic(resolver)) return this.solveArithmetic(resolver);
if (this.isQuery(resolver)) this.runQuery(resolver);
if (this.isQuery(resolver)) return this.runQuery(resolver);
}
private isQuery(resolver: string) {
return (
@@ -56,15 +58,15 @@ export class TTCQueryResolver {
// if (query.startsWith("?") || query.startsWith("_"))
return query.startsWith("_") && this.context
? this.parser.search(query.replace("_", ""), this.context)
: this.parser.search(query.replace(/^[?_].?/, ""));
? this.parser.search(query.replace("_", "^"), this.context).at(0)
: this.parser.search(query.replace(/^[?_].?/, "")).at(0);
}
private handleDice(dice: string, query: string) {
const d = new Dice(dice);
const [method, n] = query.split(":");
let num = Number(n);
if (n.startsWith("$")) num = this.getFromStack(n);
if (n && n.startsWith("$")) num = this.getFromStack(n);
switch (method) {
case "roll":
return () => d.roll();
@@ -91,7 +93,6 @@ export class TTCQueryResolver {
if (n1.startsWith("$")) num1 = this.getFromStack<number>(n1);
if (n2.startsWith("$")) num2 = this.getFromStack<number>(n2);
console.log(num1, num2);
switch (op) {
case "+":
@@ -109,7 +110,7 @@ export class TTCQueryResolver {
}
}
private getFromStack<T>(stackIndex: string): T {
public getFromStack<T>(stackIndex: string): T {
const i = Number(stackIndex.replace("$", ""));
const val = this.stack[i] as T;
return val;