Compare commits

...

2 Commits

Author SHA1 Message Date
41385f7c5e Update @lezer/common version in lock files to 1.5.0 for consistency
All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good
- Changed the version of @lezer/common from 1.5.2 to 1.5.0 in both bun.lock and pnpm-lock.yaml files.
- Ensured all references to @lezer/common across dependencies are aligned with the fixed version, improving compatibility and stability.
2026-08-10 03:34:18 +01:00
eeccfe077f Enhance fcTemplateLang with autocompletion support and XML schema integration
- Updated fcTemplateLang to accept an autoCompleteObject parameter, improving JavaScript autocompletion capabilities.
- Introduced a new schema.js file defining XML attributes and elements for FarmControl templates, enhancing template editing.
- Modified CodeBlockEditor and ObjectProperty components to pass autoCompleteObject, ensuring consistent autocompletion behavior.
- Updated TemplateEditor to utilize objectData for autocompletion, improving user experience in template editing.
2026-08-10 03:33:01 +01:00
7 changed files with 207 additions and 91 deletions

View File

@ -26,7 +26,7 @@
"@codemirror/state": "6.7.1",
"@codemirror/theme-one-dark": "^6.1.3",
"@codemirror/view": "6.39.12",
"@lezer/common": "^1.5.0",
"@lezer/common": "1.5.0",
"@lezer/highlight": "^1.2.3",
"@lezer/lr": "^1.4.8",
"@simplewebauthn/browser": "^13.1.2",
@ -497,7 +497,7 @@
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "3.1.2", "@jridgewell/sourcemap-codec": "1.5.5" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
"@lezer/common": ["@lezer/common@1.5.2", "", {}, "sha512-sxQE460fPZyU3sdc8lafxiPwJHBzZRy/udNFynGQky1SePYBdhkBl1kOagA9uT3pxR8K09bOrmTUqA9wb/PjSQ=="],
"@lezer/common": ["@lezer/common@1.5.0", "", {}, "sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA=="],
"@lezer/cpp": ["@lezer/cpp@1.1.5", "", { "dependencies": { "@lezer/common": "1.5.0", "@lezer/highlight": "1.2.3", "@lezer/lr": "1.4.8" } }, "sha512-DIhSXmYtJKLehrjzDFN+2cPt547ySQ41nA8yqcDf/GxMc+YM736xqltFkvADL2M0VebU5I+3+4ks2Vv+Kyq3Aw=="],
@ -2743,27 +2743,9 @@
"@babel/helper-create-class-features-plugin/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
"@codemirror/autocomplete/@lezer/common": ["@lezer/common@1.5.0", "", {}, "sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA=="],
"@codemirror/commands/@lezer/common": ["@lezer/common@1.5.2", "", {}, "sha512-sxQE460fPZyU3sdc8lafxiPwJHBzZRy/udNFynGQky1SePYBdhkBl1kOagA9uT3pxR8K09bOrmTUqA9wb/PjSQ=="],
"@codemirror/lang-css/@lezer/common": ["@lezer/common@1.5.0", "", {}, "sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA=="],
"@codemirror/lang-go/@lezer/common": ["@lezer/common@1.5.0", "", {}, "sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA=="],
"@codemirror/lang-html/@lezer/common": ["@lezer/common@1.5.0", "", {}, "sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA=="],
"@codemirror/lang-javascript/@lezer/common": ["@lezer/common@1.5.0", "", {}, "sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA=="],
"@codemirror/lang-markdown/@lezer/common": ["@lezer/common@1.5.0", "", {}, "sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA=="],
"@codemirror/lang-php/@lezer/common": ["@lezer/common@1.5.0", "", {}, "sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA=="],
"@codemirror/lang-python/@lezer/common": ["@lezer/common@1.5.0", "", {}, "sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA=="],
"@codemirror/lang-sql/@lezer/common": ["@lezer/common@1.5.0", "", {}, "sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA=="],
"@codemirror/lang-xml/@lezer/common": ["@lezer/common@1.5.0", "", {}, "sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA=="],
"@codemirror/lang-yaml/@lezer/common": ["@lezer/common@1.5.0", "", {}, "sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA=="],
"@codemirror/language/@lezer/common": ["@lezer/common@1.5.2", "", {}, "sha512-sxQE460fPZyU3sdc8lafxiPwJHBzZRy/udNFynGQky1SePYBdhkBl1kOagA9uT3pxR8K09bOrmTUqA9wb/PjSQ=="],
"@codemirror/lint/crelt": ["crelt@1.0.6", "", {}, "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g=="],
@ -2809,33 +2791,7 @@
"@jimp/js-png/pngjs": ["pngjs@7.0.0", "", {}, "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow=="],
"@lezer/cpp/@lezer/common": ["@lezer/common@1.5.0", "", {}, "sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA=="],
"@lezer/css/@lezer/common": ["@lezer/common@1.5.0", "", {}, "sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA=="],
"@lezer/go/@lezer/common": ["@lezer/common@1.5.0", "", {}, "sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA=="],
"@lezer/highlight/@lezer/common": ["@lezer/common@1.5.0", "", {}, "sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA=="],
"@lezer/html/@lezer/common": ["@lezer/common@1.5.0", "", {}, "sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA=="],
"@lezer/java/@lezer/common": ["@lezer/common@1.5.0", "", {}, "sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA=="],
"@lezer/javascript/@lezer/common": ["@lezer/common@1.5.0", "", {}, "sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA=="],
"@lezer/json/@lezer/common": ["@lezer/common@1.5.0", "", {}, "sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA=="],
"@lezer/lr/@lezer/common": ["@lezer/common@1.5.0", "", {}, "sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA=="],
"@lezer/markdown/@lezer/common": ["@lezer/common@1.5.0", "", {}, "sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA=="],
"@lezer/php/@lezer/common": ["@lezer/common@1.5.0", "", {}, "sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA=="],
"@lezer/python/@lezer/common": ["@lezer/common@1.5.0", "", {}, "sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA=="],
"@lezer/rust/@lezer/common": ["@lezer/common@1.5.0", "", {}, "sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA=="],
"@lezer/xml/@lezer/common": ["@lezer/common@1.5.0", "", {}, "sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA=="],
"@lezer/yaml/@lezer/common": ["@lezer/common@1.5.2", "", {}, "sha512-sxQE460fPZyU3sdc8lafxiPwJHBzZRy/udNFynGQky1SePYBdhkBl1kOagA9uT3pxR8K09bOrmTUqA9wb/PjSQ=="],
"@malept/flatpak-bundler/fs-extra": ["fs-extra@9.1.0", "", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="],

66
pnpm-lock.yaml generated
View File

@ -80,8 +80,8 @@ importers:
specifier: 6.39.12
version: 6.39.12
'@lezer/common':
specifier: ^1.5.0
version: 1.5.2
specifier: 1.5.0
version: 1.5.0
'@lezer/highlight':
specifier: ^1.2.3
version: 1.2.3
@ -1376,8 +1376,8 @@ packages:
'@jridgewell/trace-mapping@0.3.9':
resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
'@lezer/common@1.5.2':
resolution: {integrity: sha512-sxQE460fPZyU3sdc8lafxiPwJHBzZRy/udNFynGQky1SePYBdhkBl1kOagA9uT3pxR8K09bOrmTUqA9wb/PjSQ==}
'@lezer/common@1.5.0':
resolution: {integrity: sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA==}
'@lezer/cpp@1.1.5':
resolution: {integrity: sha512-DIhSXmYtJKLehrjzDFN+2cPt547ySQ41nA8yqcDf/GxMc+YM736xqltFkvADL2M0VebU5I+3+4ks2Vv+Kyq3Aw==}
@ -6908,14 +6908,14 @@ snapshots:
'@codemirror/language': 6.12.1
'@codemirror/state': 6.7.1
'@codemirror/view': 6.39.12
'@lezer/common': 1.5.2
'@lezer/common': 1.5.0
'@codemirror/commands@6.10.4':
dependencies:
'@codemirror/language': 6.12.1
'@codemirror/state': 6.7.1
'@codemirror/view': 6.39.12
'@lezer/common': 1.5.2
'@lezer/common': 1.5.0
'@codemirror/lang-cpp@6.0.3':
dependencies:
@ -6927,7 +6927,7 @@ snapshots:
'@codemirror/autocomplete': 6.20.0
'@codemirror/language': 6.12.1
'@codemirror/state': 6.7.1
'@lezer/common': 1.5.2
'@lezer/common': 1.5.0
'@lezer/css': 1.3.0
'@codemirror/lang-go@6.0.1':
@ -6935,7 +6935,7 @@ snapshots:
'@codemirror/autocomplete': 6.20.0
'@codemirror/language': 6.12.1
'@codemirror/state': 6.7.1
'@lezer/common': 1.5.2
'@lezer/common': 1.5.0
'@lezer/go': 1.0.1
'@codemirror/lang-html@6.4.11':
@ -6946,7 +6946,7 @@ snapshots:
'@codemirror/language': 6.12.1
'@codemirror/state': 6.7.1
'@codemirror/view': 6.39.12
'@lezer/common': 1.5.2
'@lezer/common': 1.5.0
'@lezer/css': 1.3.0
'@lezer/html': 1.3.13
@ -6962,7 +6962,7 @@ snapshots:
'@codemirror/lint': 6.9.3
'@codemirror/state': 6.7.1
'@codemirror/view': 6.39.12
'@lezer/common': 1.5.2
'@lezer/common': 1.5.0
'@lezer/javascript': 1.5.4
'@codemirror/lang-json@6.0.2':
@ -6977,7 +6977,7 @@ snapshots:
'@codemirror/language': 6.12.1
'@codemirror/state': 6.7.1
'@codemirror/view': 6.39.12
'@lezer/common': 1.5.2
'@lezer/common': 1.5.0
'@lezer/markdown': 1.6.3
'@codemirror/lang-php@6.0.2':
@ -6985,7 +6985,7 @@ snapshots:
'@codemirror/lang-html': 6.4.11
'@codemirror/language': 6.12.1
'@codemirror/state': 6.7.1
'@lezer/common': 1.5.2
'@lezer/common': 1.5.0
'@lezer/php': 1.0.5
'@codemirror/lang-python@6.2.1':
@ -6993,7 +6993,7 @@ snapshots:
'@codemirror/autocomplete': 6.20.0
'@codemirror/language': 6.12.1
'@codemirror/state': 6.7.1
'@lezer/common': 1.5.2
'@lezer/common': 1.5.0
'@lezer/python': 1.1.18
'@codemirror/lang-rust@6.0.2':
@ -7006,7 +7006,7 @@ snapshots:
'@codemirror/autocomplete': 6.20.0
'@codemirror/language': 6.12.1
'@codemirror/state': 6.7.1
'@lezer/common': 1.5.2
'@lezer/common': 1.5.0
'@lezer/highlight': 1.2.3
'@lezer/lr': 1.4.8
@ -7016,7 +7016,7 @@ snapshots:
'@codemirror/language': 6.12.1
'@codemirror/state': 6.7.1
'@codemirror/view': 6.39.12
'@lezer/common': 1.5.2
'@lezer/common': 1.5.0
'@lezer/xml': 1.0.6
'@codemirror/lang-yaml@6.1.2':
@ -7024,7 +7024,7 @@ snapshots:
'@codemirror/autocomplete': 6.20.0
'@codemirror/language': 6.12.1
'@codemirror/state': 6.7.1
'@lezer/common': 1.5.2
'@lezer/common': 1.5.0
'@lezer/highlight': 1.2.3
'@lezer/lr': 1.4.8
'@lezer/yaml': 1.0.4
@ -7033,7 +7033,7 @@ snapshots:
dependencies:
'@codemirror/state': 6.7.1
'@codemirror/view': 6.39.12
'@lezer/common': 1.5.2
'@lezer/common': 1.5.0
'@lezer/highlight': 1.2.3
'@lezer/lr': 1.4.8
style-mod: 4.1.3
@ -7894,90 +7894,90 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.5
'@lezer/common@1.5.2': {}
'@lezer/common@1.5.0': {}
'@lezer/cpp@1.1.5':
dependencies:
'@lezer/common': 1.5.2
'@lezer/common': 1.5.0
'@lezer/highlight': 1.2.3
'@lezer/lr': 1.4.8
'@lezer/css@1.3.0':
dependencies:
'@lezer/common': 1.5.2
'@lezer/common': 1.5.0
'@lezer/highlight': 1.2.3
'@lezer/lr': 1.4.8
'@lezer/go@1.0.1':
dependencies:
'@lezer/common': 1.5.2
'@lezer/common': 1.5.0
'@lezer/highlight': 1.2.3
'@lezer/lr': 1.4.8
'@lezer/highlight@1.2.3':
dependencies:
'@lezer/common': 1.5.2
'@lezer/common': 1.5.0
'@lezer/html@1.3.13':
dependencies:
'@lezer/common': 1.5.2
'@lezer/common': 1.5.0
'@lezer/highlight': 1.2.3
'@lezer/lr': 1.4.8
'@lezer/java@1.1.3':
dependencies:
'@lezer/common': 1.5.2
'@lezer/common': 1.5.0
'@lezer/highlight': 1.2.3
'@lezer/lr': 1.4.8
'@lezer/javascript@1.5.4':
dependencies:
'@lezer/common': 1.5.2
'@lezer/common': 1.5.0
'@lezer/highlight': 1.2.3
'@lezer/lr': 1.4.8
'@lezer/json@1.0.3':
dependencies:
'@lezer/common': 1.5.2
'@lezer/common': 1.5.0
'@lezer/highlight': 1.2.3
'@lezer/lr': 1.4.8
'@lezer/lr@1.4.8':
dependencies:
'@lezer/common': 1.5.2
'@lezer/common': 1.5.0
'@lezer/markdown@1.6.3':
dependencies:
'@lezer/common': 1.5.2
'@lezer/common': 1.5.0
'@lezer/highlight': 1.2.3
'@lezer/php@1.0.5':
dependencies:
'@lezer/common': 1.5.2
'@lezer/common': 1.5.0
'@lezer/highlight': 1.2.3
'@lezer/lr': 1.4.8
'@lezer/python@1.1.18':
dependencies:
'@lezer/common': 1.5.2
'@lezer/common': 1.5.0
'@lezer/highlight': 1.2.3
'@lezer/lr': 1.4.8
'@lezer/rust@1.0.2':
dependencies:
'@lezer/common': 1.5.2
'@lezer/common': 1.5.0
'@lezer/highlight': 1.2.3
'@lezer/lr': 1.4.8
'@lezer/xml@1.0.6':
dependencies:
'@lezer/common': 1.5.2
'@lezer/common': 1.5.0
'@lezer/highlight': 1.2.3
'@lezer/lr': 1.4.8
'@lezer/yaml@1.0.4':
dependencies:
'@lezer/common': 1.5.2
'@lezer/common': 1.5.0
'@lezer/highlight': 1.2.3
'@lezer/lr': 1.4.8

View File

@ -8,9 +8,22 @@ import {
} from '@codemirror/language'
import { styleTags, tags as t } from '@lezer/highlight'
import { parseMixed } from '@lezer/common'
import { javascriptLanguage } from '@codemirror/lang-javascript'
import { xmlLanguage } from '@codemirror/lang-xml'
import {
javascriptLanguage,
scopeCompletionSource,
localCompletionSource
} from '@codemirror/lang-javascript'
import {
xmlLanguage,
completeFromSchema,
autoCloseTags
} from '@codemirror/lang-xml'
import { parser as ejsParser } from './ejs.parser.js'
import {
fcTemplateElements,
fcTemplateAttributes,
fcTemplateHelpers
} from './schema.js'
/**
* FarmControl document template language: custom XML tags with EJS
@ -18,6 +31,7 @@ import { parser as ejsParser } from './ejs.parser.js'
* XML and JavaScript each get their own highlighting/support.
*
* @see https://codemirror.net/examples/mixed-language/
* @see https://codemirror.net/examples/autocompletion/
*/
const fcTemplateParser = ejsParser.configure({
props: [
@ -60,9 +74,42 @@ export const fcTemplateLanguage = LRLanguage.define({
}
})
function buildJsScope(autoCompleteObject) {
let data = autoCompleteObject
if (typeof data === 'string') {
try {
data = JSON.parse(data)
} catch {
data = {}
}
}
if (!data || typeof data !== 'object' || Array.isArray(data)) {
data = {}
}
return {
...data,
fc: fcTemplateHelpers
}
}
/**
* Language support for FarmControl EJS+XML document templates.
* @param {{ autoCompleteObject?: object|string }} [options]
*/
export function fcTemplateLang() {
return new LanguageSupport(fcTemplateLanguage)
export function fcTemplateLang(options = {}) {
const { autoCompleteObject } = options
const jsScope = buildJsScope(autoCompleteObject)
return new LanguageSupport(fcTemplateLanguage, [
xmlLanguage.data.of({
autocomplete: completeFromSchema(
fcTemplateElements,
fcTemplateAttributes
)
}),
autoCloseTags,
javascriptLanguage.data.of({
autocomplete: [localCompletionSource, scopeCompletionSource(jsScope)]
})
])
}

View File

@ -0,0 +1,106 @@
/**
* XML schema for FarmControl document template tags.
* Mirrors custom elements / style attrs handled in farmcontrol-ws TemplateManager.
*/
const styleAttrs = [
'padding',
'width',
'height',
'maxWidth',
'maxHeight',
'gap',
'justify',
'align',
'border',
'borderRadius',
'vertical',
'grow',
'shrink',
'color',
'background',
'scale',
'textAlign',
'textSize',
'wordWrap'
]
const justifyValues = [
'flex-start',
'flex-end',
'center',
'space-between',
'space-around',
'space-evenly'
]
const alignValues = [
'flex-start',
'flex-end',
'center',
'stretch',
'baseline'
]
/** @type {import('@codemirror/lang-xml').AttrSpec[]} */
export const fcTemplateAttributes = [
...styleAttrs.map((name) => {
const attr = { name, global: true }
if (name === 'vertical') attr.values = ['true', 'false']
if (name === 'justify') attr.values = justifyValues
if (name === 'align') attr.values = alignValues
if (name === 'textAlign') {
attr.values = ['left', 'center', 'right', 'justify']
}
return attr
}),
{
name: 'format',
values: ['code128', 'code39', 'ean13', 'ean8', 'upc', 'qrcode']
},
{ name: 'barcodeWidth' },
{
name: 'type',
values: ['header', 'footer', 'body']
}
]
const allTags = [
'Flex',
'Container',
'Title1',
'Title2',
'Title3',
'Title4',
'Text',
'Bold',
'Divider',
'ProgressBar',
'Barcode',
'DateTime',
'Table',
'Row',
'Col'
]
/** @type {import('@codemirror/lang-xml').ElementSpec[]} */
export const fcTemplateElements = allTags.map((name) => {
const el = { name, top: true, children: allTags }
if (name === 'Barcode') {
el.attributes = ['format', 'barcodeWidth', ...styleAttrs]
} else if (name === 'Row') {
el.attributes = ['type', ...styleAttrs]
} else if (name === 'Divider') {
el.children = []
}
return el
})
/** Runtime helpers available as `fc` inside templates. */
export const fcTemplateHelpers = {
listObjects: async () => [],
getObject: async () => ({}),
formatDate: () => ''
}

View File

@ -32,7 +32,8 @@ export default function CodeBlockEditor({
height = 'auto',
showLineNumbers = true,
disabled = false,
minimal = false
minimal = false,
autoCompleteObject = null
}) {
const { isDarkMode } = useThemeContext()
const [codeMirrorOpen, setCodeMirrorOpen] = useState(false)
@ -57,7 +58,7 @@ export default function CodeBlockEditor({
return xml()
case 'fctemplatelang':
case 'ejs':
return fcTemplateLang()
return fcTemplateLang({ autoCompleteObject })
case 'html':
return html()
case 'css':
@ -86,7 +87,7 @@ export default function CodeBlockEditor({
default:
return javascript() // Default fallback
}
}, [language])
}, [language, autoCompleteObject])
const handleOnChange = (value) => {
if (typeof code == 'object' && language == 'json') {
@ -178,7 +179,7 @@ export default function CodeBlockEditor({
}
CodeBlockEditor.propTypes = {
code: PropTypes.string.isRequired,
code: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired,
language: PropTypes.oneOfType([
PropTypes.string,
PropTypes.arrayOf(PropTypes.string)
@ -190,5 +191,6 @@ CodeBlockEditor.propTypes = {
height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
showLineNumbers: PropTypes.bool,
disabled: PropTypes.bool,
minimal: PropTypes.bool
minimal: PropTypes.bool,
autoCompleteObject: PropTypes.oneOfType([PropTypes.object, PropTypes.string])
}

View File

@ -111,6 +111,7 @@ const ObjectProperty = ({
initial = false,
height = 'auto',
minimal = false,
autoCompleteObject = null,
previewOpen = false,
showPreview = true,
useFormItem = true,
@ -399,6 +400,7 @@ const ObjectProperty = ({
height={height}
readOnly={true}
minimal={minimal}
autoCompleteObject={autoCompleteObject}
/>
)
} else {
@ -906,6 +908,7 @@ const ObjectProperty = ({
language={language}
height={height}
minimal={minimal}
autoCompleteObject={autoCompleteObject}
{...inputProps}
/>
)
@ -1037,6 +1040,7 @@ ObjectProperty.propTypes = {
required: PropTypes.bool,
name: PropTypes.string,
language: PropTypes.string,
autoCompleteObject: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
prefix: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
suffix: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
min: PropTypes.number,

View File

@ -92,6 +92,7 @@ const TemplateEditor = ({
language={'fcTemplateLang'}
objectData={objectData}
isEditing={isEditing}
autoCompleteObject={objectData?.testObject}
/>
</div>
</Flex>