Fixes #122
This commit is contained in:
parent
be6d98ba1a
commit
cde6311bcb
@ -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;
|
|
||||||
}
|
}
|
||||||
|
@ -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:
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user