Compare commits

..
3 Commits
Author SHA1 Message Date
xuyueandClaude Opus 5.5 ce26925e79 style(提交列表): 右栏的代码字太小,调到和题目页编辑器一样的 20px
Deploy / deploy (push) Canceled after 0s
行高跟着从 30 调到 32,标红的报错行仍和行号逐行对齐。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 20:22:39 +08:00
xuyueandClaude Opus 5.5 d2b8a1ce4a refactor(编辑器): 去掉 vue-codemirror,代码编辑器、协作编辑器、教程编辑器改用自己的薄外壳
三个编辑器只用到它的 v-model、extensions、只读、缩进、占位文字、尺寸和 ready,
shared/components/CodeMirror.vue 照它的做法写了这几样,功能和手感不变:
- 它默认带的 basicSetup(行号、撤销、折叠、搜索、括号……)照样带上
- 各项配置的先后顺序和它一致;外部改代码仍是一次不带 userEvent 的 changes,
  提交时的编辑过程统计不受影响
- @codemirror/commands 现在直接 import,显式声明进依赖

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 20:22:39 +08:00
xuyueandClaude Opus 5.5 6216e1cf22 chore(依赖): 删掉三个没用到的 vue-flow 插件,代码高亮全站只注册一份
- @vue-flow/minimap、node-resizer、node-toolbar 一处引用都没有
- App.vue 给 n-code 另建了一份 highlight.js,还注册着判题机早就不认的 Java、
  JavaScript、Go;改成空闲时加载 shared/highlight.ts 那份。62 条这三种语言的
  历史提交改为不上色显示

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 20:22:32 +08:00
10 changed files with 152 additions and 84 deletions

No files matched your search

+1 -4
View File
@@ -12,6 +12,7 @@
}, },
"dependencies": { "dependencies": {
"@codemirror/autocomplete": "^6.20.3", "@codemirror/autocomplete": "^6.20.3",
"@codemirror/commands": "^6.10.4",
"@codemirror/lang-cpp": "^6.0.3", "@codemirror/lang-cpp": "^6.0.3",
"@codemirror/lang-markdown": "^6.5.2", "@codemirror/lang-markdown": "^6.5.2",
"@codemirror/lang-python": "^6.2.1", "@codemirror/lang-python": "^6.2.1",
@@ -24,9 +25,6 @@
"@vue-flow/background": "^1.3.2", "@vue-flow/background": "^1.3.2",
"@vue-flow/controls": "^1.1.3", "@vue-flow/controls": "^1.1.3",
"@vue-flow/core": "^1.48.2", "@vue-flow/core": "^1.48.2",
"@vue-flow/minimap": "^1.5.4",
"@vue-flow/node-resizer": "^1.5.1",
"@vue-flow/node-toolbar": "^1.1.1",
"@vueuse/core": "^15.0.0", "@vueuse/core": "^15.0.0",
"@vueuse/router": "^15.0.0", "@vueuse/router": "^15.0.0",
"@wangeditor-next/editor": "^6.5.0", "@wangeditor-next/editor": "^6.5.0",
@@ -50,7 +48,6 @@
"pinyin-pro": "^3.29.5", "pinyin-pro": "^3.29.5",
"vue": "^3.5.43", "vue": "^3.5.43",
"vue-chartjs": "^5.3.4", "vue-chartjs": "^5.3.4",
"vue-codemirror": "^6.1.1",
"vue-router": "^5.4.0", "vue-router": "^5.4.0",
"y-codemirror.next": "^0.3.6", "y-codemirror.next": "^0.3.6",
"y-protocols": "1.0.7", "y-protocols": "1.0.7",
+6 -38
View File
@@ -43,47 +43,15 @@ watch(
{ immediate: true }, { immediate: true },
) )
// 延迟加载 highlight.js,避免阻塞首屏 // n-code(提交详情、看代码的弹框)用的 highlight.js,空闲时再加载,不挡首屏
const hljsInstance = ref<any>(null) const hljsInstance = shallowRef<typeof import("shared/highlight").hljs>()
const loadHighlightJS = async () => {
if (hljsInstance.value) return hljsInstance.value
// 逐个取 .default,不要在 Promise.all 后面 map —— 那样元组会塌成
// (HLJSApi | LanguageFn)[],每个元素都变成联合类型,hljs 上就找不到方法了
const [core, c, cpp, python, java, javascript, go, sql] = await Promise.all([
import("highlight.js/lib/core"),
import("highlight.js/lib/languages/c"),
import("highlight.js/lib/languages/cpp"),
import("highlight.js/lib/languages/python"),
import("highlight.js/lib/languages/java"),
import("highlight.js/lib/languages/javascript"),
import("highlight.js/lib/languages/go"),
import("highlight.js/lib/languages/sql"),
])
const hljs = core.default
hljs.registerLanguage("c", c.default)
hljs.registerLanguage("python", python.default)
hljs.registerLanguage("cpp", cpp.default)
hljs.registerLanguage("java", java.default)
hljs.registerLanguage("javascript", javascript.default)
hljs.registerLanguage("go", go.default)
hljs.registerLanguage("sql", sql.default)
hljsInstance.value = hljs
return hljs
}
// 在空闲时预加载
onMounted(() => { onMounted(() => {
if ("requestIdleCallback" in window) { const load = async () => {
requestIdleCallback(() => loadHighlightJS()) hljsInstance.value = (await import("shared/highlight")).hljs
} else {
setTimeout(() => loadHighlightJS(), 1000)
} }
if ("requestIdleCallback" in window) requestIdleCallback(load)
else setTimeout(load, 1000)
}) })
provide("hljs", hljsInstance)
</script> </script>
<template> <template>
+1 -1
View File
@@ -11,7 +11,7 @@ import type { SubmissionTrace } from "@oj2/contract"
* 直接失效。计数本身也不需要响应式。 * 直接失效。计数本身也不需要响应式。
* *
* **只数带 userEvent 的事务。** 下面这些都不带,所以天然不会被算进去: * **只数带 userEvent 的事务。** 下面这些都不带,所以天然不会被算进去:
* - `codeStore.setCode()` —— vue-codemirror 的 setDoc 只 dispatch 一个 changes: * - `codeStore.setCode()` —— shared/components/CodeMirror.vue 同步 v-model 时只 dispatch 一个 changes:
* 提交前的自动格式化、载入草稿 / 模板、切语言都走这条; * 提交前的自动格式化、载入草稿 / 模板、切语言都走这条;
* - 课堂协作里对方的改动 —— y-codemirror.next 应用远程更新时只挂 ySyncAnnotation。 * - 课堂协作里对方的改动 —— y-codemirror.next 应用远程更新时只挂 ySyncAnnotation。
* *
@@ -18,7 +18,7 @@ const props = withDefaults(
fontSize?: number fontSize?: number
lineHeight?: number lineHeight?: number
}>(), }>(),
{ markLine: null, fontSize: 18, lineHeight: 30 }, { markLine: null, fontSize: 20, lineHeight: 32 },
) )
const theme = useThemeVars() const theme = useThemeVars()
@@ -3,7 +3,7 @@ import { cpp } from "@codemirror/lang-cpp"
import { python } from "@codemirror/lang-python" import { python } from "@codemirror/lang-python"
import { sql, SQLite } from "@codemirror/lang-sql" import { sql, SQLite } from "@codemirror/lang-sql"
import { bracketMatching } from "@codemirror/language" import { bracketMatching } from "@codemirror/language"
import { Codemirror } from "vue-codemirror" import CodeMirror from "./CodeMirror.vue"
import type { Extension } from "@codemirror/state" import type { Extension } from "@codemirror/state"
import { autocompletion, closeBrackets, completeAnyWord } from "@codemirror/autocomplete" import { autocompletion, closeBrackets, completeAnyWord } from "@codemirror/autocomplete"
import type { LANGUAGE } from "utils/types" import type { LANGUAGE } from "utils/types"
@@ -53,13 +53,13 @@ const extensions = computed(() => [
</script> </script>
<template> <template>
<Codemirror <CodeMirror
v-model="code" v-model="code"
indentWithTab
:extensions="extensions" :extensions="extensions"
:disabled="readonly" :disabled="readonly"
:tab-size="4" :tab-size="4"
:placeholder="placeholder" :placeholder="placeholder"
:style="{ height, fontSize: `${fontSize}px` }" :height="height"
:font-size="`${fontSize}px`"
/> />
</template> </template>
@@ -0,0 +1,115 @@
<script setup lang="ts">
/**
* CodeMirror 6 的 Vue 外壳,代码编辑器、协作编辑器、教程编辑器共用。
*
* 原来是 vue-codemirror,三个编辑器只用到它的 v-model、extensions、只读、缩进、
* 占位文字、尺寸和 ready 这几样,这里照它的做法写了这几样:
* - **basicSetup 是它默认带的**(行号、撤销、折叠、搜索、括号……),这里也带上,
* 漏了编辑器会少一大截功能;
* - 各项配置的先后顺序和它一致(同优先级下排前面的赢),换掉之后行为不变。
*/
import { basicSetup } from "codemirror"
import { indentWithTab } from "@codemirror/commands"
import { indentUnit } from "@codemirror/language"
import { Compartment, EditorState, type Extension } from "@codemirror/state"
import { EditorView, keymap, placeholder as placeholderExt } from "@codemirror/view"
const {
extensions = [],
disabled = false,
tabSize = 4,
placeholder = "",
height = "100%",
fontSize = "",
} = defineProps<{
/** 传稳定的数组实例:每换一个新数组,编辑器就重配一次 */
extensions?: Extension[]
disabled?: boolean
tabSize?: number
placeholder?: string
height?: string
fontSize?: string
}>()
const code = defineModel<string>({ default: "" })
const emit = defineEmits<{ ready: [view: EditorView] }>()
const container = useTemplateRef("container")
let view: EditorView | null = null
const compartments = {
extensions: new Compartment(),
disabled: new Compartment(),
tabSize: new Compartment(),
placeholder: new Compartment(),
size: new Compartment(),
}
const disabledExt = (value: boolean) =>
value ? [EditorView.editable.of(false), EditorState.readOnly.of(true)] : []
const tabSizeExt = (size: number) => [EditorState.tabSize.of(size), indentUnit.of(" ".repeat(size))]
const placeholderOf = (text: string) => (text ? placeholderExt(text) : [])
const sizeExt = (h: string, fs: string) =>
EditorView.theme({ "&": fs ? { height: h, fontSize: fs } : { height: h } })
onMounted(() => {
view = new EditorView({
parent: container.value!,
state: EditorState.create({
doc: code.value,
extensions: [
basicSetup,
EditorView.updateListener.of((update) => {
if (!update.docChanged) return
const doc = update.state.doc.toString()
if (doc !== code.value) code.value = doc
}),
compartments.extensions.of(extensions),
compartments.disabled.of(disabledExt(disabled)),
keymap.of([indentWithTab]),
compartments.tabSize.of(tabSizeExt(tabSize)),
compartments.placeholder.of(placeholderOf(placeholder)),
compartments.size.of(sizeExt(height, fontSize)),
],
}),
})
emit("ready", view)
})
onBeforeUnmount(() => {
view?.destroy()
view = null
})
function reconfigure(compartment: Compartment, extension: Extension) {
view?.dispatch({ effects: compartment.reconfigure(extension) })
}
watch(code, (value) => {
if (!view) return
const current = view.state.doc.toString()
if (value === current) return
view.dispatch({ changes: { from: 0, to: current.length, insert: value } })
})
watch(
() => extensions,
(value) => reconfigure(compartments.extensions, value),
)
watch(
() => disabled,
(value) => reconfigure(compartments.disabled, disabledExt(value)),
)
watch(
() => tabSize,
(value) => reconfigure(compartments.tabSize, tabSizeExt(value)),
)
watch(
() => placeholder,
(value) => reconfigure(compartments.placeholder, placeholderOf(value)),
)
watch([() => height, () => fontSize], ([h, fs]) => reconfigure(compartments.size, sizeExt(h, fs)))
</script>
<template>
<!-- display: contents,和原来 vue-codemirror 的外层一样不占布局 -->
<div ref="container" style="display: contents" />
</template>
@@ -3,7 +3,7 @@ import { markdown } from "@codemirror/lang-markdown"
import { EditorSelection } from "@codemirror/state" import { EditorSelection } from "@codemirror/state"
import { EditorView, keymap } from "@codemirror/view" import { EditorView, keymap } from "@codemirror/view"
import { Icon } from "@iconify/vue" import { Icon } from "@iconify/vue"
import { Codemirror } from "vue-codemirror" import CodeMirror from "./CodeMirror.vue"
import { uploadImage } from "../../admin/api" import { uploadImage } from "../../admin/api"
import { styleTheme } from "../extensions/baseTheme" import { styleTheme } from "../extensions/baseTheme"
import { oneDark } from "../themes/oneDark" import { oneDark } from "../themes/oneDark"
@@ -196,12 +196,12 @@ const tools = computed(() => [
<input ref="fileInput" type="file" accept="image/*" multiple hidden @change="onPickImages" /> <input ref="fileInput" type="file" accept="image/*" multiple hidden @change="onPickImages" />
</div> </div>
<div class="body"> <div class="body">
<Codemirror <CodeMirror
v-model="modelValue" v-model="modelValue"
:extensions="extensions" :extensions="extensions"
:tab-size="4" :tab-size="4"
:style="{ height: '100%', fontSize: '14px' }" font-size="14px"
@ready="view = $event.view" @ready="view = $event"
/> />
</div> </div>
</div> </div>
@@ -1,6 +1,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import { bracketMatching } from "@codemirror/language" import { bracketMatching } from "@codemirror/language"
import { Codemirror } from "vue-codemirror" import CodeMirror from "./CodeMirror.vue"
import { autocompletion, closeBrackets, completeAnyWord } from "@codemirror/autocomplete" import { autocompletion, closeBrackets, completeAnyWord } from "@codemirror/autocomplete"
import type { EditorView } from "@codemirror/view" import type { EditorView } from "@codemirror/view"
import type { Extension } from "@codemirror/state" import type { Extension } from "@codemirror/state"
@@ -68,10 +68,6 @@ const extensions = computed(() => [
...extraExtensions, ...extraExtensions,
]) ])
interface EditorReadyPayload {
view: EditorView
}
// shallowRef,不是 ref:CodeMirror 的 EditorView 是带 getter 的类实例, // shallowRef,不是 ref:CodeMirror 的 EditorView 是带 getter 的类实例,
// Vue 的 UnwrapRef 深度展开会把它结构化成一个丢了原型方法的假类型, // Vue 的 UnwrapRef 深度展开会把它结构化成一个丢了原型方法的假类型,
// vue-tsc 会报 "missing dispatchTransactions/_root/..." 这类莫名其妙的错。 // vue-tsc 会报 "missing dispatchTransactions/_root/..." 这类莫名其妙的错。
@@ -123,11 +119,11 @@ const detach = () => {
if (wasBound && collabStore.room) collabStore.leave("left") if (wasBound && collabStore.room) collabStore.leave("left")
} }
const handleEditorReady = (payload: EditorReadyPayload) => { const handleEditorReady = (view: EditorView) => {
editorView.value = payload.view editorView.value = view
// 也从这里起:学生排队时切去看提交记录、老师在这期间接了单, // 也从这里起:学生排队时切去看提交记录、老师在这期间接了单,
// 等他切回来时 room 早就非空了,只靠下面的 watch 是等不到的 // 等他切回来时 room 早就非空了,只靠下面的 watch 是等不到的
bind(payload.view) bind(view)
} }
/** /**
@@ -206,14 +202,14 @@ onUnmounted(() => {
</script> </script>
<template> <template>
<Codemirror <CodeMirror
v-model="code" v-model="code"
indentWithTab
:extensions="extensions" :extensions="extensions"
:disabled="readonly" :disabled="readonly"
:tab-size="4" :tab-size="4"
:placeholder="placeholder" :placeholder="placeholder"
:style="{ height, fontSize: `${fontSize}px` }" :height="height"
:font-size="`${fontSize}px`"
@ready="handleEditorReady" @ready="handleEditorReady"
/> />
</template> </template>
+4 -1
View File
@@ -1,5 +1,6 @@
/** /**
* 代码高亮:自学的练一练、以及 Markdown.vue 里的代码块共用这一份(配色在 highlight.css)。 * 代码高亮:自学的练一练、Markdown.vue 里的代码块、以及 App.vue 交给 n-code 的都是这一份
* (配色在 highlight.css)。
* 只注册判题机认的几种语言,别的语言和不标语言的代码块按原文显示。 * 只注册判题机认的几种语言,别的语言和不标语言的代码块按原文显示。
*/ */
import hljs from "highlight.js/lib/core" import hljs from "highlight.js/lib/core"
@@ -13,6 +14,8 @@ hljs.registerLanguage("c", c)
hljs.registerLanguage("cpp", cpp) hljs.registerLanguage("cpp", cpp)
hljs.registerLanguage("sql", sql) hljs.registerLanguage("sql", sql)
export { hljs }
const LANGUAGE_ALIASES: Record<string, string> = { const LANGUAGE_ALIASES: Record<string, string> = {
python: "python", python: "python",
py: "python", py: "python",
+9 -20
View File
@@ -41,6 +41,7 @@
"version": "1.9.0", "version": "1.9.0",
"dependencies": { "dependencies": {
"@codemirror/autocomplete": "^6.20.3", "@codemirror/autocomplete": "^6.20.3",
"@codemirror/commands": "^6.10.4",
"@codemirror/lang-cpp": "^6.0.3", "@codemirror/lang-cpp": "^6.0.3",
"@codemirror/lang-markdown": "^6.5.2", "@codemirror/lang-markdown": "^6.5.2",
"@codemirror/lang-python": "^6.2.1", "@codemirror/lang-python": "^6.2.1",
@@ -53,9 +54,6 @@
"@vue-flow/background": "^1.3.2", "@vue-flow/background": "^1.3.2",
"@vue-flow/controls": "^1.1.3", "@vue-flow/controls": "^1.1.3",
"@vue-flow/core": "^1.48.2", "@vue-flow/core": "^1.48.2",
"@vue-flow/minimap": "^1.5.4",
"@vue-flow/node-resizer": "^1.5.1",
"@vue-flow/node-toolbar": "^1.1.1",
"@vueuse/core": "^15.0.0", "@vueuse/core": "^15.0.0",
"@vueuse/router": "^15.0.0", "@vueuse/router": "^15.0.0",
"@wangeditor-next/editor": "^6.5.0", "@wangeditor-next/editor": "^6.5.0",
@@ -79,7 +77,6 @@
"pinyin-pro": "^3.29.5", "pinyin-pro": "^3.29.5",
"vue": "^3.5.43", "vue": "^3.5.43",
"vue-chartjs": "^5.3.4", "vue-chartjs": "^5.3.4",
"vue-codemirror": "^6.1.1",
"vue-router": "^5.4.0", "vue-router": "^5.4.0",
"y-codemirror.next": "^0.3.6", "y-codemirror.next": "^0.3.6",
"y-protocols": "1.0.7", "y-protocols": "1.0.7",
@@ -312,13 +309,13 @@
"@codemirror/lang-cpp": ["@codemirror/lang-cpp@6.0.3", "https://registry.npmjs.com/@codemirror/lang-cpp/-/lang-cpp-6.0.3.tgz", { "dependencies": { "@codemirror/language": "^6.0.0", "@lezer/cpp": "^1.0.0" } }, "sha512-URM26M3vunFFn9/sm6rzqrBzDgfWuDixp85uTY49wKudToc2jTHUrKIGGKs+QWND+YLofNNZpxcNGRynFJfvgA=="], "@codemirror/lang-cpp": ["@codemirror/lang-cpp@6.0.3", "https://registry.npmjs.com/@codemirror/lang-cpp/-/lang-cpp-6.0.3.tgz", { "dependencies": { "@codemirror/language": "^6.0.0", "@lezer/cpp": "^1.0.0" } }, "sha512-URM26M3vunFFn9/sm6rzqrBzDgfWuDixp85uTY49wKudToc2jTHUrKIGGKs+QWND+YLofNNZpxcNGRynFJfvgA=="],
"@codemirror/lang-css": ["@codemirror/lang-css@6.3.1", "", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@lezer/common": "^1.0.2", "@lezer/css": "^1.1.7" } }, "sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg=="], "@codemirror/lang-css": ["@codemirror/lang-css@6.3.1", "https://registry.npmjs.com/@codemirror/lang-css/-/lang-css-6.3.1.tgz", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@lezer/common": "^1.0.2", "@lezer/css": "^1.1.7" } }, "sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg=="],
"@codemirror/lang-html": ["@codemirror/lang-html@6.4.12", "", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/lang-css": "^6.0.0", "@codemirror/lang-javascript": "^6.0.0", "@codemirror/language": "^6.4.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.17.0", "@lezer/common": "^1.0.0", "@lezer/css": "^1.1.0", "@lezer/html": "^1.3.12" } }, "sha512-pw2ReWKUqSkbvh76RAT4NYxiogRu+PWkR2ukAwO9uOgrm8uipkzjtKKtNpyeAQwHOqxEeSvAXZ6vr3AfyB9y/w=="], "@codemirror/lang-html": ["@codemirror/lang-html@6.4.12", "https://registry.npmjs.com/@codemirror/lang-html/-/lang-html-6.4.12.tgz", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/lang-css": "^6.0.0", "@codemirror/lang-javascript": "^6.0.0", "@codemirror/language": "^6.4.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.17.0", "@lezer/common": "^1.0.0", "@lezer/css": "^1.1.0", "@lezer/html": "^1.3.12" } }, "sha512-pw2ReWKUqSkbvh76RAT4NYxiogRu+PWkR2ukAwO9uOgrm8uipkzjtKKtNpyeAQwHOqxEeSvAXZ6vr3AfyB9y/w=="],
"@codemirror/lang-javascript": ["@codemirror/lang-javascript@6.2.5", "", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/language": "^6.6.0", "@codemirror/lint": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.17.0", "@lezer/common": "^1.0.0", "@lezer/javascript": "^1.0.0" } }, "sha512-zD4e5mS+50htS7F+TYjBPsiIFGanfVqg4HyUz6WNFikgOPf2BgKlx+TQedI1w6n/IqRBVBbBWmGFdLB/7uxO4A=="], "@codemirror/lang-javascript": ["@codemirror/lang-javascript@6.2.5", "https://registry.npmjs.com/@codemirror/lang-javascript/-/lang-javascript-6.2.5.tgz", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/language": "^6.6.0", "@codemirror/lint": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.17.0", "@lezer/common": "^1.0.0", "@lezer/javascript": "^1.0.0" } }, "sha512-zD4e5mS+50htS7F+TYjBPsiIFGanfVqg4HyUz6WNFikgOPf2BgKlx+TQedI1w6n/IqRBVBbBWmGFdLB/7uxO4A=="],
"@codemirror/lang-markdown": ["@codemirror/lang-markdown@6.5.2", "", { "dependencies": { "@codemirror/autocomplete": "^6.7.1", "@codemirror/lang-html": "^6.0.0", "@codemirror/language": "^6.3.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", "@lezer/common": "^1.2.1", "@lezer/markdown": "^1.0.0" } }, "sha512-AwBOdkWYuA//WcM0xO5PfHPUcmz/O2i5o0Nsg1U69SII/loCJlFI1Romd9xp2HYb1kYJRGZotyqRghuHH5n8Kw=="], "@codemirror/lang-markdown": ["@codemirror/lang-markdown@6.5.2", "https://registry.npmjs.com/@codemirror/lang-markdown/-/lang-markdown-6.5.2.tgz", { "dependencies": { "@codemirror/autocomplete": "^6.7.1", "@codemirror/lang-html": "^6.0.0", "@codemirror/language": "^6.3.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", "@lezer/common": "^1.2.1", "@lezer/markdown": "^1.0.0" } }, "sha512-AwBOdkWYuA//WcM0xO5PfHPUcmz/O2i5o0Nsg1U69SII/loCJlFI1Romd9xp2HYb1kYJRGZotyqRghuHH5n8Kw=="],
"@codemirror/lang-python": ["@codemirror/lang-python@6.2.1", "https://registry.npmjs.com/@codemirror/lang-python/-/lang-python-6.2.1.tgz", { "dependencies": { "@codemirror/autocomplete": "^6.3.2", "@codemirror/language": "^6.8.0", "@codemirror/state": "^6.0.0", "@lezer/common": "^1.2.1", "@lezer/python": "^1.1.4" } }, "sha512-IRjC8RUBhn9mGR9ywecNhB51yePWCGgvHfY1lWN/Mrp3cKuHr0isDKia+9HnvhiWNnMpbGhWrkhuWOc09exRyw=="], "@codemirror/lang-python": ["@codemirror/lang-python@6.2.1", "https://registry.npmjs.com/@codemirror/lang-python/-/lang-python-6.2.1.tgz", { "dependencies": { "@codemirror/autocomplete": "^6.3.2", "@codemirror/language": "^6.8.0", "@codemirror/state": "^6.0.0", "@lezer/common": "^1.2.1", "@lezer/python": "^1.1.4" } }, "sha512-IRjC8RUBhn9mGR9ywecNhB51yePWCGgvHfY1lWN/Mrp3cKuHr0isDKia+9HnvhiWNnMpbGhWrkhuWOc09exRyw=="],
@@ -428,17 +425,17 @@
"@lezer/cpp": ["@lezer/cpp@1.1.6", "https://registry.npmjs.com/@lezer/cpp/-/cpp-1.1.6.tgz", { "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0" } }, "sha512-vh9gWWJOXFVY8HBHK3Twzq8MgwG2iN4GSyzBP9sCGTe37P15x2R14VaBQk0VA0ezTRN1KHYBBsHhvpGZ2Xy/pA=="], "@lezer/cpp": ["@lezer/cpp@1.1.6", "https://registry.npmjs.com/@lezer/cpp/-/cpp-1.1.6.tgz", { "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0" } }, "sha512-vh9gWWJOXFVY8HBHK3Twzq8MgwG2iN4GSyzBP9sCGTe37P15x2R14VaBQk0VA0ezTRN1KHYBBsHhvpGZ2Xy/pA=="],
"@lezer/css": ["@lezer/css@1.3.9", "", { "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.3.0" } }, "sha512-ZmzgvTOBdJWGIsY/ItAfN7UW8DV802oZG+jeG6E508SwEzz5YhuAajptpWPICvIyqYAD2+VjMdOS40GgGkyEOQ=="], "@lezer/css": ["@lezer/css@1.3.9", "https://registry.npmjs.com/@lezer/css/-/css-1.3.9.tgz", { "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.3.0" } }, "sha512-ZmzgvTOBdJWGIsY/ItAfN7UW8DV802oZG+jeG6E508SwEzz5YhuAajptpWPICvIyqYAD2+VjMdOS40GgGkyEOQ=="],
"@lezer/highlight": ["@lezer/highlight@1.2.5", "https://registry.npmjs.com/@lezer/highlight/-/highlight-1.2.5.tgz", { "dependencies": { "@lezer/common": "^1.3.0" } }, "sha512-O1GMVKgtf5YspFaRzpmqkVgMtIk2HG9uMAbH6wdAIdNh3TVzCsch/+cRi+6l2//UGDKe6NB9BW3cvuR5ezMQ0w=="], "@lezer/highlight": ["@lezer/highlight@1.2.5", "https://registry.npmjs.com/@lezer/highlight/-/highlight-1.2.5.tgz", { "dependencies": { "@lezer/common": "^1.3.0" } }, "sha512-O1GMVKgtf5YspFaRzpmqkVgMtIk2HG9uMAbH6wdAIdNh3TVzCsch/+cRi+6l2//UGDKe6NB9BW3cvuR5ezMQ0w=="],
"@lezer/html": ["@lezer/html@1.3.13", "", { "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0" } }, "sha512-oI7n6NJml729m7pjm9lvLvmXbdoMoi2f+1pwSDJkl9d68zGr7a9Btz8NdHTGQZtW2DA25ybeuv/SyDb9D5tseg=="], "@lezer/html": ["@lezer/html@1.3.13", "https://registry.npmjs.com/@lezer/html/-/html-1.3.13.tgz", { "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0" } }, "sha512-oI7n6NJml729m7pjm9lvLvmXbdoMoi2f+1pwSDJkl9d68zGr7a9Btz8NdHTGQZtW2DA25ybeuv/SyDb9D5tseg=="],
"@lezer/javascript": ["@lezer/javascript@1.5.6", "", { "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.1.3", "@lezer/lr": "^1.3.0" } }, "sha512-sEvOqpl4vJQca0NugSQK02vQPbc5KrvoojnYGoqqFgFO0MtcYhwGiHKVEB+LuXYJnfyXo4QPA8ztbrEa4Fw5NA=="], "@lezer/javascript": ["@lezer/javascript@1.5.6", "https://registry.npmjs.com/@lezer/javascript/-/javascript-1.5.6.tgz", { "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.1.3", "@lezer/lr": "^1.3.0" } }, "sha512-sEvOqpl4vJQca0NugSQK02vQPbc5KrvoojnYGoqqFgFO0MtcYhwGiHKVEB+LuXYJnfyXo4QPA8ztbrEa4Fw5NA=="],
"@lezer/lr": ["@lezer/lr@1.4.10", "https://registry.npmjs.com/@lezer/lr/-/lr-1.4.10.tgz", { "dependencies": { "@lezer/common": "^1.0.0" } }, "sha512-rnCpTIBafOx4mRp43xOxDJbFipJm/c0cia/V5TiGlhmMa+wsSdoGmUN3w5Bqrks/09Q/D4tNAmWaT8p6NRi77A=="], "@lezer/lr": ["@lezer/lr@1.4.10", "https://registry.npmjs.com/@lezer/lr/-/lr-1.4.10.tgz", { "dependencies": { "@lezer/common": "^1.0.0" } }, "sha512-rnCpTIBafOx4mRp43xOxDJbFipJm/c0cia/V5TiGlhmMa+wsSdoGmUN3w5Bqrks/09Q/D4tNAmWaT8p6NRi77A=="],
"@lezer/markdown": ["@lezer/markdown@1.8.0", "", { "dependencies": { "@lezer/common": "^1.5.0", "@lezer/highlight": "^1.0.0" } }, "sha512-X6w3A2NpyhdtGqTWRJB8gR4QDXBaFMbTOs780ZdZ15KKCfBXOQTKcB3Vr+W6tqJHVlealt53tLmHRvOqPTQgYA=="], "@lezer/markdown": ["@lezer/markdown@1.8.0", "https://registry.npmjs.com/@lezer/markdown/-/markdown-1.8.0.tgz", { "dependencies": { "@lezer/common": "^1.5.0", "@lezer/highlight": "^1.0.0" } }, "sha512-X6w3A2NpyhdtGqTWRJB8gR4QDXBaFMbTOs780ZdZ15KKCfBXOQTKcB3Vr+W6tqJHVlealt53tLmHRvOqPTQgYA=="],
"@lezer/python": ["@lezer/python@1.1.19", "https://registry.npmjs.com/@lezer/python/-/python-1.1.19.tgz", { "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0" } }, "sha512-MhQIURHRytsNzP/YXnqpYKW6la6voAH3kyplTOOiCdjyFY6cWWGFVmYVdHIPrElqSDf4iCDktQCockB9FxuhzQ=="], "@lezer/python": ["@lezer/python@1.1.19", "https://registry.npmjs.com/@lezer/python/-/python-1.1.19.tgz", { "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0" } }, "sha512-MhQIURHRytsNzP/YXnqpYKW6la6voAH3kyplTOOiCdjyFY6cWWGFVmYVdHIPrElqSDf4iCDktQCockB9FxuhzQ=="],
@@ -828,12 +825,6 @@
"@vue-flow/core": ["@vue-flow/core@1.48.2", "https://registry.npmjs.com/@vue-flow/core/-/core-1.48.2.tgz", { "dependencies": { "@vueuse/core": "^10.5.0", "d3-drag": "^3.0.0", "d3-interpolate": "^3.0.1", "d3-selection": "^3.0.0", "d3-zoom": "^3.0.0" }, "peerDependencies": { "vue": "^3.3.0" } }, "sha512-raxhgKWE+G/mcEvXJjGFUDYW9rAI3GOtiHR3ZkNpwBWuIaCC1EYiBmKGwJOoNzVFgwO7COgErnK7i08i287AFA=="], "@vue-flow/core": ["@vue-flow/core@1.48.2", "https://registry.npmjs.com/@vue-flow/core/-/core-1.48.2.tgz", { "dependencies": { "@vueuse/core": "^10.5.0", "d3-drag": "^3.0.0", "d3-interpolate": "^3.0.1", "d3-selection": "^3.0.0", "d3-zoom": "^3.0.0" }, "peerDependencies": { "vue": "^3.3.0" } }, "sha512-raxhgKWE+G/mcEvXJjGFUDYW9rAI3GOtiHR3ZkNpwBWuIaCC1EYiBmKGwJOoNzVFgwO7COgErnK7i08i287AFA=="],
"@vue-flow/minimap": ["@vue-flow/minimap@1.5.4", "https://registry.npmjs.com/@vue-flow/minimap/-/minimap-1.5.4.tgz", { "dependencies": { "d3-selection": "^3.0.0", "d3-zoom": "^3.0.0" }, "peerDependencies": { "@vue-flow/core": "^1.23.0", "vue": "^3.3.0" } }, "sha512-l4C+XTAXnRxsRpUdN7cAVFBennC1sVRzq4bDSpVK+ag7tdMczAnhFYGgbLkUw3v3sY6gokyWwMl8CDonp8eB2g=="],
"@vue-flow/node-resizer": ["@vue-flow/node-resizer@1.5.1", "https://registry.npmjs.com/@vue-flow/node-resizer/-/node-resizer-1.5.1.tgz", { "dependencies": { "d3-drag": "^3.0.0", "d3-selection": "^3.0.0" }, "peerDependencies": { "@vue-flow/core": "^1.23.0", "vue": "^3.3.0" } }, "sha512-DNYgXTF39GXPAygVMFmgn5azgFztaWfqbWvv8D/X0HGgeunRrexJ0W94DyXH1rnndGyYAJ0KexEjyelsb+Nlbg=="],
"@vue-flow/node-toolbar": ["@vue-flow/node-toolbar@1.1.1", "https://registry.npmjs.com/@vue-flow/node-toolbar/-/node-toolbar-1.1.1.tgz", { "peerDependencies": { "@vue-flow/core": "^1.23.0", "vue": "^3.3.0" } }, "sha512-vgSnGMLd3FXstdpvC721qcBDzGkPsudmyA8urEP55/EMikCp59klgzPvVULTDxxsew5MdXtTBCumsqOi+PXJdg=="],
"@vue-macros/common": ["@vue-macros/common@3.1.4", "https://registry.npmjs.com/@vue-macros/common/-/common-3.1.4.tgz", { "dependencies": { "@vue/compiler-sfc": "^3.5.22", "ast-kit": "^2.1.2", "local-pkg": "^1.1.2", "magic-string-ast": "^1.0.2", "unplugin-utils": "^0.3.0" }, "peerDependencies": { "vue": "^2.7.0 || ^3.2.25" }, "optionalPeers": ["vue"] }, "sha512-/5Fv+6DgIcM9ajY05ZmKBv+LMX1M9A0X+IUwDRVdt67ciw8OV9bvG2r34p3RiEadlsQybjhKPRKNXDC8Bp23cw=="], "@vue-macros/common": ["@vue-macros/common@3.1.4", "https://registry.npmjs.com/@vue-macros/common/-/common-3.1.4.tgz", { "dependencies": { "@vue/compiler-sfc": "^3.5.22", "ast-kit": "^2.1.2", "local-pkg": "^1.1.2", "magic-string-ast": "^1.0.2", "unplugin-utils": "^0.3.0" }, "peerDependencies": { "vue": "^2.7.0 || ^3.2.25" }, "optionalPeers": ["vue"] }, "sha512-/5Fv+6DgIcM9ajY05ZmKBv+LMX1M9A0X+IUwDRVdt67ciw8OV9bvG2r34p3RiEadlsQybjhKPRKNXDC8Bp23cw=="],
"@vue/compiler-core": ["@vue/compiler-core@3.5.43", "https://registry.npmjs.com/@vue/compiler-core/-/compiler-core-3.5.43.tgz", { "dependencies": { "@babel/parser": "^7.29.8", "@vue/shared": "3.5.43", "entities": "^7.0.1", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-zdiLhnbe1QQqgDT8xZMpNmyqZ3qlI+/Q/FHQco57Kwl/b05HhCzN6eVGN9QU9rbga4CrS0H5SYY8VGHZCt/1Hg=="], "@vue/compiler-core": ["@vue/compiler-core@3.5.43", "https://registry.npmjs.com/@vue/compiler-core/-/compiler-core-3.5.43.tgz", { "dependencies": { "@babel/parser": "^7.29.8", "@vue/shared": "3.5.43", "entities": "^7.0.1", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-zdiLhnbe1QQqgDT8xZMpNmyqZ3qlI+/Q/FHQco57Kwl/b05HhCzN6eVGN9QU9rbga4CrS0H5SYY8VGHZCt/1Hg=="],
@@ -1574,8 +1565,6 @@
"vue-chartjs": ["vue-chartjs@5.3.4", "https://registry.npmjs.com/vue-chartjs/-/vue-chartjs-5.3.4.tgz", { "peerDependencies": { "chart.js": "^4.1.1", "vue": "^3.0.0-0 || ^2.7.0" } }, "sha512-x3Fqob8RQvrTdssfi9ecsCzEkFOd8JPmNwSkSQzdfKj/uBsRJs/Y88cZcZIEcPsTVfMGwMo4MOoihoDG2DoE/g=="], "vue-chartjs": ["vue-chartjs@5.3.4", "https://registry.npmjs.com/vue-chartjs/-/vue-chartjs-5.3.4.tgz", { "peerDependencies": { "chart.js": "^4.1.1", "vue": "^3.0.0-0 || ^2.7.0" } }, "sha512-x3Fqob8RQvrTdssfi9ecsCzEkFOd8JPmNwSkSQzdfKj/uBsRJs/Y88cZcZIEcPsTVfMGwMo4MOoihoDG2DoE/g=="],
"vue-codemirror": ["vue-codemirror@6.1.1", "https://registry.npmjs.com/vue-codemirror/-/vue-codemirror-6.1.1.tgz", { "dependencies": { "@codemirror/commands": "6.x", "@codemirror/language": "6.x", "@codemirror/state": "6.x", "@codemirror/view": "6.x" }, "peerDependencies": { "codemirror": "6.x", "vue": "3.x" } }, "sha512-rTAYo44owd282yVxKtJtnOi7ERAcXTeviwoPXjIc6K/IQYUsoDkzPvw/JDFtSP6T7Cz/2g3EHaEyeyaQCKoDMg=="],
"vue-demi": ["vue-demi@0.14.10", "https://registry.npmjs.com/vue-demi/-/vue-demi-0.14.10.tgz", { "peerDependencies": { "@vue/composition-api": "^1.0.0-rc.1", "vue": "^3.0.0-0 || ^2.6.0" }, "optionalPeers": ["@vue/composition-api"], "bin": { "vue-demi-fix": "bin/vue-demi-fix.js", "vue-demi-switch": "bin/vue-demi-switch.js" } }, "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg=="], "vue-demi": ["vue-demi@0.14.10", "https://registry.npmjs.com/vue-demi/-/vue-demi-0.14.10.tgz", { "peerDependencies": { "@vue/composition-api": "^1.0.0-rc.1", "vue": "^3.0.0-0 || ^2.6.0" }, "optionalPeers": ["@vue/composition-api"], "bin": { "vue-demi-fix": "bin/vue-demi-fix.js", "vue-demi-switch": "bin/vue-demi-switch.js" } }, "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg=="],
"vue-router": ["vue-router@5.4.0", "https://registry.npmjs.com/vue-router/-/vue-router-5.4.0.tgz", { "dependencies": { "@vue-macros/common": "^3.1.3", "@vue/devtools-api": "^8.1.5", "ast-walker-scope": "^0.10.0", "chokidar": "^5.0.0", "confbox": "^0.3.1", "local-pkg": "^1.2.1", "magic-string": "^1.4.3", "mlly": "^1.8.2", "muggle-string": "^0.4.1", "nostics": "^1.3.0", "pathe": "^2.0.3", "picomatch": "^4.0.7", "scule": "^1.3.0", "tinyglobby": "^0.2.17", "unplugin": "^3.4.0", "unplugin-utils": "^0.3.2" }, "peerDependencies": { "@pinia/colada": ">=0.21.2", "@vue/compiler-sfc": "^3.5.34 || ^4.0.0", "pinia": "^3.0.4 || ^4.0.2", "vite": "^7.3.0 || ^8.0.0", "vue": "^3.5.34 || ^4.0.0" }, "optionalPeers": ["@pinia/colada", "@vue/compiler-sfc", "pinia", "vite"] }, "sha512-pFvcYcxinDHjZUlf7AzFBrT8r8Xqvv4uMHoJnjc+EqPawXQvHTkF8S4tfSmQLpriVHUGfkaKlI7Et0KRjTMTdw=="], "vue-router": ["vue-router@5.4.0", "https://registry.npmjs.com/vue-router/-/vue-router-5.4.0.tgz", { "dependencies": { "@vue-macros/common": "^3.1.3", "@vue/devtools-api": "^8.1.5", "ast-walker-scope": "^0.10.0", "chokidar": "^5.0.0", "confbox": "^0.3.1", "local-pkg": "^1.2.1", "magic-string": "^1.4.3", "mlly": "^1.8.2", "muggle-string": "^0.4.1", "nostics": "^1.3.0", "pathe": "^2.0.3", "picomatch": "^4.0.7", "scule": "^1.3.0", "tinyglobby": "^0.2.17", "unplugin": "^3.4.0", "unplugin-utils": "^0.3.2" }, "peerDependencies": { "@pinia/colada": ">=0.21.2", "@vue/compiler-sfc": "^3.5.34 || ^4.0.0", "pinia": "^3.0.4 || ^4.0.2", "vite": "^7.3.0 || ^8.0.0", "vue": "^3.5.34 || ^4.0.0" }, "optionalPeers": ["@pinia/colada", "@vue/compiler-sfc", "pinia", "vite"] }, "sha512-pFvcYcxinDHjZUlf7AzFBrT8r8Xqvv4uMHoJnjc+EqPawXQvHTkF8S4tfSmQLpriVHUGfkaKlI7Et0KRjTMTdw=="],