Skip to content

Commit

Permalink
No longer index templates tagged as #template
Browse files Browse the repository at this point in the history
zefhemel committed Nov 9, 2023
1 parent 366b2ed commit d58db6a
Showing 19 changed files with 307 additions and 64 deletions.
25 changes: 19 additions & 6 deletions plug-api/lib/frontmatter.ts
Original file line number Diff line number Diff line change
@@ -11,12 +11,17 @@ import {

export type FrontMatter = { tags: string[] } & Record<string, any>;

// Extracts front matter (or legacy "meta" code blocks) from a markdown document
export type FrontmatterExtractOptions = {
removeKeys?: string[];
removeTags?: string[] | true;
removeFrontmatterSection?: boolean;
};

// Extracts front matter from a markdown document
// optionally removes certain keys from the front matter
export async function extractFrontmatter(
tree: ParseTree,
removeKeys: string[] = [],
removeFrontmatterSection = false,
options: FrontmatterExtractOptions = {},
): Promise<FrontMatter> {
let data: FrontMatter = {
tags: [],
@@ -37,6 +42,12 @@ export async function extractFrontmatter(
if (!data.tags.includes(tagname)) {
data.tags.push(tagname);
}
if (
options.removeTags === true || options.removeTags?.includes(tagname)
) {
// Ugly hack to remove the hashtag
h.children![0].text = "";
}
});
}
// Find FrontMatter and parse it
@@ -55,10 +66,10 @@ export async function extractFrontmatter(
if (typeof data.tags === "string") {
data.tags = (data.tags as string).split(/,\s*/);
}
if (removeKeys.length > 0) {
if (options.removeKeys && options.removeKeys.length > 0) {
let removedOne = false;

for (const key of removeKeys) {
for (const key of options.removeKeys) {
if (key in newData) {
delete newData[key];
removedOne = true;
@@ -69,7 +80,9 @@ export async function extractFrontmatter(
}
}
// If nothing is left, let's just delete this whole block
if (Object.keys(newData).length === 0 || removeFrontmatterSection) {
if (
Object.keys(newData).length === 0 || options.removeFrontmatterSection
) {
return null;
}
} catch (e: any) {
2 changes: 1 addition & 1 deletion plug-api/lib/query.ts
Original file line number Diff line number Diff line change
@@ -97,7 +97,7 @@ export function evalQueryExpression(
return !(val1.length === val2.length &&
val1.every((v) => val2.includes(v)));
}
return val1 !== val2;
return val1 != val2;
}
case "=~": {
if (!Array.isArray(val2)) {
8 changes: 6 additions & 2 deletions plugs/directive/command.ts
Original file line number Diff line number Diff line change
@@ -28,7 +28,9 @@ export async function updateDirectivesOnPageCommand() {
}
const text = await editor.getText();
const tree = await markdown.parseMarkdown(text);
const metaData = await extractFrontmatter(tree, ["$disableDirectives"]);
const metaData = await extractFrontmatter(tree, {
removeKeys: ["$disableDirectives"],
});

if (isFederationPath(currentPage)) {
console.info("Current page is a federation page, not updating directives.");
@@ -173,7 +175,9 @@ async function updateDirectivesForPage(
const pageMeta = await space.getPageMeta(pageName);
const currentText = await space.readPage(pageName);
const tree = await markdown.parseMarkdown(currentText);
const metaData = await extractFrontmatter(tree, ["$disableDirectives"]);
const metaData = await extractFrontmatter(tree, {
removeKeys: ["$disableDirectives"],
});

if (isFederationPath(pageName)) {
console.info("Current page is a federation page, not updating directives.");
4 changes: 2 additions & 2 deletions plugs/directive/query_directive.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { events } from "$sb/syscalls.ts";

import { replaceTemplateVars } from "../template/template.ts";
import { renderTemplate } from "./util.ts";
import { renderQueryTemplate } from "./util.ts";
import { jsonToMDTable } from "./util.ts";
import { ParseTree, parseTreeToAST } from "$sb/lib/tree.ts";
import { astToKvQuery } from "$sb/lib/parse-query.ts";
@@ -38,7 +38,7 @@ export async function queryDirectiveRenderer(
// console.log("Parsed query", parsedQuery);
const allResults = results.flat();
if (parsedQuery.render) {
const rendered = await renderTemplate(
const rendered = await renderQueryTemplate(
pageMeta,
parsedQuery.render,
allResults,
7 changes: 3 additions & 4 deletions plugs/directive/template_directive.ts
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ import { directiveRegex } from "./directives.ts";
import { updateDirectives } from "./command.ts";
import { resolvePath, rewritePageRefs } from "$sb/lib/resolve.ts";
import { PageMeta } from "$sb/types.ts";
import { renderTemplate } from "../template/plug_api.ts";

const templateRegex = /\[\[([^\]]+)\]\]\s*(.*)\s*/;

@@ -52,7 +53,7 @@ export async function templateDirectiveRenderer(
templateText = await space.readPage(templatePath);
}
const tree = await markdown.parseMarkdown(templateText);
await extractFrontmatter(tree, [], true); // Remove entire frontmatter section, if any
await extractFrontmatter(tree, { removeFrontmatterSection: true }); // Remove entire frontmatter section, if any

// Resolve paths in the template
rewritePageRefs(tree, templatePath);
@@ -63,9 +64,7 @@ export async function templateDirectiveRenderer(

// if it's a template injection (not a literal "include")
if (directive === "use") {
newBody = await handlebars.renderTemplate(newBody, parsedArgs, {
page: pageMeta,
});
newBody = await renderTemplate(newBody, pageMeta, parsedArgs);

// Recursively render directives
const tree = await markdown.parseMarkdown(newBody);
8 changes: 5 additions & 3 deletions plugs/directive/util.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { handlebars, space } from "$sb/syscalls.ts";
import { handlebarHelpers } from "../../common/syscalls/handlebar_helpers.ts";
import { PageMeta } from "$sb/types.ts";
import { cleanTemplate, renderTemplate } from "../template/plug_api.ts";

export function defaultJsonTransformer(_k: string, v: any) {
if (v === undefined) {
@@ -53,13 +54,14 @@ export function jsonToMDTable(
return lines.join("\n");
}

export async function renderTemplate(
export async function renderQueryTemplate(
pageMeta: PageMeta,
renderTemplate: string,
templatePage: string,
data: any[],
renderAll: boolean,
): Promise<string> {
let templateText = await space.readPage(renderTemplate);
let templateText = await space.readPage(templatePage);
templateText = await cleanTemplate(templateText);
if (!renderAll) {
templateText = `{{#each .}}\n${templateText}\n{{/each}}`;
}
18 changes: 13 additions & 5 deletions plugs/index/command.ts
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ import { editor, events, markdown, mq, space, system } from "$sb/syscalls.ts";
import { sleep } from "$sb/lib/async.ts";
import { IndexEvent } from "$sb/app_event.ts";
import { MQMessage } from "$sb/types.ts";
import { isTemplate } from "../template/util.ts";

export async function reindexCommand() {
await editor.flashNotification("Performing full page reindex...");
@@ -42,9 +43,16 @@ export async function processIndexQueue(messages: MQMessage[]) {
}

export async function parseIndexTextRepublish({ name, text }: IndexEvent) {
// console.log("Reindexing", name);
await events.dispatchEvent("page:index", {
name,
tree: await markdown.parseMarkdown(text),
});
if (isTemplate(text)) {
console.log("Indexing", name, "as template");
await events.dispatchEvent("page:indexTemplate", {
name,
tree: await markdown.parseMarkdown(text),
});
} else {
await events.dispatchEvent("page:index", {
name,
tree: await markdown.parseMarkdown(text),
});
}
}
4 changes: 0 additions & 4 deletions plugs/markdown/html_render.ts
Original file line number Diff line number Diff line change
@@ -41,9 +41,5 @@ export function renderHtml(t: Tag | null): string {
if (t.name === Fragment) {
return body;
}
// if (t.body) {
return `<${t.name}${attrs}>${body}</${t.name}>`;
// } else {
// return `<${t.name}${attrs}/>`;
// }
}
4 changes: 2 additions & 2 deletions plugs/query/query.ts
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ import type { WidgetContent } from "$sb/app_event.ts";
import { events, language, space, system } from "$sb/syscalls.ts";
import { parseTreeToAST } from "$sb/lib/tree.ts";
import { astToKvQuery } from "$sb/lib/parse-query.ts";
import { jsonToMDTable, renderTemplate } from "../directive/util.ts";
import { jsonToMDTable, renderQueryTemplate } from "../directive/util.ts";
import { loadPageObject, replaceTemplateVars } from "../template/template.ts";

export async function widget(
@@ -44,7 +44,7 @@ export async function widget(
} else {
if (parsedQuery.render) {
// Configured a custom rendering template, let's use it!
const rendered = await renderTemplate(
const rendered = await renderQueryTemplate(
pageObject,
parsedQuery.render,
allResults,
51 changes: 51 additions & 0 deletions plugs/template/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { handlebars, markdown, YAML } from "$sb/syscalls.ts";
import type { PageMeta } from "$sb/types.ts";
import { extractFrontmatter } from "$sb/lib/frontmatter.ts";
import { TemplateObject } from "./types.ts";
import { renderToText } from "$sb/lib/tree.ts";

/**
* Strips the template from its frontmatter and renders it.
* The assumption is that the frontmatter has already been parsed and should not appear in thhe rendered output.
* @param templateText the template text
* @param data data to be rendered by the template
* @param globals a set of global variables
* @returns
*/
export async function renderTemplate(
templateText: string,
pageMeta: PageMeta,
data: any = {},
): Promise<string> {
const tree = await markdown.parseMarkdown(templateText);
const frontmatter: Partial<TemplateObject> = await extractFrontmatter(tree, {
removeFrontmatterSection: true,
removeTags: ["template"],
});
templateText = renderToText(tree).trimStart();
// console.log(`Trimmed template: |${templateText}|`);
// If a 'frontmatter' key was specified in the frontmatter, use that as the frontmatter
if (frontmatter.frontmatter) {
if (typeof frontmatter.frontmatter === "string") {
templateText = "---\n" + frontmatter.frontmatter + "---\n" + templateText;
} else {
templateText = "---\n" + (await YAML.stringify(frontmatter.frontmatter)) +
"---\n" + templateText;
}
}
return handlebars.renderTemplate(templateText, data, { page: pageMeta });
}

/**
* Strips a template text from its frontmatter and #template tag
*/
export async function cleanTemplate(
templateText: string,
): Promise<string> {
const tree = await markdown.parseMarkdown(templateText);
await extractFrontmatter(tree, {
removeFrontmatterSection: true,
removeTags: ["template"],
});
return renderToText(tree).trimStart();
}
7 changes: 7 additions & 0 deletions plugs/template/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { IndexTreeEvent } from "$sb/app_event.ts";
import { system } from "$sb/syscalls.ts";

export async function indexTemplate({ name, tree }: IndexTreeEvent) {
// Just delegate to the index plug
await system.invokeFunction("index.indexPage", { name, tree });
}
24 changes: 24 additions & 0 deletions plugs/template/plug_api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { PageMeta } from "$sb/types.ts";
import { system } from "../../plug-api/syscalls.ts";

export function renderTemplate(
templateText: string,
pageMeta: PageMeta,
data: any = {},
): Promise<string> {
return system.invokeFunction(
"template.renderTemplate",
templateText,
pageMeta,
data,
);
}

export function cleanTemplate(
templateText: string,
): Promise<string> {
return system.invokeFunction(
"template.cleanTemplate",
templateText,
);
}
16 changes: 14 additions & 2 deletions plugs/template/template.plug.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
name: template
functions:
# API
renderTemplate:
path: api.ts:renderTemplate
cleanTemplate:
path: api.ts:cleanTemplate

insertTemplateText:
path: template.ts:insertTemplateText


indexTemplate:
path: ./index.ts:indexTemplate
events:
- page:indexTemplate

templateSlashCommand:
path: ./template.ts:templateSlashComplete
@@ -10,8 +24,6 @@ functions:
path: ./template.ts:insertSlashTemplate

# Template commands
insertTemplateText:
path: "./template.ts:insertTemplateText"
applyLineReplace:
path: ./template.ts:applyLineReplace
insertFrontMatter:
34 changes: 14 additions & 20 deletions plugs/template/template.ts
Original file line number Diff line number Diff line change
@@ -4,20 +4,19 @@ import { renderToText } from "$sb/lib/tree.ts";
import { niceDate, niceTime } from "$sb/lib/dates.ts";
import { readSettings } from "$sb/lib/settings_page.ts";
import { cleanPageRef } from "$sb/lib/resolve.ts";
import { ObjectValue, PageMeta } from "$sb/types.ts";
import { PageMeta } from "$sb/types.ts";
import { CompleteEvent, SlashCompletion } from "$sb/app_event.ts";
import { getObjectByRef, queryObjects } from "../index/plug_api.ts";

export type TemplateObject = ObjectValue<{
trigger?: string; // has to start with # for now
scope?: string;
frontmatter?: Record<string, any> | string;
}>;
import { TemplateObject } from "./types.ts";
import { renderTemplate } from "./api.ts";

export async function templateSlashComplete(
completeEvent: CompleteEvent,
): Promise<SlashCompletion[]> {
const allTemplates = await queryObjects<TemplateObject>("template", {});
const allTemplates = await queryObjects<TemplateObject>("template", {
// Only return templates that have a trigger
filter: ["!=", ["attr", "trigger"], ["null"]],
});
return allTemplates.map((template) => ({
label: template.trigger!,
detail: "template",
@@ -31,14 +30,7 @@ export async function insertSlashTemplate(slashCompletion: SlashCompletion) {
const pageObject = await loadPageObject(slashCompletion.pageName);

let templateText = await space.readPage(slashCompletion.templatePage);
templateText = await replaceTemplateVars(templateText, pageObject);
const parseTree = await markdown.parseMarkdown(templateText);
const frontmatter = await extractFrontmatter(parseTree, [], true);
templateText = renderToText(parseTree).trim();
if (frontmatter.frontmatter) {
templateText = "---\n" + (await YAML.stringify(frontmatter.frontmatter)) +
"---\n" + templateText;
}
templateText = await renderTemplate(templateText, pageObject);

const cursorPos = await editor.getCursor();
const carretPos = templateText.indexOf("|^|");
@@ -76,10 +68,12 @@ export async function instantiateTemplateCommand() {
);

const parseTree = await markdown.parseMarkdown(text);
const additionalPageMeta = await extractFrontmatter(parseTree, [
"$name",
"$disableDirectives",
]);
const additionalPageMeta = await extractFrontmatter(parseTree, {
removeKeys: [
"$name",
"$disableDirectives",
],
});

const tempPageMeta: PageMeta = {
tags: ["page"],
Loading
Oops, something went wrong.

0 comments on commit d58db6a

Please sign in to comment.