Add Python macro worker runtime, ScriptEngine resolution, and PageRenderer/registry integration
Co-authored-by: rfc1437 <774975+rfc1437@users.noreply.github.com>
This commit is contained in:
@@ -24,6 +24,9 @@ export type {
|
||||
MacroParams,
|
||||
MacroRenderContext,
|
||||
ParsedMacro,
|
||||
PythonMacroInfo,
|
||||
PythonMacroResolver,
|
||||
PythonMacroRendererFn,
|
||||
} from './types';
|
||||
|
||||
// Re-export registry functions
|
||||
@@ -39,4 +42,5 @@ export {
|
||||
renderMacro,
|
||||
renderAllMacros,
|
||||
getEditorPreview,
|
||||
setPythonMacroResolver,
|
||||
} from './registry';
|
||||
|
||||
@@ -5,11 +5,22 @@
|
||||
* Macros self-register using registerMacro() function.
|
||||
*/
|
||||
|
||||
import type { MacroDefinition, MacroParams, MacroRenderContext, ParsedMacro } from './types';
|
||||
import type {
|
||||
MacroDefinition,
|
||||
MacroParams,
|
||||
MacroRenderContext,
|
||||
ParsedMacro,
|
||||
PythonMacroResolver,
|
||||
PythonMacroRendererFn,
|
||||
} from './types';
|
||||
|
||||
// Internal registry storage
|
||||
const macroRegistry = new Map<string, MacroDefinition>();
|
||||
|
||||
// Python macro resolution
|
||||
let pythonMacroResolverFn: PythonMacroResolver | null = null;
|
||||
let pythonMacroRendererFn: PythonMacroRendererFn | null = null;
|
||||
|
||||
/**
|
||||
* Register a macro definition.
|
||||
* Call this from each macro definition file.
|
||||
@@ -25,6 +36,18 @@ export function registerMacro(macro: MacroDefinition): void {
|
||||
macroRegistry.set(name, macro);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Python macro resolver and renderer for preview rendering.
|
||||
* When a macro is not found in the JS registry, the resolver will be called.
|
||||
*/
|
||||
export function setPythonMacroResolver(
|
||||
resolver: PythonMacroResolver | null,
|
||||
renderer: PythonMacroRendererFn | null,
|
||||
): void {
|
||||
pythonMacroResolverFn = resolver;
|
||||
pythonMacroRendererFn = renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a macro definition by name.
|
||||
*
|
||||
@@ -124,6 +147,7 @@ export function parseMacros(markdown: string): ParsedMacro[] {
|
||||
|
||||
/**
|
||||
* Render a single macro to HTML.
|
||||
* First checks JS registry, then falls back to Python macro resolver.
|
||||
*
|
||||
* @param macro - The parsed macro
|
||||
* @param context - Render context
|
||||
@@ -135,25 +159,36 @@ export async function renderMacro(
|
||||
): Promise<string> {
|
||||
const definition = getMacro(macro.name);
|
||||
|
||||
if (!definition) {
|
||||
return `<span class="macro-error" title="Unknown macro: ${macro.name}">${macro.rawText}</span>`;
|
||||
}
|
||||
|
||||
// Validate if validator exists
|
||||
if (definition.validate) {
|
||||
const error = definition.validate(macro.params);
|
||||
if (error) {
|
||||
return `<span class="macro-error" title="${error}">${macro.rawText}</span>`;
|
||||
if (definition) {
|
||||
// Validate if validator exists
|
||||
if (definition.validate) {
|
||||
const error = definition.validate(macro.params);
|
||||
if (error) {
|
||||
return `<span class="macro-error" title="${error}">${macro.rawText}</span>`;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const result = definition.render(macro.params, context);
|
||||
return result instanceof Promise ? await result : result;
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : 'Render error';
|
||||
return `<span class="macro-error" title="${message}">${macro.rawText}</span>`;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const result = definition.render(macro.params, context);
|
||||
return result instanceof Promise ? await result : result;
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : 'Render error';
|
||||
return `<span class="macro-error" title="${message}">${macro.rawText}</span>`;
|
||||
|
||||
if (pythonMacroResolverFn && pythonMacroRendererFn) {
|
||||
try {
|
||||
const pythonInfo = await pythonMacroResolverFn(macro.name);
|
||||
if (pythonInfo) {
|
||||
return await pythonMacroRendererFn(pythonInfo, macro.params, context);
|
||||
}
|
||||
} catch {
|
||||
return `<span class="macro-error" title="Python macro error">${macro.rawText}</span>`;
|
||||
}
|
||||
}
|
||||
|
||||
return `<span class="macro-error" title="Unknown macro: ${macro.name}">${macro.rawText}</span>`;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -75,3 +75,30 @@ export interface ParsedMacro {
|
||||
/** End position in the source text */
|
||||
end: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolved Python macro script information for rendering.
|
||||
*/
|
||||
export interface PythonMacroInfo {
|
||||
scriptId: string;
|
||||
slug: string;
|
||||
code: string;
|
||||
entrypoint: string;
|
||||
version: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolver function that checks if a macro name maps to a Python script.
|
||||
* Returns script info if found, null otherwise.
|
||||
*/
|
||||
export type PythonMacroResolver = (macroName: string) => Promise<PythonMacroInfo | null>;
|
||||
|
||||
/**
|
||||
* Renderer function that executes a Python macro with the given context.
|
||||
* Returns the rendered HTML string.
|
||||
*/
|
||||
export type PythonMacroRendererFn = (
|
||||
info: PythonMacroInfo,
|
||||
params: MacroParams,
|
||||
context: MacroRenderContext,
|
||||
) => Promise<string>;
|
||||
|
||||
Reference in New Issue
Block a user