import { CodeWidgetContent } from "$sb/types.ts"; import { editor, language, markdown, space } from "$sb/syscalls.ts"; import { extractFrontmatter } from "$sb/lib/frontmatter.ts"; import { queryObjects } from "./api.ts"; import { TemplateObject } from "../template/types.ts"; import { renderTemplate } from "../template/plug_api.ts"; import { loadPageObject } from "../template/template.ts"; import { expressionToKvQueryExpression } from "$sb/lib/parse-query.ts"; import { evalQueryExpression } from "$sb/lib/query.ts"; import { parseTreeToAST } from "$sb/lib/tree.ts"; // Somewhat decent looking default template const fallbackTemplate = `{{#each .}} {{#ifEq @key "tags"}}{{else}}**{{@key}}**: {{.}} {{/ifEq}} {{/each}} {{#if tags}}_Tagged with_ {{#each tags}}#{{.}} {{/each}}{{/if}}`; export async function renderFrontmatterWidget(): Promise< CodeWidgetContent | null > { const text = await editor.getText(); const pageMeta = await loadPageObject(await editor.getCurrentPage()); const parsedMd = await markdown.parseMarkdown(text); const frontmatter = await extractFrontmatter(parsedMd); const allFrontMatterTemplates = await queryObjects( "template", { filter: ["=", ["attr", "type"], ["string", "frontmatter"]], orderBy: [{ expr: ["attr", "priority"], desc: false }], }, ); let templateText = fallbackTemplate; // Strategy: walk through all matching templates, evaluate the 'where' expression, and pick the first one that matches for (const template of allFrontMatterTemplates) { const exprAST = parseTreeToAST( await language.parseLanguage("expression", template.where!), ); const parsedExpression = expressionToKvQueryExpression(exprAST[1]); if (evalQueryExpression(parsedExpression, pageMeta)) { // Match! We're happy templateText = await space.readPage(template.ref); break; } } const summaryText = await renderTemplate( templateText, pageMeta, frontmatter, ); // console.log("Rendered", summaryText); return { markdown: summaryText.text, banner: "frontmatter", buttons: [ { description: "Reload", svg: ``, invokeFunction: "index.refreshWidgets", }, { description: "Edit", svg: ``, invokeFunction: "index.editFrontmatter", }, { description: "", svg: "", widgetTarget: true, invokeFunction: "index.editFrontmatter", }, ], }; } export async function editFrontmatter() { // 4 = after the frontmatter (--- + newline) await editor.moveCursor(4, true); }