silverbullet/plugs/index/widget.ts

96 lines
3.4 KiB
TypeScript
Raw Normal View History

import {
codeWidget,
editor,
language,
markdown,
space,
} from "@silverbulletmd/silverbullet/syscalls";
import {
parseTreeToAST,
renderToText,
} from "@silverbulletmd/silverbullet/lib/tree";
2024-07-30 23:33:33 +08:00
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"],
},
],
};
}