Skip to content

feat: Vue and Vuetify editing in the ui-template code editor - #2290

Open
Steve-Mcl wants to merge 1 commit into
mainfrom
feat/ui-template-vue-script
Open

Steve-Mcl wants to merge 1 commit into
mainfrom
feat/ui-template-vue-script

Conversation

@Steve-Mcl

Copy link
Copy Markdown
Contributor

Description

Related to node-red/nr-monaco-build#9 and node-red/node-red#5994

Summary

People regularly ask for better editing in ui-template (e.g. https://discourse.nodered.org/t/weather-card-struggling-with-methods/85434/6). Today the editor treats a Vue template as plain HTML: no Vue syntax and no help with Vuetify components.

This adds a vue-sfc language to Node-RED's Monaco editor, shipped with the Dashboard as an editor plugin. Nothing is added to Node-RED core's editor bundle, which was the concern raised in node-red/nr-monaco-build#9. With it, the ui-template editor gets:

  • Vue highlighting: directives, bindings (:prop), events (@click), slots (#activator) and {{ }} expressions highlighted as JavaScript. <script> and <style> blocks are highlighted too, including lang="ts" / lang="scss" / lang="less".
  • Vuetify completion and hover:
    • Typing <v- lists the components.
    • Inside a tag you get its props, bound props (:), events (@), Vuetify directives, and, on a <template> inside a component, that component's slots (#).
    • Props with a fixed set of values (e.g. variant) suggest those values.
    • Hover shows the type, default, description and a link to the Vuetify API docs.
  • Vue's own directives and components (v-if, v-for, <transition>, ...), with links to the Vue docs.
  • Plain HTML completion, hover and formatting, as before, from Monaco's html worker.

It works offline, and works with any Node-RED that uses Monaco. Editors set to ACE keep the plain HTML mode.

How it works

  • nodes/plugins/vue-editor.html: a small editor plugin (registered under node-red.plugins in package.json). At startup it only registers the vue-sfc language and Monaco's HTML language service for it. Everything else loads the first time a ui-template editor opens.
  • resources/vue-editor/vue-sfc.mjs: loaded on first use. The tokenizer, which is adapted from Monaco's HTML tokenizer (MIT, credited in the file), plus the Vue/Vuetify completion and hover providers. Only public Monaco APIs are used.
  • scripts/build-vue-editor-data.js: generates resources/vue-editor/vuetify.json from vuetify/dist/json/web-types.json, so the editor always matches the Vuetify version the Dashboard bundles. It runs as part of npm run build (and build:dev / dev), and the output is gitignored. 192 components, 401 KB raw / 66 KB gzipped, with descriptions de-duplicated into a string table.
  • nodes/widgets/ui_template.html: uses vue-sfc when the editor is Monaco and the plugin is loaded, html otherwise. The expand editor uses the same mode.
  • package.json: adds resources/* to files, the build step, and the plugin entry.

Choices worth flagging:

  • A new language id (vue-sfc) rather than vue. Node-RED maps the vue mode to html, while other ids pass through, so this needs no change in core.
  • Vuetify completion runs on the main thread, not through the html worker's custom data. The HTML service filters attribute completions on the typed text, so :col, @cli or #act would never match color etc.
  • A worker mapping in the plugin. Monaco asks for a language's worker by its language id, and Node-RED's Monaco only knows its built-in ids. The plugin maps vue-sfc to the html worker. feat: add JavaScript and CSS support to script and style blocks in HT… node-red/node-red#5994 does this in core for newer versions.

Package size: about 434 KB more unpacked (the plugin 3.6 KB, vue-sfc.mjs 29 KB, vuetify.json 401 KB) - BUT - it is only loaded when a ui-template editor opens!

What's next

node-red/node-red#5994 adds JavaScript and CSS support to <script> and <style> blocks in Node-RED's HTML editors, with an API that languages like this one can opt into. A follow-up PR builds on it so that, on Node-RED versions that have it, ui-template also gets JavaScript completion and error checking in <script>, with this typed for the component (this.send(), this.msg, data/computed/methods), and CSS completion in <style>. This PR doesn't depend on it.

Testing

  • New unit tests in test/resources/vue-editor.spec.js (20) for cursor context (including skipping script/style/comments/interpolation), parent tag for slots, completions, values and hover. The full suite passes.
  • Lint clean on new/changed files.
  • Checked in the browser with Playwright on Node-RED 5 (Monaco 0.57) and Node-RED 4.1.13 (Monaco 0.52.2):
    • inline and expand editors use vue-sfc;
    • bound props, events, tags, prop values, slots in <template #> and hover all work;
    • HTML completion comes from the html worker;
    • switching the template type to the CSS scopes uses css, and back again uses vue-sfc;
    • Done saves with noerr 0;
    • ACE stays on HTML;
    • no console errors.

Notes

  • FlowFuse Expert: nr-assistant registers its ui-template CodeLens and inline completions for the html language. With ui-template on vue-sfc, those won't show in the template part until nr-assistant also accepts vue-sfc. That's a small change in nr-assistant (CodeLens registration, supportedInlineCompletions, and isInsideComment). I'll PR that as well.
  • The docs (docs/en/nodes/widgets/ui-template.md) get a short "Code Editor" section. I've only done the English page.

Related Issue(s)

Checklist

  • I have read the contribution guidelines
  • Suitable unit/system level tests have been added and they pass
  • Documentation has been updated
    • Upgrade instructions
    • Configuration details
    • Concepts
  • Changes flowforge.yml?
    • Issue/PR raised on FlowFuse/helm to update ConfigMap Template
    • Issue/PR raised on FlowFuse/CloudProject to update values for Staging/Production
  • Link to Changelog Entry PR, or note why one is not needed.

Labels

  • Includes a DB migration? -> add the area:migration label

The ui-template editor treats a Vue template as plain HTML: no Vue syntax, no help
with Vuetify components. This adds a `vue-sfc` language for Node-RED's Monaco editor,
shipped as an editor plugin with the Dashboard, so nothing is added to Node-RED core.

- Vue highlighting: directives, bindings, events, slots and {{ }} as JavaScript;
  <script> and <style> blocks (TS, SCSS and Less with lang=)
- Completion and hover for Vuetify components, props, bound props, events, slots,
  prop values and directives, plus Vue's own directives and components
- Vuetify data is generated at build time from the Vuetify version the Dashboard
  bundles (scripts/build-vue-editor-data.js), and loaded only when a ui-template
  editor is first opened
- Plain HTML completion, hover and formatting from Monaco's html worker
- ui-template uses the new language with Monaco; ACE keeps the HTML mode

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant