Support ${lua expression} in templates
parent
a169406d37
commit
e1c997616c
|
@ -1,10 +1,29 @@
|
|||
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 {
|
||||
"lua.parse": (_ctx, code: string) => {
|
||||
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 { expressionToKvQueryExpression } from "../../plug-api/lib/parse_query.ts";
|
||||
import type { FunctionMap } from "../../plug-api/types.ts";
|
||||
import { jsonToMDTable } from "../../plugs/template/util.ts";
|
||||
import { LuaTable } from "$common/space_lua/runtime.ts";
|
||||
import { renderExpressionResult } from "../../plugs/template/util.ts";
|
||||
|
||||
export async function renderTemplate(
|
||||
ast: AST,
|
||||
|
@ -83,35 +82,6 @@ async function renderExpressionDirective(
|
|||
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(
|
||||
ast: AST,
|
||||
value: any[],
|
||||
|
|
|
@ -6,3 +6,9 @@ export function parse(
|
|||
): Promise<ParseTree> {
|
||||
return syscall("lua.parse", code);
|
||||
}
|
||||
|
||||
export function evalExpression(
|
||||
expression: string,
|
||||
): Promise<any> {
|
||||
return syscall("lua.evalExpression", expression);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import {
|
|||
renderToText,
|
||||
replaceNodesMatchingAsync,
|
||||
} 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 {
|
||||
type MarkdownRenderOptions,
|
||||
|
@ -12,6 +12,8 @@ import {
|
|||
} from "./markdown_render.ts";
|
||||
import { validatePageName } 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
|
||||
|
@ -102,6 +104,26 @@ export async function expandCodeWidgets(
|
|||
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;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import type { PageMeta } from "../../plug-api/types.ts";
|
||||
import { space, system, template } from "@silverbulletmd/silverbullet/syscalls";
|
||||
import { cleanTemplate } from "./plug_api.ts";
|
||||
import { LuaTable } from "$common/space_lua/runtime.ts";
|
||||
|
||||
export function defaultJsonTransformer(v: any): string {
|
||||
if (v === undefined) {
|
||||
|
@ -91,3 +92,32 @@ export async function renderQueryTemplate(
|
|||
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(),
|
||||
indexSyscalls(this),
|
||||
commandSyscalls(this),
|
||||
luaSyscalls(),
|
||||
luaSyscalls(this),
|
||||
templateSyscalls(this.ds),
|
||||
dataStoreReadSyscalls(this.ds, this),
|
||||
codeWidgetSyscalls(codeWidgetHook),
|
||||
|
|
|
@ -168,7 +168,7 @@ export class ClientSystem extends CommonSystem {
|
|||
jsonschemaSyscalls(),
|
||||
indexSyscalls(this),
|
||||
commandSyscalls(this),
|
||||
luaSyscalls(),
|
||||
luaSyscalls(this),
|
||||
this.client.syncMode
|
||||
// In sync mode handle locally
|
||||
? mqSyscalls(this.mq)
|
||||
|
|
|
@ -11,7 +11,7 @@ import { extendedMarkdownLanguage } from "$common/markdown_parser/parser.ts";
|
|||
import { renderToText } from "@silverbulletmd/silverbullet/lib/tree";
|
||||
import { activeWidgets } from "./markdown_widget.ts";
|
||||
import { attachWidgetEventHandlers } from "./widget_util.ts";
|
||||
import { renderExpressionResult } from "$common/template/render.ts";
|
||||
import { renderExpressionResult } from "../../plugs/template/util.ts";
|
||||
|
||||
export type LuaWidgetCallback = (
|
||||
bodyText: string,
|
||||
|
|
Loading…
Reference in New Issue