fix: lots of missing pieces for python macro handling
This commit is contained in:
@@ -77,10 +77,16 @@ These are current realities and should be treated as authoritative unless we exp
|
||||
|
||||
### Implementation details
|
||||
|
||||
- **Production path**: `PageRenderer` now accepts an optional `PythonMacroRendererContract`. Macro replacement in the Liquid `markdown` filter is async via `replaceAllMacrosAsync()`. When an unknown macro name is encountered and a Python macro renderer is provided, the renderer resolves enabled macro scripts by slug and executes them via `PythonMacroWorkerRuntime` (Node.js worker thread + Pyodide). Script resolution only occurs when at least one non-built-in macro is present in the content, avoiding overhead for posts with only JS macros.
|
||||
- **Calling convention**: Python macro entrypoints use a two-argument signature: `def render(context, post)`. `context` is the macro context dict (with `params`, `language`, `post_slug`, etc.). `post` is the full `PostData` dict for the post containing the macro (with `title`, `slug`, `content`, `tags`, `categories`, `createdAt`, etc.), or `None` if post data is unavailable.
|
||||
|
||||
- **Production path**: `PageRenderer` now accepts an optional `PythonMacroRendererContract`. Macro replacement in the Liquid `markdown` filter is async via `replaceAllMacrosAsync()`. When an unknown macro name is encountered and a Python macro renderer is provided, the renderer resolves enabled macro scripts by slug and executes them via `PythonMacroWorkerRuntime` (Node.js worker thread + Pyodide). Script resolution only occurs when at least one non-built-in macro is present in the content, avoiding overhead for posts with only JS macros. PostData is serialized per-post via `serializePostDataForMacro()` and threaded through the Liquid `markdown` filter as `post_data_json_by_id`.
|
||||
|
||||
- **Preview path**: The renderer macro registry (`registry.ts`) supports `setPythonMacroResolver()`. When a macro is not found in the JS registry, the Python resolver is consulted. If a matching script is found, the renderer delegates to `PythonMacroRendererFn` which uses the existing `PythonRuntimeManager` (web worker + Pyodide).
|
||||
|
||||
- **`bds_api` module**: Python macros can call app APIs via the `bds_api` module. In the main-process worker (`PythonMacroWorkerRuntime`), API calls are dispatched via `mainProcessPythonApiInvoker.ts` which routes to engine methods directly. In the renderer worker, API calls go through the existing IPC bridge. The `bds_api` module is auto-generated by `generatePythonApiModuleV1.ts` and installed in both workers at bootstrap.
|
||||
|
||||
- **Editor macro detection**: The editor macro plugin uses `hasMacro()` to distinguish known macros from unknown ones. `hasMacro()` checks both the JS macro registry and a set of known Python macro slugs fetched via `scripts:getEnabledMacroSlugs` IPC. The slug set is refreshed on startup and whenever scripts change (`BDS_EVENT_SCRIPTS_CHANGED`).
|
||||
|
||||
- **Precedence**: JS built-in macros (youtube, vimeo, gallery, photo_archive, tag_cloud) always take priority over Python scripts with the same slug. Python macros only activate for names not registered in the JS macro registry.
|
||||
|
||||
- **Error handling**: Python macro execution errors are caught and result in empty string output, preserving the rest of the document. Script resolution errors are also caught gracefully.
|
||||
|
||||
Reference in New Issue
Block a user