1
0
This commit is contained in:
Zef Hemel 2022-11-19 15:22:43 +01:00
parent be6d98ba1a
commit cde6311bcb
3 changed files with 79 additions and 39 deletions

View File

@ -1,39 +1,84 @@
import { editor, space, system } from "$sb/silverbullet-syscall/mod.ts"; import { editor, markdown, system } from "$sb/silverbullet-syscall/mod.ts";
import { renderDirectives } from "./directives.ts"; import { nodeAtPos } from "$sb/lib/tree.ts";
import { replaceAsync } from "$sb/lib/util.ts";
import { directiveRegex, renderDirectives } from "./directives.ts";
import { extractMeta } from "./data.ts";
export async function updateDirectivesOnPageCommand() { export async function updateDirectivesOnPageCommand() {
const currentPage = await editor.getCurrentPage(); const pageName = await editor.getCurrentPage();
await editor.save(); const text = await editor.getText();
if ( const tree = await markdown.parseMarkdown(text);
await system.invokeFunction( const metaData = extractMeta(tree, ["$disableDirectives"]);
"server", if (metaData.$disableDirectives) {
"updateDirectivesOnPage", // Not updating, directives disabled
currentPage, return;
)
) {
await editor.reloadPage();
} }
// Collect all directives and their body replacements
const replacements: { startInst: string; text?: string }[] = [];
await replaceAsync(
text,
directiveRegex,
async (fullMatch, startInst, _type, _arg, _body, endInst, index) => {
const replacement: { startInst: string; text?: string } = { startInst };
// Pushing to the replacement array
replacements.push(replacement);
const currentNode = nodeAtPos(tree, index + 1);
if (currentNode?.type !== "CommentBlock") {
// If not a comment block, it's likely a code block, ignore
// console.log("Not comment block, ingoring", fullMatch);
return fullMatch;
}
try {
const replacementText = await system.invokeFunction(
"server",
"serverRenderDirective",
pageName,
fullMatch,
);
replacement.text = replacementText;
return replacementText;
} catch (e: any) {
return `${startInst}\n**ERROR:** ${e.message}\n${endInst}`;
}
},
);
let counter = 0;
// Iterate again and replace the bodies. Iterating again (not using previous positions)
// because text may have changed in the mean time (directive processing may take some time)
// Hypothetically in the mean time directives in text may have been changed/swapped, in which
// case this will break. This would be a rare edge case, however.
await replaceAsync(
text,
directiveRegex,
async (fullMatch, startInst, _type, _arg, _body, endInst, index) => {
const replacement = replacements[counter++];
if (!replacement.text) {
return `${startInst}\n$**ERROR:** Internal error, no replacement found\n${endInst}`;
}
if (replacement.text === fullMatch) {
// No change, no need to dispatch
return fullMatch;
}
// Dispatch the change as a somewhat minimal diff in order not to interfere with current editing
await editor.dispatch({
changes: {
from: index,
to: index + fullMatch.length,
insert: replacement.text,
},
});
return replacement.text;
},
);
} }
// Called from client, running on server // Called from client, running on server
export async function updateDirectivesOnPage( // The text passed here is going to be a single directive block (not a full page)
export function serverRenderDirective(
pageName: string, pageName: string,
): Promise<boolean> { text: string,
let text = ""; ): Promise<string> {
try { return renderDirectives(pageName, text);
text = await space.readPage(pageName);
} catch {
console.warn(
"Could not read page",
pageName,
"perhaps it doesn't yet exist",
);
return false;
}
const newText = await renderDirectives(pageName, text);
if (text !== newText) {
await space.writePage(pageName, newText);
return true;
}
return false;
} }

View File

@ -2,8 +2,8 @@ name: directive
imports: imports:
- https://get.silverbullet.md/global.plug.json - https://get.silverbullet.md/global.plug.json
functions: functions:
updateDirectivesOnPage: serverRenderDirective:
path: ./command.ts:updateDirectivesOnPage path: ./command.ts:serverRenderDirective
updateDirectivesOnPageCommand: updateDirectivesOnPageCommand:
path: ./command.ts:updateDirectivesOnPageCommand path: ./command.ts:updateDirectivesOnPageCommand
command: command:

View File

@ -52,12 +52,7 @@ export async function renderDirectives(
text: string, text: string,
): Promise<string> { ): Promise<string> {
const tree = await markdown.parseMarkdown(text); const tree = await markdown.parseMarkdown(text);
const metaData = extractMeta(tree, ["$disableDirectives"]);
// console.log("Meta data", pageName, metaData);
if (metaData.$disableDirectives) {
return text;
}
text = renderToText(tree);
text = await directiveDispatcher(pageName, text, tree, { text = await directiveDispatcher(pageName, text, tree, {
use: templateDirectiveRenderer, use: templateDirectiveRenderer,
"use-verbose": templateDirectiveRenderer, "use-verbose": templateDirectiveRenderer,