import { codeWidget, editor, language, markdown, space, } from "@silverbulletmd/silverbullet/syscalls"; import { parseTreeToAST, renderToText, } from "@silverbulletmd/silverbullet/lib/tree"; import type { CodeWidgetContent } from "../../plug-api/types.ts"; import { loadPageObject } from "../template/page.ts"; import { queryObjects } from "./api.ts"; import type { TemplateObject } from "../template/types.ts"; import { expressionToKvQueryExpression } from "../../plug-api/lib/parse_query.ts"; import { evalQueryExpression } from "@silverbulletmd/silverbullet/lib/query_expression"; import { renderTemplate } from "../template/plug_api.ts"; import { extractFrontmatter } from "@silverbulletmd/silverbullet/lib/frontmatter"; import { rewritePageRefs } from "@silverbulletmd/silverbullet/lib/resolve"; export async function refreshWidgets() { await codeWidget.refreshAll(); } export async function renderTemplateWidgets(side: "top" | "bottom"): Promise< CodeWidgetContent | null > { const text = await editor.getText(); let pageMeta = await loadPageObject(await editor.getCurrentPage()); const parsedMd = await markdown.parseMarkdown(text); const frontmatter = await extractFrontmatter(parsedMd); pageMeta = { ...pageMeta, ...frontmatter }; const blockTemplates = await queryObjects<TemplateObject>( "template", { // where hooks.top/bottom exists filter: ["attr", ["attr", "hooks"], side], orderBy: [{ // order by hooks.top/bottom.order asc expr: ["attr", ["attr", ["attr", "hooks"], side], "order"], desc: false, }], }, ); // console.log(`Found the following ${side} templates`, blockTemplates); const templateBits: string[] = []; // Strategy: walk through all matching templates, evaluate the 'where' expression, and pick the first one that matches for (const template of blockTemplates) { if (!template.hooks) { console.warn( "No hooks specified for template", template.ref, "this should never happen", ); continue; } const blockDef = template.hooks[side]!; const exprAST = parseTreeToAST( await language.parseLanguage("expression", blockDef.where!), ); const parsedExpression = expressionToKvQueryExpression(exprAST[1]); if (await evalQueryExpression(parsedExpression, pageMeta, {}, {})) { // Match! We're happy const templateText = await space.readPage(template.ref); let renderedTemplate = (await renderTemplate( templateText, frontmatter, { page: pageMeta }, )).text; const parsedMarkdown = await markdown.parseMarkdown(renderedTemplate); rewritePageRefs(parsedMarkdown, template.ref); renderedTemplate = renderToText(parsedMarkdown); templateBits.push(renderedTemplate.trim()); } } const summaryText = templateBits.join("\n"); // console.log("Summary:", summaryText); return { markdown: summaryText, buttons: [ { description: "Reload", svg: `<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-refresh-cw"><polyline points="23 4 23 10 17 10"></polyline><polyline points="1 20 1 14 7 14"></polyline><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"></path></svg>`, invokeFunction: ["index.refreshWidgets"], }, ], }; }