Attributes now have YAML values
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import "$sb/lib/syscall_mock.ts";
|
||||
import { parse } from "../../common/markdown_parser/parse_tree.ts";
|
||||
import buildMarkdown from "../../common/markdown_parser/parser.ts";
|
||||
import { extractAttributes } from "$sb/lib/attribute.ts";
|
||||
@@ -6,7 +7,7 @@ import { renderToText } from "$sb/lib/tree.ts";
|
||||
|
||||
const inlineAttributeSample = `
|
||||
# My document
|
||||
Top level attributes: [name:: sup] [age:: 42]
|
||||
Top level attributes: [name:: sup] [age:: 42] [children: [pete, "john", mary]]
|
||||
|
||||
* [ ] Attribute in a task [tag:: foo]
|
||||
* Regular item [tag:: bar]
|
||||
@@ -16,7 +17,7 @@ Top level attributes: [name:: sup] [age:: 42]
|
||||
|
||||
const cleanedInlineAttributeSample = `
|
||||
# My document
|
||||
Top level attributes:
|
||||
Top level attributes:
|
||||
|
||||
* [ ] Attribute in a task [tag:: foo]
|
||||
* Regular item [tag:: bar]
|
||||
@@ -24,16 +25,17 @@ Top level attributes:
|
||||
1. Itemized list [tag:: baz]
|
||||
`;
|
||||
|
||||
Deno.test("Test attribute extraction", () => {
|
||||
Deno.test("Test attribute extraction", async () => {
|
||||
const lang = buildMarkdown([]);
|
||||
const tree = parse(lang, inlineAttributeSample);
|
||||
const toplevelAttributes = extractAttributes(tree, false);
|
||||
assertEquals(Object.keys(toplevelAttributes).length, 2);
|
||||
const toplevelAttributes = await extractAttributes(tree, false);
|
||||
// console.log("All attributes", toplevelAttributes);
|
||||
assertEquals(toplevelAttributes.name, "sup");
|
||||
assertEquals(toplevelAttributes.age, 42);
|
||||
assertEquals(toplevelAttributes.children, ["pete", "john", "mary"]);
|
||||
// Check if the attributes are still there
|
||||
assertEquals(renderToText(tree), inlineAttributeSample);
|
||||
// Now once again with cleaning
|
||||
extractAttributes(tree, true);
|
||||
await extractAttributes(tree, true);
|
||||
assertEquals(renderToText(tree), cleanedInlineAttributeSample);
|
||||
});
|
||||
|
||||
+12
-10
@@ -1,28 +1,28 @@
|
||||
import {
|
||||
findNodeOfType,
|
||||
ParseTree,
|
||||
replaceNodesMatching,
|
||||
replaceNodesMatchingAsync,
|
||||
} from "$sb/lib/tree.ts";
|
||||
|
||||
import { YAML } from "$sb/plugos-syscall/mod.ts";
|
||||
|
||||
export type Attribute = {
|
||||
name: string;
|
||||
value: string;
|
||||
};
|
||||
|
||||
const numberRegex = /^-?\d+(\.\d+)?$/;
|
||||
|
||||
/**
|
||||
* Extracts attributes from a tree, optionally cleaning them out of the tree.
|
||||
* @param tree tree to extract attributes from
|
||||
* @param clean whether or not to clean out the attributes from the tree
|
||||
* @returns mapping from attribute name to attribute value
|
||||
*/
|
||||
export function extractAttributes(
|
||||
export async function extractAttributes(
|
||||
tree: ParseTree,
|
||||
clean: boolean,
|
||||
): Record<string, any> {
|
||||
): Promise<Record<string, any>> {
|
||||
const attributes: Record<string, any> = {};
|
||||
replaceNodesMatching(tree, (n) => {
|
||||
await replaceNodesMatchingAsync(tree, async (n) => {
|
||||
if (n.type === "ListItem") {
|
||||
// Find top-level only, no nested lists
|
||||
return n;
|
||||
@@ -31,11 +31,13 @@ export function extractAttributes(
|
||||
const nameNode = findNodeOfType(n, "AttributeName");
|
||||
const valueNode = findNodeOfType(n, "AttributeValue");
|
||||
if (nameNode && valueNode) {
|
||||
let val: any = valueNode.children![0].text!;
|
||||
if (numberRegex.test(val)) {
|
||||
val = +val;
|
||||
const name = nameNode.children![0].text!;
|
||||
const val = valueNode.children![0].text!;
|
||||
try {
|
||||
attributes[name] = await YAML.parse(val);
|
||||
} catch (e: any) {
|
||||
console.error("Error parsing attribute value as YAML", val, e);
|
||||
}
|
||||
attributes[nameNode.children![0].text!] = val;
|
||||
}
|
||||
// Remove from tree
|
||||
if (clean) {
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import { YAML } from "../../common/deps.ts";
|
||||
|
||||
globalThis.syscall = (name: string, ...args: readonly any[]) => {
|
||||
switch (name) {
|
||||
case "yaml.parse":
|
||||
return Promise.resolve(YAML.parse(args[0]));
|
||||
default:
|
||||
throw Error(`Not implemented in tests: ${name}`);
|
||||
}
|
||||
};
|
||||
@@ -129,7 +129,7 @@ export async function replaceNodesMatchingAsync(
|
||||
tree.children.splice(pos, 1);
|
||||
}
|
||||
} else {
|
||||
replaceNodesMatchingAsync(child, substituteFn);
|
||||
await replaceNodesMatchingAsync(child, substituteFn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,4 +2,4 @@ declare global {
|
||||
function syscall(name: string, ...args: any[]): Promise<any>;
|
||||
}
|
||||
|
||||
export const syscall = self.syscall;
|
||||
export const syscall = globalThis.syscall;
|
||||
|
||||
Reference in New Issue
Block a user