Support ${lua expression} in templates
parent
a169406d37
commit
e1c997616c
|
@ -1,10 +1,29 @@
|
||||||
import type { SysCallMapping } from "$lib/plugos/system.ts";
|
import type { SysCallMapping } from "$lib/plugos/system.ts";
|
||||||
import { parse } from "../space_lua/parse.ts";
|
import { evalExpression } from "$common/space_lua/eval.ts";
|
||||||
|
import { parse, parseExpressionString } from "../space_lua/parse.ts";
|
||||||
|
import type { CommonSystem } from "$common/common_system.ts";
|
||||||
|
import { LuaStackFrame, luaValueToJS } from "$common/space_lua/runtime.ts";
|
||||||
|
|
||||||
export function luaSyscalls(): SysCallMapping {
|
export function luaSyscalls(commonSystem: CommonSystem): SysCallMapping {
|
||||||
return {
|
return {
|
||||||
"lua.parse": (_ctx, code: string) => {
|
"lua.parse": (_ctx, code: string) => {
|
||||||
return parse(code);
|
return parse(code);
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Evaluates a Lua expression and returns the result as a JavaScript value
|
||||||
|
* @param _ctx
|
||||||
|
* @param expression
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
"lua.evalExpression": (_ctx, expression: string) => {
|
||||||
|
const ast = parseExpressionString(expression);
|
||||||
|
return luaValueToJS(
|
||||||
|
evalExpression(
|
||||||
|
ast,
|
||||||
|
commonSystem.spaceLuaEnv.env,
|
||||||
|
LuaStackFrame.lostFrame,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,7 @@ import type { AST } from "../../plug-api/lib/tree.ts";
|
||||||
import { evalQueryExpression } from "@silverbulletmd/silverbullet/lib/query_expression";
|
import { evalQueryExpression } from "@silverbulletmd/silverbullet/lib/query_expression";
|
||||||
import { expressionToKvQueryExpression } from "../../plug-api/lib/parse_query.ts";
|
import { expressionToKvQueryExpression } from "../../plug-api/lib/parse_query.ts";
|
||||||
import type { FunctionMap } from "../../plug-api/types.ts";
|
import type { FunctionMap } from "../../plug-api/types.ts";
|
||||||
import { jsonToMDTable } from "../../plugs/template/util.ts";
|
import { renderExpressionResult } from "../../plugs/template/util.ts";
|
||||||
import { LuaTable } from "$common/space_lua/runtime.ts";
|
|
||||||
|
|
||||||
export async function renderTemplate(
|
export async function renderTemplate(
|
||||||
ast: AST,
|
ast: AST,
|
||||||
|
@ -83,35 +82,6 @@ async function renderExpressionDirective(
|
||||||
return renderExpressionResult(result);
|
return renderExpressionResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderExpressionResult(result: any): string {
|
|
||||||
if (result instanceof LuaTable) {
|
|
||||||
result = result.toJS();
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
Array.isArray(result) && result.length > 0 && typeof result[0] === "object"
|
|
||||||
) {
|
|
||||||
// If result is an array of objects, render as a markdown table
|
|
||||||
try {
|
|
||||||
return jsonToMDTable(result);
|
|
||||||
} catch (e: any) {
|
|
||||||
console.error(
|
|
||||||
`Error rendering expression directive: ${e.message} for value ${
|
|
||||||
JSON.stringify(result)
|
|
||||||
}`,
|
|
||||||
);
|
|
||||||
return JSON.stringify(result);
|
|
||||||
}
|
|
||||||
} else if (typeof result === "object" && result.constructor === Object) {
|
|
||||||
// if result is a plain object, render as a markdown table
|
|
||||||
return jsonToMDTable([result]);
|
|
||||||
} else if (Array.isArray(result)) {
|
|
||||||
// Not-object array, let's render it as a markdown list
|
|
||||||
return result.map((item) => `- ${item}`).join("\n");
|
|
||||||
} else {
|
|
||||||
return "" + result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function renderEachVarDirective(
|
async function renderEachVarDirective(
|
||||||
ast: AST,
|
ast: AST,
|
||||||
value: any[],
|
value: any[],
|
||||||
|
|
|
@ -6,3 +6,9 @@ export function parse(
|
||||||
): Promise<ParseTree> {
|
): Promise<ParseTree> {
|
||||||
return syscall("lua.parse", code);
|
return syscall("lua.parse", code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function evalExpression(
|
||||||
|
expression: string,
|
||||||
|
): Promise<any> {
|
||||||
|
return syscall("lua.evalExpression", expression);
|
||||||
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import {
|
||||||
renderToText,
|
renderToText,
|
||||||
replaceNodesMatchingAsync,
|
replaceNodesMatchingAsync,
|
||||||
} from "../../plug-api/lib/tree.ts";
|
} from "../../plug-api/lib/tree.ts";
|
||||||
import { codeWidget } from "@silverbulletmd/silverbullet/syscalls";
|
import { codeWidget, lua } from "@silverbulletmd/silverbullet/syscalls";
|
||||||
import { parseMarkdown } from "../../plug-api/syscalls/markdown.ts";
|
import { parseMarkdown } from "../../plug-api/syscalls/markdown.ts";
|
||||||
import {
|
import {
|
||||||
type MarkdownRenderOptions,
|
type MarkdownRenderOptions,
|
||||||
|
@ -12,6 +12,8 @@ import {
|
||||||
} from "./markdown_render.ts";
|
} from "./markdown_render.ts";
|
||||||
import { validatePageName } from "@silverbulletmd/silverbullet/lib/page_ref";
|
import { validatePageName } from "@silverbulletmd/silverbullet/lib/page_ref";
|
||||||
import { parsePageRef } from "@silverbulletmd/silverbullet/lib/page_ref";
|
import { parsePageRef } from "@silverbulletmd/silverbullet/lib/page_ref";
|
||||||
|
import type { LuaExpression } from "$common/space_lua/ast.ts";
|
||||||
|
import { renderExpressionResult } from "../template/util.ts";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds code widgets, runs their plug code to render and inlines their content in the parse tree
|
* Finds code widgets, runs their plug code to render and inlines their content in the parse tree
|
||||||
|
@ -102,6 +104,26 @@ export async function expandCodeWidgets(
|
||||||
page,
|
page,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
} else if (n.type === "LuaDirective") {
|
||||||
|
const expr: LuaExpression | null = findNodeOfType(
|
||||||
|
n,
|
||||||
|
"LuaExpressionDirective",
|
||||||
|
) as LuaExpression | null;
|
||||||
|
if (!expr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const exprText = renderToText(expr);
|
||||||
|
|
||||||
|
let result = await lua.evalExpression(exprText);
|
||||||
|
|
||||||
|
if (result.markdown) {
|
||||||
|
result = result.markdown;
|
||||||
|
}
|
||||||
|
|
||||||
|
const markdown = renderExpressionResult(result);
|
||||||
|
|
||||||
|
console.log("Expanding LuaDirective", exprText, result, markdown);
|
||||||
|
return await parseMarkdown(markdown);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return mdTree;
|
return mdTree;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import type { PageMeta } from "../../plug-api/types.ts";
|
import type { PageMeta } from "../../plug-api/types.ts";
|
||||||
import { space, system, template } from "@silverbulletmd/silverbullet/syscalls";
|
import { space, system, template } from "@silverbulletmd/silverbullet/syscalls";
|
||||||
import { cleanTemplate } from "./plug_api.ts";
|
import { cleanTemplate } from "./plug_api.ts";
|
||||||
|
import { LuaTable } from "$common/space_lua/runtime.ts";
|
||||||
|
|
||||||
export function defaultJsonTransformer(v: any): string {
|
export function defaultJsonTransformer(v: any): string {
|
||||||
if (v === undefined) {
|
if (v === undefined) {
|
||||||
|
@ -91,3 +92,32 @@ export async function renderQueryTemplate(
|
||||||
config,
|
config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function renderExpressionResult(result: any): string {
|
||||||
|
if (result instanceof LuaTable) {
|
||||||
|
result = result.toJS();
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
Array.isArray(result) && result.length > 0 && typeof result[0] === "object"
|
||||||
|
) {
|
||||||
|
// If result is an array of objects, render as a markdown table
|
||||||
|
try {
|
||||||
|
return jsonToMDTable(result);
|
||||||
|
} catch (e: any) {
|
||||||
|
console.error(
|
||||||
|
`Error rendering expression directive: ${e.message} for value ${
|
||||||
|
JSON.stringify(result)
|
||||||
|
}`,
|
||||||
|
);
|
||||||
|
return JSON.stringify(result);
|
||||||
|
}
|
||||||
|
} else if (typeof result === "object" && result.constructor === Object) {
|
||||||
|
// if result is a plain object, render as a markdown table
|
||||||
|
return jsonToMDTable([result]);
|
||||||
|
} else if (Array.isArray(result)) {
|
||||||
|
// Not-object array, let's render it as a markdown list
|
||||||
|
return result.map((item) => `- ${item}`).join("\n");
|
||||||
|
} else {
|
||||||
|
return "" + result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -139,7 +139,7 @@ export class ServerSystem extends CommonSystem {
|
||||||
jsonschemaSyscalls(),
|
jsonschemaSyscalls(),
|
||||||
indexSyscalls(this),
|
indexSyscalls(this),
|
||||||
commandSyscalls(this),
|
commandSyscalls(this),
|
||||||
luaSyscalls(),
|
luaSyscalls(this),
|
||||||
templateSyscalls(this.ds),
|
templateSyscalls(this.ds),
|
||||||
dataStoreReadSyscalls(this.ds, this),
|
dataStoreReadSyscalls(this.ds, this),
|
||||||
codeWidgetSyscalls(codeWidgetHook),
|
codeWidgetSyscalls(codeWidgetHook),
|
||||||
|
|
|
@ -168,7 +168,7 @@ export class ClientSystem extends CommonSystem {
|
||||||
jsonschemaSyscalls(),
|
jsonschemaSyscalls(),
|
||||||
indexSyscalls(this),
|
indexSyscalls(this),
|
||||||
commandSyscalls(this),
|
commandSyscalls(this),
|
||||||
luaSyscalls(),
|
luaSyscalls(this),
|
||||||
this.client.syncMode
|
this.client.syncMode
|
||||||
// In sync mode handle locally
|
// In sync mode handle locally
|
||||||
? mqSyscalls(this.mq)
|
? mqSyscalls(this.mq)
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { extendedMarkdownLanguage } from "$common/markdown_parser/parser.ts";
|
||||||
import { renderToText } from "@silverbulletmd/silverbullet/lib/tree";
|
import { renderToText } from "@silverbulletmd/silverbullet/lib/tree";
|
||||||
import { activeWidgets } from "./markdown_widget.ts";
|
import { activeWidgets } from "./markdown_widget.ts";
|
||||||
import { attachWidgetEventHandlers } from "./widget_util.ts";
|
import { attachWidgetEventHandlers } from "./widget_util.ts";
|
||||||
import { renderExpressionResult } from "$common/template/render.ts";
|
import { renderExpressionResult } from "../../plugs/template/util.ts";
|
||||||
|
|
||||||
export type LuaWidgetCallback = (
|
export type LuaWidgetCallback = (
|
||||||
bodyText: string,
|
bodyText: string,
|
||||||
|
|
Loading…
Reference in New Issue