silverbullet/plug-api/lib/attribute.ts

70 lines
1.7 KiB
TypeScript
Raw Permalink Normal View History

2023-07-25 01:54:31 +08:00
import {
findNodeOfType,
2024-07-30 23:33:33 +08:00
type ParseTree,
renderToText,
2024-08-22 02:13:40 +08:00
replaceNodesMatching,
traverseTreeAsync,
2024-02-29 22:23:05 +08:00
} from "./tree.ts";
2023-07-25 01:54:31 +08:00
import { cleanupJSON } from "@silverbulletmd/silverbullet/lib/json";
2024-07-09 15:32:57 +08:00
import { system, YAML } from "../syscalls.ts";
2023-07-26 23:12:56 +08:00
2023-07-25 01:54:31 +08:00
/**
2024-08-22 02:13:40 +08:00
* Extracts attributes from a tree
2023-07-25 01:54:31 +08:00
* @param tree tree to extract attributes from
* @returns mapping from attribute name to attribute value
*/
2023-07-26 23:12:56 +08:00
export async function extractAttributes(
tags: string[],
2023-07-25 01:54:31 +08:00
tree: ParseTree,
2023-07-26 23:12:56 +08:00
): Promise<Record<string, any>> {
let attributes: Record<string, any> = {};
2024-08-22 02:13:40 +08:00
await traverseTreeAsync(tree, async (n) => {
if (tree !== n && n.type === "ListItem") {
2023-07-25 01:54:31 +08:00
// Find top-level only, no nested lists
2024-08-22 02:13:40 +08:00
return true;
2023-07-25 01:54:31 +08:00
}
if (n.type === "Attribute") {
const nameNode = findNodeOfType(n, "AttributeName");
const valueNode = findNodeOfType(n, "AttributeValue");
if (nameNode && valueNode) {
2023-07-26 23:12:56 +08:00
const name = nameNode.children![0].text!;
const val = valueNode.children![0].text!;
try {
2024-07-09 15:32:57 +08:00
attributes[name] = cleanupJSON(await YAML.parse(val));
2023-07-26 23:12:56 +08:00
} catch (e: any) {
console.error("Error parsing attribute value as YAML", val, e);
2023-07-25 01:54:31 +08:00
}
}
2024-08-22 02:13:40 +08:00
return true;
2023-07-25 01:54:31 +08:00
}
// Go on...
2024-08-22 02:13:40 +08:00
return false;
2023-07-25 01:54:31 +08:00
});
const text = renderToText(tree);
const spaceScriptAttributes = await system.applyAttributeExtractors(
tags,
text,
tree,
);
attributes = {
...attributes,
...spaceScriptAttributes,
};
2023-07-25 01:54:31 +08:00
return attributes;
}
2024-08-22 02:13:40 +08:00
/**
* Cleans attributes from a tree (as a side effect)
* @param tree to clean attributes from
*/
export function cleanAttributes(tree: ParseTree) {
replaceNodesMatching(tree, (n) => {
if (n.type === "Attribute") {
return null;
}
return;
});
}