mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-10-14 02:56:36 +00:00
feat(web): serve plugin-declared widgets, and actually ask for them
LEDMatrixWidgets.loadPluginWidget has always fetched /static/plugin-widgets/<plugin>/<widget>.js, and docs/widget-guide.md has always documented that path, but nothing served it. soccer-scoreboard has shipped a 17KB widgets/custom-leagues.js since August that could never load. Both halves were missing, not just the route: - serve_plugin_widget serves the script from the plugin's widgets/ directory as text/javascript. The manifest is the allowlist -- only a widget the plugin declares is reachable -- so installing a plugin does not publish everything it ships. Path handling mirrors the sibling serve_plugin_web_ui: allowlist regexes, os.path.basename, resolve() + relative_to() containment, and the ledmatrix- prefix fallback. The declared script name is guarded too, since it comes from the plugin rather than the request. - The config form never requested one. Its x-widget dispatch is a hardcoded list of core widget names, so a plugin's own widget fell through to a plain text input. An unrecognised x-widget on a string field now asks ensureWidget() for it. The text input stays as the fallback and is removed only once the widget has actually rendered, so a missing or broken widget costs the user an editor rather than their configured value on the next save. - manifest_schema.json gains "widgets", so the declaration is validated rather than merely tolerated by additionalProperties. Verified in a browser against the real partial: a declared widget loads, registers and renders, and its field posts exactly one value; a field whose widget 404s keeps its text input and still posts its value. Not addressed: loadPluginWidgetsFromManifest still has no caller. The per-field ensureWidget path is lazier and is what the form now uses, so that bulk helper is dead weight -- worth removing, but left alone here rather than inventing a call site for it. Known limitation, documented: only string-typed fields take this path. object/array/boolean/number fields and enums are dispatched by the template's own branches, which still only know core widgets. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -280,14 +280,40 @@ In your plugin's `config_schema.json`:
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3: Widget Loading
|
||||
### Step 3: Declare the Widget in `manifest.json`
|
||||
|
||||
The widget will be automatically loaded when the plugin configuration form is rendered. The system will:
|
||||
The manifest is the allowlist -- a widget is served only if the plugin declares
|
||||
it, so shipping a file under `widgets/` does not by itself publish it:
|
||||
|
||||
1. Check if widget is registered in the core registry
|
||||
2. If not found, attempt to load from plugin directory: `/static/plugin-widgets/[plugin-id]/[widget-name].js`
|
||||
```json
|
||||
{
|
||||
"widgets": [
|
||||
{ "name": "my-custom-widget", "script": "my-custom-widget.js" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
`script` is optional and defaults to `[name].js`. It must be a plain filename
|
||||
directly inside the plugin's `widgets/` directory.
|
||||
|
||||
### Step 4: Widget Loading
|
||||
|
||||
The widget is loaded on demand when the config form renders a field that
|
||||
references it. The system will:
|
||||
|
||||
1. Check if the widget is registered in the core registry
|
||||
2. If not, fetch `/static/plugin-widgets/[plugin-id]/[widget-name].js`, which
|
||||
serves the declared script from the plugin's `widgets/` directory
|
||||
3. Render the widget using the registered `render` function
|
||||
|
||||
The fetch is a dynamic `import()`, so the file must parse as an ES module (a
|
||||
plain IIFE does). If anything fails, the field falls back to a plain text input
|
||||
holding the current value, so a broken widget never costs the user their
|
||||
configured value.
|
||||
|
||||
Only `string`-typed fields take this path today; see `docs/widget-guide.md`
|
||||
for the full details and limitations.
|
||||
|
||||
## Widget API Reference
|
||||
|
||||
### Widget Definition Object
|
||||
|
||||
Reference in New Issue
Block a user