@veltra/desktop 1.2.18 → 1.2.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (20) hide show
  1. package/dist/components/action/action-group.vue.d.ts +1 -1
  2. package/dist/components/action/action.vue.d.ts +1 -1
  3. package/dist/components/code-editor/code-editor.js +8 -13
  4. package/dist/components/code-editor/code-editor.js.map +1 -1
  5. package/dist/components/code-editor/lang-loaders.js +16 -0
  6. package/dist/components/code-editor/lang-loaders.js.map +1 -0
  7. package/dist/components/pop-confirm/pop-confirm.vue.d.ts +1 -1
  8. package/dist/components/tip/tip.vue.d.ts +1 -1
  9. package/dist/node_modules/.bun/@codemirror_commands@6.10.4/node_modules/@codemirror/commands/dist/index.js +1 -1
  10. package/dist/node_modules/.bun/@codemirror_lang-java@6.0.2/node_modules/@codemirror/lang-java/dist/index.js +1 -1
  11. package/dist/node_modules/.bun/@codemirror_lang-javascript@6.2.5/node_modules/@codemirror/lang-javascript/dist/index.js +2 -2
  12. package/dist/node_modules/.bun/@codemirror_lang-sql@6.10.0/node_modules/@codemirror/lang-sql/dist/index.js +1 -1
  13. package/dist/node_modules/.bun/@codemirror_language@6.12.4/node_modules/@codemirror/language/dist/index.js +2 -2
  14. package/dist/node_modules/.bun/@codemirror_theme-one-dark@6.1.3/node_modules/@codemirror/theme-one-dark/dist/index.js +1 -1
  15. package/dist/node_modules/.bun/@lezer_java@1.1.3/node_modules/@lezer/java/dist/index.js +1 -1
  16. package/dist/node_modules/.bun/@lezer_javascript@1.5.4/node_modules/@lezer/javascript/dist/index.js +1 -1
  17. package/dist/node_modules/.bun/@lezer_json@1.0.3/node_modules/@lezer/json/dist/index.js +1 -1
  18. package/package.json +6 -6
  19. package/src/components/code-editor/code-editor.vue +11 -15
  20. package/src/components/code-editor/lang-loaders.ts +16 -0
@@ -9,9 +9,9 @@ declare const __VLS_base: import("vue").DefineComponent<ActionGroupProps, _Actio
9
9
  type: import("@veltra/utils").ColorType;
10
10
  text: boolean;
11
11
  size: "small" | "default" | "large";
12
- circle: boolean;
13
12
  max: number;
14
13
  loading: boolean;
14
+ circle: boolean;
15
15
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
16
16
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
17
17
  declare const _default: typeof __VLS_export;
@@ -15,8 +15,8 @@ declare const __VLS_base: import("vue").DefineComponent<ActionProps, {}, {}, {},
15
15
  type: ButtonType;
16
16
  text: boolean;
17
17
  size: import("@veltra/utils").ComponentSize;
18
- circle: boolean;
19
18
  loading: boolean;
19
+ circle: boolean;
20
20
  inDropdown: boolean;
21
21
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
22
22
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -1,12 +1,9 @@
1
1
  import _sfc_main$1 from "../scroll/scroll.js";
2
2
  import { Compartment, EditorState } from "../../node_modules/.bun/@codemirror_state@6.7.0/node_modules/@codemirror/state/dist/index.js";
3
3
  import { EditorView, ViewPlugin, tooltips } from "../../node_modules/.bun/@codemirror_view@6.43.4/node_modules/@codemirror/view/dist/index.js";
4
- import { java } from "../../node_modules/.bun/@codemirror_lang-java@6.0.2/node_modules/@codemirror/lang-java/dist/index.js";
5
- import { javascript } from "../../node_modules/.bun/@codemirror_lang-javascript@6.2.5/node_modules/@codemirror/lang-javascript/dist/index.js";
6
- import { json } from "../../node_modules/.bun/@codemirror_lang-json@6.0.2/node_modules/@codemirror/lang-json/dist/index.js";
7
- import { sql } from "../../node_modules/.bun/@codemirror_lang-sql@6.10.0/node_modules/@codemirror/lang-sql/dist/index.js";
8
4
  import { oneDark } from "../../node_modules/.bun/@codemirror_theme-one-dark@6.1.3/node_modules/@codemirror/theme-one-dark/dist/index.js";
9
5
  import { basicSetup } from "./basic-setup.js";
6
+ import { loadLanguage } from "./lang-loaders.js";
10
7
  import { computed, createBlock, createElementVNode, defineComponent, mergeModels, normalizeClass, normalizeStyle, onBeforeUnmount, openBlock, shallowRef, unref, useModel, useTemplateRef, watch, withCtx, withKeys, withModifiers } from "vue";
11
8
  import { useFormFallbackProps } from "@veltra/compositions";
12
9
  import { bem, injectFormContext, zIndex } from "@veltra/utils";
@@ -59,13 +56,6 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
59
56
  const rootStyle = computed(() => ({ "--u-code-editor-default-lines": Math.max(1, props.defaultLines) }));
60
57
  const containerRef = useTemplateRef("container");
61
58
  const editor = shallowRef(null);
62
- /** 静态导入语言包,避免动态 import 在打包/Vite 预构建下产生多份 @codemirror/* 实例 */
63
- const langExtensions = {
64
- js: javascript({ typescript: true }),
65
- sql: sql(),
66
- java: java(),
67
- json: json()
68
- };
69
59
  const themeCompartment = new Compartment();
70
60
  const editableCompartment = new Compartment();
71
61
  const readOnlyCompartment = new Compartment();
@@ -130,12 +120,17 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
130
120
  }
131
121
  let editorToken = 0;
132
122
  let langToken = 0;
133
- function applyLanguage() {
123
+ async function applyLanguage() {
134
124
  const view = editor.value;
135
125
  if (!view) return;
136
126
  const myToken = ++langToken;
137
127
  const { language } = props;
138
- const ext = language ? langExtensions[language] : [];
128
+ if (!language) {
129
+ if (myToken !== langToken || editor.value !== view) return;
130
+ view.dispatch({ effects: langCompartment.reconfigure([]) });
131
+ return;
132
+ }
133
+ const ext = await loadLanguage(language);
139
134
  if (myToken !== langToken || editor.value !== view) return;
140
135
  view.dispatch({ effects: langCompartment.reconfigure(ext) });
141
136
  }
@@ -1 +1 @@
1
- {"version":3,"file":"code-editor.js","names":[],"sources":["../../../src/components/code-editor/code-editor.vue"],"sourcesContent":["<template>\n <u-scroll :class=\"className\" :style=\"rootStyle\" @keyup.enter.stop>\n <div ref=\"container\"></div>\n </u-scroll>\n</template>\n\n<script lang=\"ts\" setup>\nimport { java } from '@codemirror/lang-java'\nimport { javascript } from '@codemirror/lang-javascript'\nimport { json } from '@codemirror/lang-json'\nimport { sql } from '@codemirror/lang-sql'\nimport { Compartment, EditorState, type Extension } from '@codemirror/state'\nimport { oneDark } from '@codemirror/theme-one-dark'\nimport { EditorView, ViewPlugin, tooltips, type ViewUpdate } from '@codemirror/view'\nimport { useFormFallbackProps } from '@veltra/compositions'\nimport { bem, zIndex } from '@veltra/utils'\nimport { injectFormContext } from '@veltra/utils'\nimport {\n computed,\n onBeforeUnmount,\n shallowRef,\n useTemplateRef,\n watch,\n type CSSProperties\n} from 'vue'\n\nimport type { CodeEditorLang, CodeEditorProps } from '../../types'\nimport { UScroll } from '../scroll'\nimport { basicSetup } from './basic-setup'\n\ndefineOptions({ name: 'UCodeEditor' })\n\nconst props = withDefaults(defineProps<CodeEditorProps>(), {\n disabled: undefined,\n readonly: undefined,\n dark: false,\n defaultLines: 8\n})\n\nconst model = defineModel<string>()\n\nconst cls = bem('code-editor')\n\nconst { formProps } = injectFormContext()\n\nconst { disabled, readonly } = useFormFallbackProps([formProps ?? {}, props], {\n disabled: false,\n readonly: false\n})\n\nconst className = computed<string[]>(() => [\n cls.b,\n bem.is('disabled', disabled.value),\n bem.is('readonly', readonly.value),\n bem.is('dark', props.dark)\n])\n\nconst rootStyle = computed<CSSProperties>(() => ({\n '--u-code-editor-default-lines': Math.max(1, props.defaultLines)\n}))\n\nconst containerRef = useTemplateRef('container')\nconst editor = shallowRef<EditorView | null>(null)\n\n/** 静态导入语言包,避免动态 import 在打包/Vite 预构建下产生多份 @codemirror/* 实例 */\nconst langExtensions: Record<CodeEditorLang, Extension> = {\n js: javascript({ typescript: true }),\n sql: sql(),\n java: java(),\n json: json()\n}\n\nconst themeCompartment = new Compartment()\nconst editableCompartment = new Compartment()\nconst readOnlyCompartment = new Compartment()\nconst langCompartment = new Compartment()\n\nlet phantomGutter: HTMLElement | null = null\nlet phantomContainer: HTMLElement | null = null\nlet lastPhantomKey = ''\n\nfunction resetPhantomCache() {\n phantomGutter = null\n phantomContainer = null\n lastPhantomKey = ''\n}\n\n/**\n * 在 .cm-lineNumbers 末尾追加占位行号 DOM,使可视行号数量补齐到 defaultLines。\n * CodeMirror 的 lineNumbers() 仅为真实文档行渲染行号,超出部分由本逻辑补全。\n */\nfunction syncPhantomLineNumbers() {\n const view = editor.value\n if (!view) return\n\n if (!phantomGutter || !phantomGutter.isConnected) {\n phantomGutter = view.dom.querySelector<HTMLElement>('.cm-gutter.cm-lineNumbers')\n }\n if (!phantomGutter) return\n\n if (!phantomContainer) {\n phantomContainer = document.createElement('div')\n phantomContainer.className = 'cm-phantom-lines'\n }\n if (\n phantomContainer.parentElement !== phantomGutter ||\n phantomContainer !== phantomGutter.lastElementChild\n ) {\n phantomGutter.appendChild(phantomContainer)\n }\n\n const realLines = view.state.doc.lines\n const target = Math.max(0, Math.max(1, props.defaultLines) - realLines)\n const lineHeight = view.defaultLineHeight\n\n const key = `${realLines}|${target}|${lineHeight}`\n if (key === lastPhantomKey) return\n lastPhantomKey = key\n\n while (phantomContainer.children.length > target) {\n phantomContainer.lastElementChild!.remove()\n }\n while (phantomContainer.children.length < target) {\n const el = document.createElement('div')\n el.className = 'cm-gutterElement cm-gutterElement-phantom'\n phantomContainer.appendChild(el)\n }\n for (let i = 0; i < target; i++) {\n const el = phantomContainer.children[i] as HTMLElement\n const num = String(realLines + i + 1)\n if (el.textContent !== num) el.textContent = num\n if (lineHeight && el.style.height !== `${lineHeight}px`) {\n el.style.height = `${lineHeight}px`\n }\n }\n}\n\nconst phantomLineNumbersPlugin = ViewPlugin.fromClass(\n class {\n update(update: ViewUpdate) {\n if (update.docChanged || update.geometryChanged) {\n syncPhantomLineNumbers()\n }\n }\n }\n)\n\nfunction buildExtensions(): Extension[] {\n return [\n basicSetup,\n tooltips({ parent: document.body }),\n EditorView.theme({ '.cm-tooltip': { zIndex: zIndex() } }),\n themeCompartment.of(props.dark ? oneDark : []),\n editableCompartment.of(EditorView.editable.of(!disabled.value)),\n readOnlyCompartment.of(EditorState.readOnly.of(readonly.value)),\n langCompartment.of([]),\n phantomLineNumbersPlugin\n ]\n}\n\nlet editorToken = 0\nlet langToken = 0\n\nfunction applyLanguage() {\n const view = editor.value\n if (!view) return\n const myToken = ++langToken\n const { language } = props\n const ext = language ? langExtensions[language] : []\n if (myToken !== langToken || editor.value !== view) return\n view.dispatch({ effects: langCompartment.reconfigure(ext) })\n}\n\nfunction destroyEditor() {\n ++editorToken\n ++langToken\n editor.value?.destroy()\n editor.value = null\n resetPhantomCache()\n}\n\nfunction createEditor() {\n destroyEditor()\n const myToken = ++editorToken\n const parent = containerRef.value\n if (!parent) return\n\n const view = new EditorView({\n doc: model.value,\n extensions: buildExtensions(),\n parent,\n dispatch(tr) {\n view.update([tr])\n if (tr.docChanged) {\n model.value = tr.state.doc.toString()\n }\n }\n })\n\n if (myToken !== editorToken) {\n view.destroy()\n return\n }\n\n editor.value = view\n syncPhantomLineNumbers()\n applyLanguage()\n}\n\nwatch(\n containerRef,\n (el) => {\n if (el) createEditor()\n else destroyEditor()\n },\n { immediate: true, flush: 'post' }\n)\n\nwatch(() => props.language, applyLanguage)\n\nwatch(\n () => props.dark,\n (dark) => {\n editor.value?.dispatch({ effects: themeCompartment.reconfigure(dark ? oneDark : []) })\n }\n)\n\nwatch(disabled, (v) => {\n editor.value?.dispatch({ effects: editableCompartment.reconfigure(EditorView.editable.of(!v)) })\n})\n\nwatch(readonly, (v) => {\n editor.value?.dispatch({ effects: readOnlyCompartment.reconfigure(EditorState.readOnly.of(v)) })\n})\n\nwatch(() => props.defaultLines, syncPhantomLineNumbers)\n\nwatch(\n [() => props.modelValue, editor],\n ([v, e]) => {\n if (!e) return\n if (e.composing) return\n const next = v ?? ''\n if (e.state.doc.toString() === next) return\n\n const valueLength = next.length\n const inRange = e.state.selection.ranges.every(\n (range) => range.anchor <= valueLength && range.head <= valueLength\n )\n e.dispatch({\n changes: { from: 0, to: e.state.doc.length, insert: next },\n selection: inRange ? e.state.selection : { anchor: 0, head: 0 },\n scrollIntoView: true\n })\n },\n { immediate: true }\n)\n\nonBeforeUnmount(destroyEditor)\n</script>\n"],"mappings":"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"}
1
+ {"version":3,"file":"code-editor.js","names":[],"sources":["../../../src/components/code-editor/code-editor.vue"],"sourcesContent":["<template>\n <u-scroll :class=\"className\" :style=\"rootStyle\" @keyup.enter.stop>\n <div ref=\"container\"></div>\n </u-scroll>\n</template>\n\n<script lang=\"ts\" setup>\nimport { Compartment, EditorState, type Extension } from '@codemirror/state'\nimport { oneDark } from '@codemirror/theme-one-dark'\nimport { EditorView, ViewPlugin, tooltips, type ViewUpdate } from '@codemirror/view'\nimport { useFormFallbackProps } from '@veltra/compositions'\nimport { bem, zIndex } from '@veltra/utils'\nimport { injectFormContext } from '@veltra/utils'\nimport {\n computed,\n onBeforeUnmount,\n shallowRef,\n useTemplateRef,\n watch,\n type CSSProperties\n} from 'vue'\n\nimport type { CodeEditorProps } from '../../types'\nimport { UScroll } from '../scroll'\nimport { basicSetup } from './basic-setup'\nimport { loadLanguage } from './lang-loaders'\n\ndefineOptions({ name: 'UCodeEditor' })\n\nconst props = withDefaults(defineProps<CodeEditorProps>(), {\n disabled: undefined,\n readonly: undefined,\n dark: false,\n defaultLines: 8\n})\n\nconst model = defineModel<string>()\n\nconst cls = bem('code-editor')\n\nconst { formProps } = injectFormContext()\n\nconst { disabled, readonly } = useFormFallbackProps([formProps ?? {}, props], {\n disabled: false,\n readonly: false\n})\n\nconst className = computed<string[]>(() => [\n cls.b,\n bem.is('disabled', disabled.value),\n bem.is('readonly', readonly.value),\n bem.is('dark', props.dark)\n])\n\nconst rootStyle = computed<CSSProperties>(() => ({\n '--u-code-editor-default-lines': Math.max(1, props.defaultLines)\n}))\n\nconst containerRef = useTemplateRef('container')\nconst editor = shallowRef<EditorView | null>(null)\n\nconst themeCompartment = new Compartment()\nconst editableCompartment = new Compartment()\nconst readOnlyCompartment = new Compartment()\nconst langCompartment = new Compartment()\n\nlet phantomGutter: HTMLElement | null = null\nlet phantomContainer: HTMLElement | null = null\nlet lastPhantomKey = ''\n\nfunction resetPhantomCache() {\n phantomGutter = null\n phantomContainer = null\n lastPhantomKey = ''\n}\n\n/**\n * 在 .cm-lineNumbers 末尾追加占位行号 DOM,使可视行号数量补齐到 defaultLines。\n * CodeMirror 的 lineNumbers() 仅为真实文档行渲染行号,超出部分由本逻辑补全。\n */\nfunction syncPhantomLineNumbers() {\n const view = editor.value\n if (!view) return\n\n if (!phantomGutter || !phantomGutter.isConnected) {\n phantomGutter = view.dom.querySelector<HTMLElement>('.cm-gutter.cm-lineNumbers')\n }\n if (!phantomGutter) return\n\n if (!phantomContainer) {\n phantomContainer = document.createElement('div')\n phantomContainer.className = 'cm-phantom-lines'\n }\n if (\n phantomContainer.parentElement !== phantomGutter ||\n phantomContainer !== phantomGutter.lastElementChild\n ) {\n phantomGutter.appendChild(phantomContainer)\n }\n\n const realLines = view.state.doc.lines\n const target = Math.max(0, Math.max(1, props.defaultLines) - realLines)\n const lineHeight = view.defaultLineHeight\n\n const key = `${realLines}|${target}|${lineHeight}`\n if (key === lastPhantomKey) return\n lastPhantomKey = key\n\n while (phantomContainer.children.length > target) {\n phantomContainer.lastElementChild!.remove()\n }\n while (phantomContainer.children.length < target) {\n const el = document.createElement('div')\n el.className = 'cm-gutterElement cm-gutterElement-phantom'\n phantomContainer.appendChild(el)\n }\n for (let i = 0; i < target; i++) {\n const el = phantomContainer.children[i] as HTMLElement\n const num = String(realLines + i + 1)\n if (el.textContent !== num) el.textContent = num\n if (lineHeight && el.style.height !== `${lineHeight}px`) {\n el.style.height = `${lineHeight}px`\n }\n }\n}\n\nconst phantomLineNumbersPlugin = ViewPlugin.fromClass(\n class {\n update(update: ViewUpdate) {\n if (update.docChanged || update.geometryChanged) {\n syncPhantomLineNumbers()\n }\n }\n }\n)\n\nfunction buildExtensions(): Extension[] {\n return [\n basicSetup,\n tooltips({ parent: document.body }),\n EditorView.theme({ '.cm-tooltip': { zIndex: zIndex() } }),\n themeCompartment.of(props.dark ? oneDark : []),\n editableCompartment.of(EditorView.editable.of(!disabled.value)),\n readOnlyCompartment.of(EditorState.readOnly.of(readonly.value)),\n langCompartment.of([]),\n phantomLineNumbersPlugin\n ]\n}\n\nlet editorToken = 0\nlet langToken = 0\n\nasync function applyLanguage() {\n const view = editor.value\n if (!view) return\n const myToken = ++langToken\n const { language } = props\n\n if (!language) {\n if (myToken !== langToken || editor.value !== view) return\n view.dispatch({ effects: langCompartment.reconfigure([]) })\n return\n }\n\n const ext = await loadLanguage(language)\n if (myToken !== langToken || editor.value !== view) return\n view.dispatch({ effects: langCompartment.reconfigure(ext) })\n}\n\nfunction destroyEditor() {\n ++editorToken\n ++langToken\n editor.value?.destroy()\n editor.value = null\n resetPhantomCache()\n}\n\nfunction createEditor() {\n destroyEditor()\n const myToken = ++editorToken\n const parent = containerRef.value\n if (!parent) return\n\n const view = new EditorView({\n doc: model.value,\n extensions: buildExtensions(),\n parent,\n dispatch(tr) {\n view.update([tr])\n if (tr.docChanged) {\n model.value = tr.state.doc.toString()\n }\n }\n })\n\n if (myToken !== editorToken) {\n view.destroy()\n return\n }\n\n editor.value = view\n syncPhantomLineNumbers()\n applyLanguage()\n}\n\nwatch(\n containerRef,\n (el) => {\n if (el) createEditor()\n else destroyEditor()\n },\n { immediate: true, flush: 'post' }\n)\n\nwatch(() => props.language, applyLanguage)\n\nwatch(\n () => props.dark,\n (dark) => {\n editor.value?.dispatch({ effects: themeCompartment.reconfigure(dark ? oneDark : []) })\n }\n)\n\nwatch(disabled, (v) => {\n editor.value?.dispatch({ effects: editableCompartment.reconfigure(EditorView.editable.of(!v)) })\n})\n\nwatch(readonly, (v) => {\n editor.value?.dispatch({ effects: readOnlyCompartment.reconfigure(EditorState.readOnly.of(v)) })\n})\n\nwatch(() => props.defaultLines, syncPhantomLineNumbers)\n\nwatch(\n [() => props.modelValue, editor],\n ([v, e]) => {\n if (!e) return\n if (e.composing) return\n const next = v ?? ''\n if (e.state.doc.toString() === next) return\n\n const valueLength = next.length\n const inRange = e.state.selection.ranges.every(\n (range) => range.anchor <= valueLength && range.head <= valueLength\n )\n e.dispatch({\n changes: { from: 0, to: e.state.doc.length, insert: next },\n selection: inRange ? e.state.selection : { anchor: 0, head: 0 },\n scrollIntoView: true\n })\n },\n { immediate: true }\n)\n\nonBeforeUnmount(destroyEditor)\n</script>\n"],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ //#region src/components/code-editor/lang-loaders.ts
2
+ /** 语言包动态加载器,新增语言只需在此注册一条 */
3
+ const LANG_LOADERS = {
4
+ js: () => import("../../node_modules/.bun/@codemirror_lang-javascript@6.2.5/node_modules/@codemirror/lang-javascript/dist/index.js").then((m) => m.javascript({ typescript: true })),
5
+ sql: () => import("../../node_modules/.bun/@codemirror_lang-sql@6.10.0/node_modules/@codemirror/lang-sql/dist/index.js").then((m) => m.sql()),
6
+ java: () => import("../../node_modules/.bun/@codemirror_lang-java@6.0.2/node_modules/@codemirror/lang-java/dist/index.js").then((m) => m.java()),
7
+ json: () => import("../../node_modules/.bun/@codemirror_lang-json@6.0.2/node_modules/@codemirror/lang-json/dist/index.js").then((m) => m.json())
8
+ };
9
+ /** 按需加载语言扩展;模块缓存由运行时保证,重复切换同一语言不会重复下载 */
10
+ function loadLanguage(lang) {
11
+ return LANG_LOADERS[lang]();
12
+ }
13
+ //#endregion
14
+ export { loadLanguage };
15
+
16
+ //# sourceMappingURL=lang-loaders.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lang-loaders.js","names":[],"sources":["../../../src/components/code-editor/lang-loaders.ts"],"sourcesContent":["import type { Extension } from '@codemirror/state'\n\nimport type { CodeEditorLang } from '../../types'\n\n/** 语言包动态加载器,新增语言只需在此注册一条 */\nconst LANG_LOADERS: Record<CodeEditorLang, () => Promise<Extension>> = {\n js: () => import('@codemirror/lang-javascript').then((m) => m.javascript({ typescript: true })),\n sql: () => import('@codemirror/lang-sql').then((m) => m.sql()),\n java: () => import('@codemirror/lang-java').then((m) => m.java()),\n json: () => import('@codemirror/lang-json').then((m) => m.json())\n}\n\n/** 按需加载语言扩展;模块缓存由运行时保证,重复切换同一语言不会重复下载 */\nexport function loadLanguage(lang: CodeEditorLang): Promise<Extension> {\n return LANG_LOADERS[lang]()\n}\n"],"mappings":";;AAKA,MAAM,eAAiE;CACrE,UAAU,OAAO,mHAA8B,CAAC,MAAM,MAAM,EAAE,WAAW,EAAE,YAAY,KAAK,CAAC,CAAC;CAC9F,WAAW,OAAO,sGAAuB,CAAC,MAAM,MAAM,EAAE,IAAI,CAAC;CAC7D,YAAY,OAAO,uGAAwB,CAAC,MAAM,MAAM,EAAE,KAAK,CAAC;CAChE,YAAY,OAAO,uGAAwB,CAAC,MAAM,MAAM,EAAE,KAAK,CAAC;AAClE;;AAGA,SAAgB,aAAa,MAA0C;CACrE,OAAO,aAAa,KAAK,CAAC;AAC5B"}
@@ -12,8 +12,8 @@ declare const __VLS_base: import("vue").DefineComponent<PopConfirmProps, {}, {},
12
12
  onConfirm?: (() => any) | undefined;
13
13
  onCancel?: (() => any) | undefined;
14
14
  }>, {
15
- direction: TipDirection;
16
15
  trigger: "hover" | "click";
16
+ direction: TipDirection;
17
17
  icon: import("vue").Component;
18
18
  iconColor: string;
19
19
  confirmText: string;
@@ -9,10 +9,10 @@ declare const __VLS_base: import("vue").DefineComponent<TipProps, {}, {}, {}, {}
9
9
  }, string, import("vue").PublicProps, Readonly<TipProps> & Readonly<{
10
10
  "onUpdate:visible"?: ((value: boolean) => any) | undefined;
11
11
  }>, {
12
- direction: TipDirection;
13
12
  trigger: "hover" | "click";
14
13
  contentTag: string;
15
14
  visible: boolean;
15
+ direction: TipDirection;
16
16
  content: string;
17
17
  alignment: TipAlign;
18
18
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
@@ -1,6 +1,6 @@
1
- import { NodeProp } from "../../../../../@lezer_common@1.5.2/node_modules/@lezer/common/dist/index.js";
2
1
  import { Annotation, ChangeDesc, ChangeSet, EditorSelection, Facet, StateEffect, StateField, Text, Transaction, combineConfig, countColumn, findClusterBreak } from "../../../../../@codemirror_state@6.7.0/node_modules/@codemirror/state/dist/index.js";
3
2
  import { Direction, EditorView } from "../../../../../@codemirror_view@6.43.4/node_modules/@codemirror/view/dist/index.js";
3
+ import { NodeProp } from "../../../../../@lezer_common@1.5.2/node_modules/@lezer/common/dist/index.js";
4
4
  import { IndentContext, getIndentUnit, getIndentation, indentString, indentUnit, matchBrackets, syntaxTree } from "../../../../../@codemirror_language@6.12.4/node_modules/@codemirror/language/dist/index.js";
5
5
  //#region ../../node_modules/.bun/@codemirror+commands@6.10.4/node_modules/@codemirror/commands/dist/index.js
6
6
  /**
@@ -1,5 +1,5 @@
1
- import { parser } from "../../../../../@lezer_java@1.1.3/node_modules/@lezer/java/dist/index.js";
2
1
  import { LRLanguage, LanguageSupport, continuedIndent, delimitedIndent, flatIndent, foldInside, foldNodeProp, indentNodeProp } from "../../../../../@codemirror_language@6.12.4/node_modules/@codemirror/language/dist/index.js";
2
+ import { parser } from "../../../../../@lezer_java@1.1.3/node_modules/@lezer/java/dist/index.js";
3
3
  //#region ../../node_modules/.bun/@codemirror+lang-java@6.0.2/node_modules/@codemirror/lang-java/dist/index.js
4
4
  /**
5
5
  A language provider based on the [Lezer Java
@@ -1,9 +1,9 @@
1
- import { IterMode, NodeWeakMap } from "../../../../../@lezer_common@1.5.2/node_modules/@lezer/common/dist/index.js";
2
1
  import { EditorSelection } from "../../../../../@codemirror_state@6.7.0/node_modules/@codemirror/state/dist/index.js";
3
2
  import { EditorView } from "../../../../../@codemirror_view@6.43.4/node_modules/@codemirror/view/dist/index.js";
3
+ import { IterMode, NodeWeakMap } from "../../../../../@lezer_common@1.5.2/node_modules/@lezer/common/dist/index.js";
4
4
  import { LRLanguage, LanguageSupport, continuedIndent, defineLanguageFacet, delimitedIndent, flatIndent, foldInside, foldNodeProp, indentNodeProp, sublanguageProp, syntaxTree } from "../../../../../@codemirror_language@6.12.4/node_modules/@codemirror/language/dist/index.js";
5
- import { parser } from "../../../../../@lezer_javascript@1.5.4/node_modules/@lezer/javascript/dist/index.js";
6
5
  import { completeFromList, ifNotIn, snippetCompletion } from "../../../../../@codemirror_autocomplete@6.20.3/node_modules/@codemirror/autocomplete/dist/index.js";
6
+ import { parser } from "../../../../../@lezer_javascript@1.5.4/node_modules/@lezer/javascript/dist/index.js";
7
7
  //#region ../../node_modules/.bun/@codemirror+lang-javascript@6.2.5/node_modules/@codemirror/lang-javascript/dist/index.js
8
8
  /**
9
9
  A collection of JavaScript-related
@@ -1,7 +1,7 @@
1
- import { ExternalTokenizer, LRParser } from "../../../../../@lezer_lr@1.4.10/node_modules/@lezer/lr/dist/index.js";
2
1
  import { styleTags, tags } from "../../../../../@lezer_highlight@1.2.3/node_modules/@lezer/highlight/dist/index.js";
3
2
  import { LRLanguage, LanguageSupport, continuedIndent, foldNodeProp, indentNodeProp, syntaxTree } from "../../../../../@codemirror_language@6.12.4/node_modules/@codemirror/language/dist/index.js";
4
3
  import { completeFromList, ifNotIn } from "../../../../../@codemirror_autocomplete@6.20.3/node_modules/@codemirror/autocomplete/dist/index.js";
4
+ import { ExternalTokenizer, LRParser } from "../../../../../@lezer_lr@1.4.10/node_modules/@lezer/lr/dist/index.js";
5
5
  //#region ../../node_modules/.bun/@codemirror+lang-sql@6.10.0/node_modules/@codemirror/lang-sql/dist/index.js
6
6
  const whitespace = 36, LineComment = 1, BlockComment = 2, String$1 = 3, Number = 4, Bool = 5, Null = 6, ParenL = 7, ParenR = 8, BraceL = 9, BraceR = 10, BracketL = 11, BracketR = 12, Semi = 13, Dot = 14, Operator = 15, Punctuation = 16, SpecialVar = 17, Identifier = 18, QuotedIdentifier = 19, Keyword = 20, Type = 21, Bits = 22, Bytes = 23, Builtin = 24;
7
7
  function isAlpha(ch) {
@@ -1,8 +1,8 @@
1
- import { IterMode, NodeProp, NodeType, Parser, Tree, TreeFragment } from "../../../../../@lezer_common@1.5.2/node_modules/@lezer/common/dist/index.js";
2
- import { highlightTree, styleTags, tagHighlighter, tags } from "../../../../../@lezer_highlight@1.2.3/node_modules/@lezer/highlight/dist/index.js";
3
1
  import { EditorState, Facet, Prec, RangeSet, RangeSetBuilder, StateEffect, StateField, combineConfig, countColumn } from "../../../../../@codemirror_state@6.7.0/node_modules/@codemirror/state/dist/index.js";
4
2
  import { StyleModule } from "../../../../../style-mod@4.1.3/node_modules/style-mod/src/style-mod.js";
5
3
  import { Decoration, Direction, EditorView, GutterMarker, ViewPlugin, WidgetType, gutter, logException } from "../../../../../@codemirror_view@6.43.4/node_modules/@codemirror/view/dist/index.js";
4
+ import { IterMode, NodeProp, NodeType, Parser, Tree, TreeFragment } from "../../../../../@lezer_common@1.5.2/node_modules/@lezer/common/dist/index.js";
5
+ import { highlightTree, styleTags, tagHighlighter, tags } from "../../../../../@lezer_highlight@1.2.3/node_modules/@lezer/highlight/dist/index.js";
6
6
  //#region ../../node_modules/.bun/@codemirror+language@6.12.4/node_modules/@codemirror/language/dist/index.js
7
7
  var _a;
8
8
  /**
@@ -1,5 +1,5 @@
1
- import { tags } from "../../../../../@lezer_highlight@1.2.3/node_modules/@lezer/highlight/dist/index.js";
2
1
  import { EditorView } from "../../../../../@codemirror_view@6.43.4/node_modules/@codemirror/view/dist/index.js";
2
+ import { tags } from "../../../../../@lezer_highlight@1.2.3/node_modules/@lezer/highlight/dist/index.js";
3
3
  import { HighlightStyle, syntaxHighlighting } from "../../../../../@codemirror_language@6.12.4/node_modules/@codemirror/language/dist/index.js";
4
4
  //#region ../../node_modules/.bun/@codemirror+theme-one-dark@6.1.3/node_modules/@codemirror/theme-one-dark/dist/index.js
5
5
  const chalky = "#e5c07b", coral = "#e06c75", cyan = "#56b6c2", invalid = "#ffffff", ivory = "#abb2bf", stone = "#7d8799", malibu = "#61afef", sage = "#98c379", whiskey = "#d19a66", violet = "#c678dd", darkBackground = "#21252b", highlightBackground = "#2c313a", background = "#282c34", tooltipBackground = "#353a42", selection = "#3E4451", cursor = "#528bff";
@@ -1,5 +1,5 @@
1
- import { LRParser } from "../../../../../@lezer_lr@1.4.10/node_modules/@lezer/lr/dist/index.js";
2
1
  import { styleTags, tags } from "../../../../../@lezer_highlight@1.2.3/node_modules/@lezer/highlight/dist/index.js";
2
+ import { LRParser } from "../../../../../@lezer_lr@1.4.10/node_modules/@lezer/lr/dist/index.js";
3
3
  //#region ../../node_modules/.bun/@lezer+java@1.1.3/node_modules/@lezer/java/dist/index.js
4
4
  const javaHighlighting = styleTags({
5
5
  null: tags.null,
@@ -1,5 +1,5 @@
1
- import { ContextTracker, ExternalTokenizer, LRParser, LocalTokenGroup } from "../../../../../@lezer_lr@1.4.10/node_modules/@lezer/lr/dist/index.js";
2
1
  import { styleTags, tags } from "../../../../../@lezer_highlight@1.2.3/node_modules/@lezer/highlight/dist/index.js";
2
+ import { ContextTracker, ExternalTokenizer, LRParser, LocalTokenGroup } from "../../../../../@lezer_lr@1.4.10/node_modules/@lezer/lr/dist/index.js";
3
3
  //#region ../../node_modules/.bun/@lezer+javascript@1.5.4/node_modules/@lezer/javascript/dist/index.js
4
4
  const noSemi = 316, noSemiType = 317, incdec = 1, incdecPrefix = 2, questionDot = 3, JSXStartTag = 4, insertSemi = 318, spaces = 320, newline = 321, LineComment = 5, BlockComment = 6, Dialect_jsx = 0;
5
5
  const space = [
@@ -1,5 +1,5 @@
1
- import { LRParser } from "../../../../../@lezer_lr@1.4.10/node_modules/@lezer/lr/dist/index.js";
2
1
  import { styleTags, tags } from "../../../../../@lezer_highlight@1.2.3/node_modules/@lezer/highlight/dist/index.js";
2
+ import { LRParser } from "../../../../../@lezer_lr@1.4.10/node_modules/@lezer/lr/dist/index.js";
3
3
  //#region ../../node_modules/.bun/@lezer+json@1.0.3/node_modules/@lezer/json/dist/index.js
4
4
  const jsonHighlighting = styleTags({
5
5
  String: tags.string,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@veltra/desktop",
3
- "version": "1.2.18",
3
+ "version": "1.2.19",
4
4
  "files": [
5
5
  "dist",
6
6
  "src"
@@ -57,11 +57,11 @@
57
57
  "@cat-kit/core": ">=1.1.8",
58
58
  "@cat-kit/excel": ">=1.0.0",
59
59
  "@cat-kit/fe": "^1.1.8",
60
- "@veltra/compositions": "1.2.18",
61
- "@veltra/directives": "1.2.18",
62
- "@veltra/icons": "1.2.18",
63
- "@veltra/styles": "1.2.18",
64
- "@veltra/utils": "1.2.18",
60
+ "@veltra/compositions": "1.2.19",
61
+ "@veltra/directives": "1.2.19",
62
+ "@veltra/icons": "1.2.19",
63
+ "@veltra/styles": "1.2.19",
64
+ "@veltra/utils": "1.2.19",
65
65
  "vue": ">=3.5.39"
66
66
  },
67
67
  "devDependencies": {
@@ -5,10 +5,6 @@
5
5
  </template>
6
6
 
7
7
  <script lang="ts" setup>
8
- import { java } from '@codemirror/lang-java'
9
- import { javascript } from '@codemirror/lang-javascript'
10
- import { json } from '@codemirror/lang-json'
11
- import { sql } from '@codemirror/lang-sql'
12
8
  import { Compartment, EditorState, type Extension } from '@codemirror/state'
13
9
  import { oneDark } from '@codemirror/theme-one-dark'
14
10
  import { EditorView, ViewPlugin, tooltips, type ViewUpdate } from '@codemirror/view'
@@ -24,9 +20,10 @@ import {
24
20
  type CSSProperties
25
21
  } from 'vue'
26
22
 
27
- import type { CodeEditorLang, CodeEditorProps } from '../../types'
23
+ import type { CodeEditorProps } from '../../types'
28
24
  import { UScroll } from '../scroll'
29
25
  import { basicSetup } from './basic-setup'
26
+ import { loadLanguage } from './lang-loaders'
30
27
 
31
28
  defineOptions({ name: 'UCodeEditor' })
32
29
 
@@ -62,14 +59,6 @@ const rootStyle = computed<CSSProperties>(() => ({
62
59
  const containerRef = useTemplateRef('container')
63
60
  const editor = shallowRef<EditorView | null>(null)
64
61
 
65
- /** 静态导入语言包,避免动态 import 在打包/Vite 预构建下产生多份 @codemirror/* 实例 */
66
- const langExtensions: Record<CodeEditorLang, Extension> = {
67
- js: javascript({ typescript: true }),
68
- sql: sql(),
69
- java: java(),
70
- json: json()
71
- }
72
-
73
62
  const themeCompartment = new Compartment()
74
63
  const editableCompartment = new Compartment()
75
64
  const readOnlyCompartment = new Compartment()
@@ -161,12 +150,19 @@ function buildExtensions(): Extension[] {
161
150
  let editorToken = 0
162
151
  let langToken = 0
163
152
 
164
- function applyLanguage() {
153
+ async function applyLanguage() {
165
154
  const view = editor.value
166
155
  if (!view) return
167
156
  const myToken = ++langToken
168
157
  const { language } = props
169
- const ext = language ? langExtensions[language] : []
158
+
159
+ if (!language) {
160
+ if (myToken !== langToken || editor.value !== view) return
161
+ view.dispatch({ effects: langCompartment.reconfigure([]) })
162
+ return
163
+ }
164
+
165
+ const ext = await loadLanguage(language)
170
166
  if (myToken !== langToken || editor.value !== view) return
171
167
  view.dispatch({ effects: langCompartment.reconfigure(ext) })
172
168
  }
@@ -0,0 +1,16 @@
1
+ import type { Extension } from '@codemirror/state'
2
+
3
+ import type { CodeEditorLang } from '../../types'
4
+
5
+ /** 语言包动态加载器,新增语言只需在此注册一条 */
6
+ const LANG_LOADERS: Record<CodeEditorLang, () => Promise<Extension>> = {
7
+ js: () => import('@codemirror/lang-javascript').then((m) => m.javascript({ typescript: true })),
8
+ sql: () => import('@codemirror/lang-sql').then((m) => m.sql()),
9
+ java: () => import('@codemirror/lang-java').then((m) => m.java()),
10
+ json: () => import('@codemirror/lang-json').then((m) => m.json())
11
+ }
12
+
13
+ /** 按需加载语言扩展;模块缓存由运行时保证,重复切换同一语言不会重复下载 */
14
+ export function loadLanguage(lang: CodeEditorLang): Promise<Extension> {
15
+ return LANG_LOADERS[lang]()
16
+ }