perf(Markdown): 题面、教程、AI 提示每次打开都去 unpkg.com 拉四个库,机房网络下又慢又不稳

md-editor-v3 的 MdPreview 不管正文里有没有代码、公式,都会从 unpkg.com 加载
highlight.js、katex、mermaid、echarts(mermaid 还是另一份 11.x)。而我们只用到最基础的
Markdown:题面 95% 是富文本存的 HTML,教程是标题、表格、图片,AI 输出是标题、列表、
表格、少量代码块,库里一处公式、mermaid 都没有。

- 显示:新组件 shared/components/Markdown.vue,直接用 markdown-it,代码高亮走本地的
  highlight.js(和练一练共用 shared/highlight.ts,补了 C++ / SQL)。9 处 MdPreview 全换掉。
  正文默认 16px,教程也统一成 16px。
- 编辑:后台教程编辑器换成项目已有的 CodeMirror,加一排格式按钮;图片可以按按钮选、
  粘贴、拖进来,都是先上传再插入。md-editor-v3 从依赖里删掉。
- AI 生成的内容(AI 提示、AI 分析、班级报告)不再放行原生 HTML:学生能在代码里诱导
  AI 吐出 <img onerror>,老师在后台一打开就执行。库里 1196 条 AI 输出没有一个 HTML
  标签,关掉不影响显示。题面、教程照旧放行。
- 长英文改成在单词之间折行,原来 break-all 会把 "I live" 断成 "I l / ive"。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xuyueandClaude Opus 5.5 committed 2026-10-12 14:02:54 +08:00
1 parent c497ccadc8
commit 6f47ad8358
24 files changed
+504 -308

No files matched your search

+3 -1
View File
@@ -13,6 +13,7 @@
"dependencies": { "dependencies": {
"@codemirror/autocomplete": "^6.20.3", "@codemirror/autocomplete": "^6.20.3",
"@codemirror/lang-cpp": "^6.0.3", "@codemirror/lang-cpp": "^6.0.3",
"@codemirror/lang-markdown": "^6.5.2",
"@codemirror/lang-python": "^6.2.1", "@codemirror/lang-python": "^6.2.1",
"@codemirror/lang-sql": "^6.10.0", "@codemirror/lang-sql": "^6.10.0",
"@codemirror/language": "^6.12.4", "@codemirror/language": "^6.12.4",
@@ -40,7 +41,7 @@
"fflate": "^0.8.3", "fflate": "^0.8.3",
"highlight.js": "^11.12.0", "highlight.js": "^11.12.0",
"lib0": "0.2.117", "lib0": "0.2.117",
"md-editor-v3": "^6.5.6", "markdown-it": "^14.3.0",
"mermaid": "^11.17.2", "mermaid": "^11.17.2",
"naive-ui": "^2.45.2", "naive-ui": "^2.45.2",
"nanoid": "^6.0.1", "nanoid": "^6.0.1",
@@ -58,6 +59,7 @@
"devDependencies": { "devDependencies": {
"@iconify/vue": "^5.0.1", "@iconify/vue": "^5.0.1",
"@types/canvas-confetti": "^1.9.0", "@types/canvas-confetti": "^1.9.0",
"@types/markdown-it": "^14.1.2",
"@types/node": "^26.3.0", "@types/node": "^26.3.0",
"@vitejs/plugin-legacy": "^8.2.3", "@vitejs/plugin-legacy": "^8.2.3",
"@vitejs/plugin-vue": "^6.0.8", "@vitejs/plugin-vue": "^6.0.8",
+2 -3
View File
@@ -53,7 +53,7 @@
</n-descriptions-item> </n-descriptions-item>
</n-descriptions> </n-descriptions>
<n-scrollbar style="max-height: 60vh; margin-top: 12px"> <n-scrollbar style="max-height: 60vh; margin-top: 12px">
<MdPreview :model-value="detail.analysis" /> <Markdown :content="detail.analysis" />
</n-scrollbar> </n-scrollbar>
</div> </div>
</n-spin> </n-spin>
@@ -62,8 +62,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import PageHeader from "admin/components/PageHeader.vue" import PageHeader from "admin/components/PageHeader.vue"
import { MdPreview } from "md-editor-v3" import Markdown from "shared/components/Markdown.vue"
import "md-editor-v3/lib/preview.css"
import Pagination from "shared/components/Pagination.vue" import Pagination from "shared/components/Pagination.vue"
import { parseTime } from "utils/functions" import { parseTime } from "utils/functions"
import { getAIReportList, getAIReportDetail, pinAIReport, getPinnedAIReports } from "../api" import { getAIReportList, getAIReportDetail, pinAIReport, getPinnedAIReports } from "../api"
+3 -21
View File
@@ -1,8 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { EditorView } from "@codemirror/view" import { EditorView } from "@codemirror/view"
import { PROBLEM_TAG_MAX_LENGTH, TEST_CASE_MAX_CASES } from "@oj2/contract" import { PROBLEM_TAG_MAX_LENGTH, TEST_CASE_MAX_CASES } from "@oj2/contract"
import { MdPreview } from "md-editor-v3" import Markdown from "shared/components/Markdown.vue"
import "md-editor-v3/lib/preview.css"
import { StorageSerializers } from "@vueuse/core" import { StorageSerializers } from "@vueuse/core"
import { useThemeVars } from "naive-ui" import { useThemeVars } from "naive-ui"
import PageHeader from "admin/components/PageHeader.vue" import PageHeader from "admin/components/PageHeader.vue"
@@ -56,7 +55,6 @@ const message = useMessage()
const router = useRouter() const router = useRouter()
const theme = useThemeVars() const theme = useThemeVars()
const previewCollapsed = usePreviewCollapsed() const previewCollapsed = usePreviewCollapsed()
const isDark = useDark()
const isCreate = computed(() => !props.problemID) const isCreate = computed(() => !props.problemID)
@@ -680,11 +678,7 @@ onMounted(async () => {
</n-tag> </n-tag>
</div> </div>
<h3 class="title">描述</h3> <h3 class="title">描述</h3>
<MdPreview <Markdown html :content="form.description" />
preview-theme="vuepress"
:model-value="form.description"
:theme="isDark ? 'dark' : 'light'"
/>
<p v-if="selected > 0" class="otherGroup"> <p v-if="selected > 0" class="otherGroup">
学生看到的是第 1 组,下面是第 {{ selected + 1 }} 组跑出来的样子 学生看到的是第 1 组,下面是第 {{ selected + 1 }} 组跑出来的样子
</p> </p>
@@ -720,11 +714,7 @@ onMounted(async () => {
</template> </template>
<template v-if="!isBlankHtml(form.hint)"> <template v-if="!isBlankHtml(form.hint)">
<h3 class="title sqlTitle">提示</h3> <h3 class="title sqlTitle">提示</h3>
<MdPreview <Markdown html :content="form.hint" />
preview-theme="vuepress"
:model-value="form.hint"
:theme="isDark ? 'dark' : 'light'"
/>
</template> </template>
</div> </div>
</aside> </aside>
@@ -1003,14 +993,6 @@ onMounted(async () => {
margin-top: 14px; margin-top: 14px;
} }
.page :deep(.md-editor) {
background: transparent;
}
.page :deep(.md-editor-preview-wrapper) {
padding: 0;
}
.otherGroup { .otherGroup {
margin: 14px 0 0; margin: 14px 0 0;
padding: 6px 10px; padding: 6px 10px;
@@ -1,6 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { MdPreview } from "md-editor-v3" import Markdown from "shared/components/Markdown.vue"
import "md-editor-v3/lib/preview.css"
import { useThemeVars } from "naive-ui" import { useThemeVars } from "naive-ui"
import { useMermaid } from "shared/composables/useMermaid" import { useMermaid } from "shared/composables/useMermaid"
import { DIFFICULTY, SOURCES } from "utils/constants" import { DIFFICULTY, SOURCES } from "utils/constants"
@@ -42,7 +41,6 @@ const tab = defineModel<PreviewTab>("tab", { required: true })
const emit = defineEmits<{ renderState: [ok: boolean]; collapse: [] }>() const emit = defineEmits<{ renderState: [ok: boolean]; collapse: [] }>()
const theme = useThemeVars() const theme = useThemeVars()
const isDark = useDark()
const isBlankHtml = (html: string) => !html.trim() || html === "<p><br></p>" const isBlankHtml = (html: string) => !html.trim() || html === "<p><br></p>"
@@ -154,30 +152,17 @@ onMounted(() => nextTick(render))
</div> </div>
<h3 class="title">描述</h3> <h3 class="title">描述</h3>
<MdPreview <Markdown html v-if="!isBlankHtml(description)" :content="description" />
v-if="!isBlankHtml(description)"
preview-theme="vuepress"
:model-value="description"
:theme="isDark ? 'dark' : 'light'"
/>
<p v-else class="placeholder">(还没写描述)</p> <p v-else class="placeholder">(还没写描述)</p>
<div class="io"> <div class="io">
<section> <section>
<h3 class="title">输入</h3> <h3 class="title">输入</h3>
<MdPreview <Markdown html :content="inputDescription" />
preview-theme="vuepress"
:model-value="inputDescription"
:theme="isDark ? 'dark' : 'light'"
/>
</section> </section>
<section> <section>
<h3 class="title">输出</h3> <h3 class="title">输出</h3>
<MdPreview <Markdown html :content="outputDescription" />
preview-theme="vuepress"
:model-value="outputDescription"
:theme="isDark ? 'dark' : 'light'"
/>
</section> </section>
</div> </div>
@@ -207,11 +192,7 @@ onMounted(() => nextTick(render))
<template v-if="!isBlankHtml(hint)"> <template v-if="!isBlankHtml(hint)">
<h3 class="title">提示</h3> <h3 class="title">提示</h3>
<MdPreview <Markdown html :content="hint" />
preview-theme="vuepress"
:model-value="hint"
:theme="isDark ? 'dark' : 'light'"
/>
</template> </template>
</div> </div>
@@ -347,14 +328,6 @@ onMounted(() => nextTick(render))
border-left: 3px solid v-bind("theme.primaryColor"); border-left: 3px solid v-bind("theme.primaryColor");
} }
.page :deep(.md-editor) {
background: transparent;
}
.page :deep(.md-editor-preview-wrapper) {
padding: 0;
}
.io { .io {
display: grid; display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-columns: repeat(2, minmax(0, 1fr));
+1 -5
View File
@@ -203,7 +203,7 @@ onMounted(init)
<MarkdownEditor <MarkdownEditor
ref="editor" ref="editor"
v-model:value="tutorial.content" v-model:value="tutorial.content"
:preview="false" :code-lang="tutorial.type"
height="100%" height="100%"
/> />
</div> </div>
@@ -340,10 +340,6 @@ onMounted(init)
min-width: 0; min-width: 0;
border-right: 1px solid rgba(128, 128, 128, 0.22); border-right: 1px solid rgba(128, 128, 128, 0.22);
} }
.source :deep(.md-editor) {
border: 0;
border-radius: 0;
}
.preview { .preview {
flex: 0 0 50%; flex: 0 0 50%;
min-width: 0; min-width: 0;
-8
View File
@@ -33,14 +33,6 @@ body {
padding-top: 8px; padding-top: 8px;
} }
.md-editor-dark {
--md-bk-color: var(--n-body-color) !important;
}
.md-editor-dark div.vuepress-theme {
--md-theme-color: var(--n-text-color) !important;
}
.oj-mermaid-surface { .oj-mermaid-surface {
box-sizing: border-box; box-sizing: border-box;
padding: 18px; padding: 18px;
+2 -7
View File
@@ -19,15 +19,14 @@
</template> </template>
开始分析 开始分析
</n-button> </n-button>
<MdPreview v-else :model-value="aiStore.mdContent" /> <Markdown v-else :content="aiStore.mdContent" />
</n-flex> </n-flex>
</n-spin> </n-spin>
</n-card> </n-card>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useAIStore } from "oj/store/ai" import { useAIStore } from "oj/store/ai"
import { MdPreview } from "md-editor-v3" import Markdown from "shared/components/Markdown.vue"
import "md-editor-v3/lib/preview.css"
import { Icon } from "@iconify/vue" import { Icon } from "@iconify/vue"
const aiStore = useAIStore() const aiStore = useAIStore()
@@ -86,8 +85,4 @@ onMounted(async () => {
.container { .container {
min-height: 120px; min-height: 120px;
} }
:deep(.md-editor-preview h1) {
margin-top: 0;
}
</style> </style>
+2 -11
View File
@@ -1,7 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import type { ClassBattleItem, ClassPk, ClassPkPeriod } from "@oj2/contract" import type { ClassBattleItem, ClassPk, ClassPkPeriod } from "@oj2/contract"
import { MdPreview } from "md-editor-v3" import Markdown from "shared/components/Markdown.vue"
import "md-editor-v3/lib/preview.css"
import { useThemeVars } from "naive-ui" import { useThemeVars } from "naive-ui"
import { getClassBattle, getClassPk } from "oj/api" import { getClassBattle, getClassPk } from "oj/api"
import { classLabel, groupClassOptions } from "oj/submission/utils" import { classLabel, groupClassOptions } from "oj/submission/utils"
@@ -293,7 +292,7 @@ async function analyze() {
<n-button size="small" :loading="ai.running.value" @click="analyze">重新分析</n-button> <n-button size="small" :loading="ai.running.value" @click="analyze">重新分析</n-button>
</div> </div>
<span v-if="ai.waiting.value" class="muted">正在看这几个班的数据…</span> <span v-if="ai.waiting.value" class="muted">正在看这几个班的数据…</span>
<MdPreview v-if="report" class="report" :model-value="report" /> <Markdown v-if="report" :content="report" />
</section> </section>
</template> </template>
<div v-else-if="!loading" class="card empty"> <div v-else-if="!loading" class="card empty">
@@ -518,14 +517,6 @@ button.chip {
font-size: var(--oj-fs-meta); font-size: var(--oj-fs-meta);
} }
.report {
background: transparent;
}
.report :deep(.md-editor-preview-wrapper) {
padding: 0;
}
.compact .chip { .compact .chip {
font-size: var(--oj-fs-meta); font-size: var(--oj-fs-meta);
} }
@@ -1,8 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import ExerciseResult from "./ExerciseResult.vue" import ExerciseResult from "./ExerciseResult.vue"
import type { Exercise, ExerciseDebugData } from "utils/types" import type { Exercise, ExerciseDebugData } from "utils/types"
import { highlightLines } from "../composables/useCodeHighlight" import { highlightLines } from "shared/highlight"
import "./exercise-highlight.css" import "shared/highlight.css"
const props = defineProps<{ exercise: Exercise; lang?: string }>() const props = defineProps<{ exercise: Exercise; lang?: string }>()
const emit = defineEmits<{ const emit = defineEmits<{
@@ -1,8 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import ExerciseResult from "./ExerciseResult.vue" import ExerciseResult from "./ExerciseResult.vue"
import type { Exercise, ExerciseFillData } from "utils/types" import type { Exercise, ExerciseFillData } from "utils/types"
import { highlight } from "../composables/useCodeHighlight" import { highlight } from "shared/highlight"
import "./exercise-highlight.css" import "shared/highlight.css"
const props = defineProps<{ exercise: Exercise; lang?: string }>() const props = defineProps<{ exercise: Exercise; lang?: string }>()
const emit = defineEmits<{ const emit = defineEmits<{
@@ -1,8 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import ExerciseResult from "./ExerciseResult.vue" import ExerciseResult from "./ExerciseResult.vue"
import type { Exercise, ExercisePredictData } from "utils/types" import type { Exercise, ExercisePredictData } from "utils/types"
import { highlight } from "../composables/useCodeHighlight" import { highlight } from "shared/highlight"
import "./exercise-highlight.css" import "shared/highlight.css"
const props = defineProps<{ exercise: Exercise; lang?: string }>() const props = defineProps<{ exercise: Exercise; lang?: string }>()
const emit = defineEmits<{ const emit = defineEmits<{
@@ -2,8 +2,8 @@
import ExerciseResult from "./ExerciseResult.vue" import ExerciseResult from "./ExerciseResult.vue"
import type { Exercise, ExerciseSortData } from "utils/types" import type { Exercise, ExerciseSortData } from "utils/types"
import { shuffle } from "../composables/useShuffle" import { shuffle } from "../composables/useShuffle"
import { highlightLines } from "../composables/useCodeHighlight" import { highlightLines } from "shared/highlight"
import "./exercise-highlight.css" import "shared/highlight.css"
const props = defineProps<{ exercise: Exercise; lang?: string }>() const props = defineProps<{ exercise: Exercise; lang?: string }>()
const emit = defineEmits<{ const emit = defineEmits<{
@@ -1,6 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { MdPreview } from "md-editor-v3" import Markdown from "shared/components/Markdown.vue"
import "md-editor-v3/lib/preview.css"
import type { LessonSegment } from "../composables/useLessonParse" import type { LessonSegment } from "../composables/useLessonParse"
import CodeRunBlock from "./CodeRunBlock.vue" import CodeRunBlock from "./CodeRunBlock.vue"
@@ -16,9 +15,7 @@ defineProps<{
}>() }>()
const emit = defineEmits<{ solved: [exerciseId: number] }>() const emit = defineEmits<{ solved: [exerciseId: number] }>()
const isDark = useDark() /** 学习目标那几行只有行内的 **加粗** 和 `代码`,先转义再换成标签,别为它拉一整个 Markdown 渲染 */
/** 学习目标那几行只有行内的 **加粗** 和 `代码`,先转义再换成标签,别为它拉一个 MdPreview */
function inline(text: string) { function inline(text: string) {
return text return text
.replace(/&/g, "&amp;") .replace(/&/g, "&amp;")
@@ -32,13 +29,7 @@ function inline(text: string) {
<template> <template>
<div class="body"> <div class="body">
<template v-for="(seg, i) in segments" :key="i"> <template v-for="(seg, i) in segments" :key="i">
<MdPreview <Markdown html v-if="seg.type === 'md'" :content="seg.content" />
v-if="seg.type === 'md'"
preview-theme="vuepress"
:theme="isDark ? 'dark' : 'light'"
:model-value="seg.content"
class="md"
/>
<h2 v-else-if="seg.type === 'heading'" :id="seg.id" class="h2">{{ seg.text }}</h2> <h2 v-else-if="seg.type === 'heading'" :id="seg.id" class="h2">{{ seg.text }}</h2>
<div v-else-if="seg.type === 'goals'" :id="seg.id" class="goals"> <div v-else-if="seg.type === 'goals'" :id="seg.id" class="goals">
<div class="goals-title">学完这课你能</div> <div class="goals-title">学完这课你能</div>
@@ -65,16 +56,9 @@ function inline(text: string) {
<style scoped> <style scoped>
.body { .body {
font-size: 15px; font-size: 16px;
line-height: 1.85; line-height: 1.85;
} }
.md :deep(.md-editor-preview) {
font-size: 15px;
padding: 0;
}
.md :deep(.md-editor-preview-wrapper) {
padding: 0;
}
.h2 { .h2 {
font-size: 20px; font-size: 20px;
line-height: 1.4; line-height: 1.4;
@@ -8,7 +8,7 @@ import type { Exercise } from "utils/types"
* - `code`:带语言的代码块(```python / ```c)换成能改、能运行的代码块; * - `code`:带语言的代码块(```python / ```c)换成能改、能运行的代码块;
* 不带语言的(「输出结果」那种)留在 Markdown 里照常显示; * 不带语言的(「输出结果」那种)留在 Markdown 里照常显示;
* - `exercise`:`[[exercise:36]]` 占位符换成练一练; * - `exercise`:`[[exercise:36]]` 占位符换成练一练;
* - `md`:其余的交给 MdPreview。 * - `md`:其余的交给 Markdown.vue。
* *
* 正文开头的「# 标题」「**所属项目:…**」和紧跟着的项目配图不渲染:标题和项目页面上方 * 正文开头的「# 标题」「**所属项目:…**」和紧跟着的项目配图不渲染:标题和项目页面上方
* 已经有了,每课都重复一张同样的项目图只是把正文往下推。 * 已经有了,每课都重复一张同样的项目图只是把正文往下推。
@@ -6,9 +6,7 @@ import { useProblemStore } from "oj/store/problem"
import { DIFFICULTY } from "utils/constants" import { DIFFICULTY } from "utils/constants"
import { copyToClipboard, getTagColor } from "utils/functions" import { copyToClipboard, getTagColor } from "utils/functions"
import { useSubmissionStore } from "oj/store/submission" import { useSubmissionStore } from "oj/store/submission"
import { useDark } from "@vueuse/core" import Markdown from "shared/components/Markdown.vue"
import { MdPreview } from "md-editor-v3"
import "md-editor-v3/lib/preview.css"
import SqlProblemData from "./SqlProblemData.vue" import SqlProblemData from "./SqlProblemData.vue"
import SimilarProblems from "./SimilarProblems.vue" import SimilarProblems from "./SimilarProblems.vue"
import { isFlowchartPass, useFlowchartStore } from "oj/store/flowchart" import { isFlowchartPass, useFlowchartStore } from "oj/store/flowchart"
@@ -19,7 +17,6 @@ import { useProblemPageContext } from "../composables/problemPageContext"
const ProblemFlowchart = defineAsyncComponent(() => import("./ProblemFlowchart.vue")) const ProblemFlowchart = defineAsyncComponent(() => import("./ProblemFlowchart.vue"))
const MyFlowchart = defineAsyncComponent(() => import("./MyFlowchart.vue")) const MyFlowchart = defineAsyncComponent(() => import("./MyFlowchart.vue"))
const isDark = useDark()
const theme = useThemeVars() const theme = useThemeVars()
const problemStore = useProblemStore() const problemStore = useProblemStore()
const { problem } = storeToRefs(problemStore) const { problem } = storeToRefs(problemStore)
@@ -234,30 +231,18 @@ const astRequirements = computed(() => Object.entries(problem.value?.astRequirem
<section class="block"> <section class="block">
<h3 class="title">描述</h3> <h3 class="title">描述</h3>
<MdPreview <Markdown html :content="problem.description" />
preview-theme="vuepress"
:model-value="problem.description"
:theme="isDark ? 'dark' : 'light'"
/>
</section> </section>
<!-- 输入、输出一般都只有一两句,左右摆开省半屏 --> <!-- 输入、输出一般都只有一两句,左右摆开省半屏 -->
<div v-if="!isSQL" class="io"> <div v-if="!isSQL" class="io">
<section class="block"> <section class="block">
<h3 class="title">输入</h3> <h3 class="title">输入</h3>
<MdPreview <Markdown html :content="problem.inputDescription" />
preview-theme="vuepress"
:model-value="problem.inputDescription"
:theme="isDark ? 'dark' : 'light'"
/>
</section> </section>
<section class="block"> <section class="block">
<h3 class="title">输出</h3> <h3 class="title">输出</h3>
<MdPreview <Markdown html :content="problem.outputDescription" />
preview-theme="vuepress"
:model-value="problem.outputDescription"
:theme="isDark ? 'dark' : 'light'"
/>
</section> </section>
</div> </div>
@@ -388,20 +373,12 @@ const astRequirements = computed(() => Object.entries(problem.value?.astRequirem
<section v-if="problem.hint" class="block"> <section v-if="problem.hint" class="block">
<h3 class="title">提示</h3> <h3 class="title">提示</h3>
<MdPreview <Markdown html :content="problem.hint" />
preview-theme="preview"
:model-value="problem.hint"
:theme="isDark ? 'dark' : 'light'"
/>
</section> </section>
<section v-if="problem.source" class="block"> <section v-if="problem.source" class="block">
<h3 class="title">来源</h3> <h3 class="title">来源</h3>
<MdPreview <Markdown html :content="problem.source" />
preview-theme="vuepress"
:model-value="problem.source"
:theme="isDark ? 'dark' : 'light'"
/>
</section> </section>
<SimilarProblems v-if="showSimilar" title="相似题目推荐" /> <SimilarProblems v-if="showSimilar" title="相似题目推荐" />
@@ -477,23 +454,6 @@ const astRequirements = computed(() => Object.entries(problem.value?.astRequirem
border-left: 3px solid v-bind("theme.primaryColor"); border-left: 3px solid v-bind("theme.primaryColor");
} }
/* md-editor 的预览自带一圈 padding、白底和段落外边距,放在小节标题下面显得很散 */
:deep(.md-editor) {
background: transparent;
}
:deep(.md-editor-preview-wrapper) {
padding: 0;
}
:deep(.md-editor-preview > :first-child) {
margin-top: 0;
}
:deep(.md-editor-preview > :last-child) {
margin-bottom: 0;
}
.io { .io {
display: grid; display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-columns: repeat(2, minmax(0, 1fr));
@@ -23,9 +23,7 @@ import ResultHeader from "./ResultHeader.vue"
import SimilarProblems from "./SimilarProblems.vue" import SimilarProblems from "./SimilarProblems.vue"
import { useLessonStore } from "oj/store/lesson" import { useLessonStore } from "oj/store/lesson"
import { useProblemPageContext } from "../composables/problemPageContext" import { useProblemPageContext } from "../composables/problemPageContext"
import { MdPreview } from "md-editor-v3" import Markdown from "shared/components/Markdown.vue"
import "md-editor-v3/lib/preview.css"
import { useDark } from "@vueuse/core"
const props = defineProps<{ const props = defineProps<{
submission?: Submission submission?: Submission
@@ -36,7 +34,6 @@ const props = defineProps<{
peer?: boolean peer?: boolean
}>() }>()
const isDark = useDark()
const problemStore = useProblemStore() const problemStore = useProblemStore()
const theme = useThemeVars() const theme = useThemeVars()
@@ -390,12 +387,7 @@ const columns: DataTableColumn<JudgeCaseResult>[] = [
<template v-if="showAIHint && hintTarget"> <template v-if="showAIHint && hintTarget">
<n-card size="small" class="hint-card"> <n-card size="small" class="hint-card">
<n-spin v-if="hintLoading && !hintContent" size="small" /> <n-spin v-if="hintLoading && !hintContent" size="small" />
<MdPreview <Markdown v-if="hintContent" :content="hintContent" />
v-if="hintContent"
:model-value="hintContent"
preview-theme="vuepress"
:theme="isDark ? 'dark' : 'light'"
/>
<!-- 等级和「再多一点提示」。按钮出不出由后端 done 里的 canEscalate 定, <!-- 等级和「再多一点提示」。按钮出不出由后端 done 里的 canEscalate 定,
前端不自己推阶梯(要再交一次才升得动,规则在 services/hint-level.ts) --> 前端不自己推阶梯(要再交一次才升得动,规则在 services/hint-level.ts) -->
<n-flex <n-flex
@@ -30,7 +30,7 @@ export function useSubmissionHint() {
const hintFeedbackSending = ref(false) const hintFeedbackSending = ref(false)
// 打字机:每 24ms 吐 3 个字,约 125 字/秒。步子不敢迈太小 —— // 打字机:每 24ms 吐 3 个字,约 125 字/秒。步子不敢迈太小 ——
// 每一帧都要让 MdPreview 重渲染一次 Markdown,机房那批机器扛不住逐字 // 每一帧都要让 Markdown 重渲染一次 Markdown,机房那批机器扛不住逐字
const TYPE_STEP = 3 const TYPE_STEP = 3
const TYPE_INTERVAL = 24 const TYPE_INTERVAL = 24
let typingTimer: ReturnType<typeof setInterval> | null = null let typingTimer: ReturnType<typeof setInterval> | null = null
@@ -1,7 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import type { ClassDetail } from "@oj2/contract" import type { ClassDetail } from "@oj2/contract"
import { MdPreview } from "md-editor-v3" import Markdown from "shared/components/Markdown.vue"
import "md-editor-v3/lib/preview.css"
import { useThemeVars } from "naive-ui" import { useThemeVars } from "naive-ui"
import { getClassDetail } from "oj/api" import { getClassDetail } from "oj/api"
import { classLabel } from "oj/submission/utils" import { classLabel } from "oj/submission/utils"
@@ -237,7 +236,7 @@ function go(path: string, query: Record<string, string>) {
</n-button> </n-button>
</div> </div>
<span v-if="ai.waiting.value" class="muted">正在看这个班的数据…</span> <span v-if="ai.waiting.value" class="muted">正在看这个班的数据…</span>
<MdPreview v-if="report" class="report" :model-value="report" /> <Markdown v-if="report" :content="report" />
</section> </section>
<a v-if="pk" href="#" class="pk" @click.prevent="go('/class', { classes: className! })" <a v-if="pk" href="#" class="pk" @click.prevent="go('/class', { classes: className! })"
@@ -461,12 +460,4 @@ section {
.ai-head b { .ai-head b {
color: v-bind("theme.textColor1"); color: v-bind("theme.textColor1");
} }
.report {
background: transparent;
}
.report :deep(.md-editor-preview-wrapper) {
padding: 0;
}
</style> </style>
+163
View File
@@ -0,0 +1,163 @@
<script setup lang="ts">
import { useThemeVars } from "naive-ui"
import { renderMarkdown } from "shared/markdown"
import "shared/highlight.css"
/**
* 显示一段 Markdown / HTML 正文:题面、教程、AI 的提示和报告。
* `html` 只给老师写的内容(题面、教程)打开,AI 生成的别开 —— 理由见 shared/markdown.ts。
* 默认 16px / 1.75,和原来 md-editor 一样;各页可以用自己的 class 盖掉。
*/
const { content, html = false } = defineProps<{
content: string | null | undefined
html?: boolean
}>()
const theme = useThemeVars()
const rendered = computed(() => renderMarkdown(content ?? "", html))
</script>
<template>
<div class="oj-markdown" v-html="rendered" />
</template>
<!-- 不加 scoped:v-html 进来的节点不带 scoped 的属性,靠 .oj-markdown 前缀收住范围 -->
<style>
.oj-markdown {
font-size: 16px;
line-height: 1.75;
/* 长英文、长网址在单词之间折;实在折不开再断词。原来 md-editor 是 break-all,
题面里「Hello, I am …」这种一句话会从单词中间断开 */
overflow-wrap: break-word;
}
.oj-markdown > :first-child {
margin-top: 0;
}
.oj-markdown > :last-child {
margin-bottom: 0;
}
.oj-markdown p {
margin: 0.7em 0;
}
.oj-markdown h1,
.oj-markdown h2,
.oj-markdown h3,
.oj-markdown h4,
.oj-markdown h5,
.oj-markdown h6 {
margin: 1.2em 0 0.5em;
font-weight: 600;
line-height: 1.4;
}
.oj-markdown h1 {
font-size: 1.5em;
}
.oj-markdown h2 {
font-size: 1.3em;
}
.oj-markdown h3 {
font-size: 1.15em;
}
.oj-markdown h4,
.oj-markdown h5,
.oj-markdown h6 {
font-size: 1em;
}
.oj-markdown ul,
.oj-markdown ol {
margin: 0.5em 0;
padding-left: 1.6em;
}
.oj-markdown li + li {
margin-top: 0.25em;
}
.oj-markdown li > p {
margin: 0.25em 0;
}
.oj-markdown a {
color: v-bind("theme.primaryColor");
text-decoration: none;
}
.oj-markdown a:hover {
text-decoration: underline;
}
.oj-markdown img {
max-width: 100%;
height: auto;
vertical-align: middle;
}
.oj-markdown hr {
margin: 1.2em 0;
border: 0;
border-top: 1px solid v-bind("theme.dividerColor");
}
.oj-markdown blockquote {
margin: 0.8em 0;
padding: 0.1em 1em;
border-left: 4px solid v-bind("theme.dividerColor");
color: v-bind("theme.textColor3");
}
.oj-markdown code {
padding: 0.1em 0.45em;
border-radius: 4px;
background-color: rgba(128, 128, 128, 0.12);
font-family: Consolas, Monaco, monospace;
/* 等宽字体比同字号的中文矮,再缩就和旁边的字差一截 */
font-size: 0.95em;
}
.oj-markdown pre {
margin: 0.8em 0;
padding: 12px 14px;
border-radius: 6px;
background-color: rgba(128, 128, 128, 0.08);
overflow-x: auto;
line-height: 1.6;
}
.oj-markdown pre code {
padding: 0;
border-radius: 0;
background: none;
font-size: 14px;
white-space: pre;
}
/* 宽表自己横着滚,不把整页撑出横向滚动条 */
.oj-markdown table {
display: block;
max-width: 100%;
overflow-x: auto;
margin: 0.8em 0;
border-collapse: collapse;
}
.oj-markdown th,
.oj-markdown td {
padding: 6px 12px;
border: 1px solid v-bind("theme.dividerColor");
text-align: left;
}
.oj-markdown th {
font-weight: 600;
background-color: rgba(128, 128, 128, 0.08);
}
</style>
+233 -41
View File
@@ -1,60 +1,252 @@
<template>
<MdEditor
ref="editor"
:theme="isDark ? 'dark' : 'light'"
v-model="modelValue"
:preview="preview"
:style="height ? { height } : undefined"
@onUploadImg="onUploadImg"
/>
</template>
<script setup lang="ts"> <script setup lang="ts">
import { MdEditor, type ExposeParam } from "md-editor-v3" import { markdown } from "@codemirror/lang-markdown"
import "md-editor-v3/lib/style.css" import { EditorSelection } from "@codemirror/state"
import { EditorView, keymap } from "@codemirror/view"
import { Icon } from "@iconify/vue"
import { Codemirror } from "vue-codemirror"
import { uploadImage } from "../../admin/api" import { uploadImage } from "../../admin/api"
import { styleTheme } from "../extensions/baseTheme"
import { oneDark } from "../themes/oneDark"
import { smoothy } from "../themes/smoothy"
/** /**
* `preview` 关掉自带的预览:教程编辑页右边要用学生端同一套组件预览(练一练、能运行的 * 后台教程正文的 Markdown 编辑器:左边写,右边由教程编辑页用学生端同一套组件预览。
* 代码块),md-editor 自己那份预览认不出 `[[exercise:N]]`。 * 原来是 md-editor-v3,但它每次打开都去 unpkg.com 拉 highlight.js、katex、mermaid、echarts,
* 而这里只需要一个能插格式、能传图的文本框,所以换成项目里已有的 CodeMirror。
* 图片三种进法:工具栏按钮选文件、粘贴、拖进来,都是先传到服务器再插 ![](地址)。
*/ */
const { preview = true, height } = defineProps<{ preview?: boolean; height?: string }>() const { height, codeLang = "python" } = defineProps<{
height?: string
const isDark = useDark() /** 「代码块」按钮插入的语言:教程里标了 python / c 的代码块在学生端是能运行的 */
const editor = useTemplateRef<ExposeParam>("editor") codeLang?: string
}>()
const modelValue = defineModel<string>("value") const modelValue = defineModel<string>("value")
const isDark = useDark()
const message = useMessage() const message = useMessage()
const view = shallowRef<EditorView>()
/** 在光标处插一段文字(教程编辑页插练一练占位符用),自成一行 */ /** 选中了就把选中的包起来,没选中就插一段占位文字并选中它,方便直接改 */
function wrap(before: string, after: string, placeholder: string) {
const v = view.value
if (!v) return
v.dispatch(
v.state.changeByRange((range) => {
const text = range.empty ? placeholder : v.state.sliceDoc(range.from, range.to)
return {
changes: { from: range.from, to: range.to, insert: before + text + after },
range: EditorSelection.range(
range.from + before.length,
range.from + before.length + text.length,
),
}
}),
)
v.focus()
}
/** 给选中的每一行(没选中就是光标那行)行首加前缀:标题、列表、引用 */
function prefixLines(prefix: (index: number) => string) {
const v = view.value
if (!v) return
const { from, to } = v.state.selection.main
const first = v.state.doc.lineAt(from).number
const last = v.state.doc.lineAt(to).number
const changes = []
for (let n = first; n <= last; n++) {
changes.push({ from: v.state.doc.line(n).from, insert: prefix(n - first) })
}
v.dispatch({ changes })
v.focus()
}
/**
* 在光标处插一段自成一行的内容;`cursor` 是插完后光标落在这段文字里的位置(默认放末尾)
*/
function insertBlock(text: string, cursor = text.length) {
const v = view.value
if (!v) return
const { from, to } = v.state.selection.main
const line = v.state.doc.lineAt(from)
const lead = from === line.from ? "" : "\n"
const insert = `${lead}${text}\n`
v.dispatch({
changes: { from, to, insert },
selection: { anchor: from + lead.length + cursor },
})
v.focus()
}
/** 教程编辑页插练一练占位符用 */
function insert(text: string) { function insert(text: string) {
editor.value?.insert(() => ({ insertBlock(text)
targetValue: `\n${text}\n`,
select: false,
deviationStart: 0,
deviationEnd: 0,
}))
} }
defineExpose({ insert }) defineExpose({ insert })
const onUploadImg = async (files: File[], callback: (urls: string[]) => void) => { const uploading = ref(false)
const fileInput = useTemplateRef<HTMLInputElement>("fileInput")
async function uploadAndInsert(files: File[]) {
const images = files.filter((file) => file.type.startsWith("image/"))
if (!images.length) return
uploading.value = true
try { try {
const res = await Promise.all( const paths = await Promise.all(images.map((file) => uploadImage(file).catch(() => "")))
files.map(async (file) => { if (paths.some((path) => !path)) message.error("有图片没传上去")
const path = await uploadImage(file) const ok = paths.filter(Boolean)
if (!path) { if (ok.length) insertBlock(ok.map((path) => `![](${path})`).join("\n"))
message.error("图片上传失败") } finally {
return "" uploading.value = false
}
return path
}),
)
callback(res.filter((url) => url !== ""))
} catch (err) {
message.error("图片上传失败")
callback([])
} }
} }
function onPickImages(e: Event) {
const input = e.target as HTMLInputElement
void uploadAndInsert([...(input.files ?? [])])
input.value = ""
}
const imageEvents = EditorView.domEventHandlers({
paste(event) {
const files = [...(event.clipboardData?.files ?? [])]
if (!files.some((file) => file.type.startsWith("image/"))) return false
event.preventDefault()
void uploadAndInsert(files)
return true
},
drop(event, v) {
const files = [...(event.dataTransfer?.files ?? [])]
if (!files.some((file) => file.type.startsWith("image/"))) return false
event.preventDefault()
// 插到松手的位置
const pos = v.posAtCoords({ x: event.clientX, y: event.clientY })
if (pos !== null) v.dispatch({ selection: { anchor: pos } })
void uploadAndInsert(files)
return true
},
})
const shortcuts = keymap.of([
{ key: "Mod-b", run: () => (wrap("**", "**", "加粗文字"), true) },
{ key: "Mod-i", run: () => (wrap("*", "*", "斜体文字"), true) },
])
/** styleTheme 只写了 Monaco,机房的 Windows 没有它;和 Markdown.vue 里代码的字体保持一致 */
const fontTheme = EditorView.theme({
"& .cm-scroller": { fontFamily: "Consolas, Monaco, monospace" },
})
const extensions = computed(() => [
styleTheme,
fontTheme,
markdown(),
EditorView.lineWrapping,
imageEvents,
shortcuts,
isDark.value ? oneDark : smoothy,
])
const tools = computed(() => [
{ icon: "ph:text-h-two-bold", title: "标题", run: () => prefixLines(() => "## ") },
{ icon: "ph:text-b-bold", title: "加粗(Ctrl+B)", run: () => wrap("**", "**", "加粗文字") },
{ icon: "ph:code-bold", title: "行内代码", run: () => wrap("`", "`", "代码") },
{
icon: "ph:code-block-bold",
title: `代码块(${codeLang},学生那边能运行)`,
run: () => insertBlock(`\`\`\`${codeLang}\n\n\`\`\``, codeLang.length + 4),
},
{ icon: "ph:list-bullets-bold", title: "无序列表", run: () => prefixLines(() => "- ") },
{ icon: "ph:list-numbers-bold", title: "有序列表", run: () => prefixLines((i) => `${i + 1}. `) },
{ icon: "ph:quotes-bold", title: "引用", run: () => prefixLines(() => "> ") },
{
icon: "ph:table-bold",
title: "表格",
run: () => insertBlock("| 列 1 | 列 2 |\n| --- | --- |\n| | |"),
},
{ icon: "ph:link-bold", title: "链接", run: () => wrap("[", "](https://)", "链接文字") },
])
</script> </script>
<template>
<div class="editor-box" :style="height ? { height } : undefined">
<div class="toolbar">
<button
v-for="tool in tools"
:key="tool.icon"
type="button"
class="tool"
:title="tool.title"
:aria-label="tool.title"
@click="tool.run"
>
<Icon :icon="tool.icon" :width="16" />
</button>
<button
type="button"
class="tool"
title="图片(也可以直接粘贴、拖进来)"
aria-label="插入图片"
:disabled="uploading"
@click="fileInput?.click()"
>
<Icon icon="ph:image-bold" :width="16" />
</button>
<input ref="fileInput" type="file" accept="image/*" multiple hidden @change="onPickImages" />
</div>
<div class="body">
<Codemirror
v-model="modelValue"
:extensions="extensions"
:tab-size="4"
:style="{ height: '100%', fontSize: '14px' }"
@ready="view = $event.view"
/>
</div>
</div>
</template>
<style scoped>
.editor-box {
display: flex;
flex-direction: column;
min-height: 300px;
}
.toolbar {
flex: none;
display: flex;
flex-wrap: wrap;
gap: 2px;
padding: 4px 6px;
border-bottom: 1px solid rgba(128, 128, 128, 0.22);
}
.tool {
width: 30px;
height: 28px;
display: inline-flex;
align-items: center;
justify-content: center;
border: 0;
border-radius: 4px;
background: transparent;
color: inherit;
cursor: pointer;
}
.tool:hover:not(:disabled) {
background-color: rgba(128, 128, 128, 0.14);
}
.tool:disabled {
cursor: wait;
opacity: 0.6;
}
.body {
flex: 1;
min-height: 0;
}
</style>
@@ -1,4 +1,4 @@
/* 练一练代码高亮配色(明 / 暗),由涉及代码高亮的题型组件统一引入 */ /* 代码高亮配色(明 / 暗):练一练的题型组件和 Markdown.vue 的代码块共用,见 shared/highlight.ts */
.hljs-keyword, .hljs-keyword,
.hljs-operator, .hljs-operator,
.hljs-selector-tag { .hljs-selector-tag {
@@ -1,16 +1,34 @@
/**
* 代码高亮:自学的练一练、以及 Markdown.vue 里的代码块共用这一份(配色在 highlight.css)。
* 只注册判题机认的几种语言,别的语言和不标语言的代码块按原文显示。
*/
import hljs from "highlight.js/lib/core" import hljs from "highlight.js/lib/core"
import python from "highlight.js/lib/languages/python"
import c from "highlight.js/lib/languages/c" import c from "highlight.js/lib/languages/c"
import cpp from "highlight.js/lib/languages/cpp"
import python from "highlight.js/lib/languages/python"
import sql from "highlight.js/lib/languages/sql"
hljs.registerLanguage("python", python) hljs.registerLanguage("python", python)
hljs.registerLanguage("c", c) hljs.registerLanguage("c", c)
hljs.registerLanguage("cpp", cpp)
hljs.registerLanguage("sql", sql)
const LANGUAGE_ALIASES: Record<string, string> = {
python: "python",
py: "python",
python3: "python",
c: "c",
cpp: "cpp",
"c++": "cpp",
sql: "sql",
}
export function escapeHtml(text: string): string { export function escapeHtml(text: string): string {
return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;") return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")
} }
function normalizeLang(lang?: string): "python" | "c" | null { function normalizeLang(lang?: string): string | null {
return lang === "python" ? "python" : lang === "c" ? "c" : null return LANGUAGE_ALIASES[lang?.toLowerCase() ?? ""] ?? null
} }
// 把整段代码高亮为 HTML;不支持的语言或异常时回退为转义文本 // 把整段代码高亮为 HTML;不支持的语言或异常时回退为转义文本
+34
View File
@@ -0,0 +1,34 @@
/**
* Markdown / HTML 正文渲染,配 shared/components/Markdown.vue 用。
*
* 原来用 md-editor-v3 的 MdPreview:不管正文里有没有代码、公式,每次打开都去 unpkg.com
* 拉 highlight.js、katex、mermaid、echarts(实测,6.x 起就这样),机房网络下慢且不稳;
* 而我们只用到最基础的 Markdown —— 题面 95% 是富文本编辑器存的 HTML,教程是标题、表格、
* 图片,AI 的输出是标题、列表、表格、少量代码块,库里一处公式、mermaid 都没有。
* 现在直接用 markdown-it(md-editor 内部也是它),代码高亮走本地的 shared/highlight.ts。
*
* 两档信任:
* - 题面、教程是老师写的,原生 HTML 必须放行(富文本存的就是 HTML),原来 md-editor 也是放行的;
* - AI 生成的东西不放行。学生能在代码里夹带指令,诱导 AI 吐出 <img onerror> 一类的 HTML,
* 老师在后台一打开就执行。库里 1196 条 AI 输出一个 HTML 标签都没有,关掉不影响显示。
*/
import MarkdownIt from "markdown-it"
import { highlight } from "./highlight"
function create(html: boolean) {
return new MarkdownIt({
html,
// 和 md-editor 的默认值一致:单个换行就换行、裸网址变链接
breaks: true,
linkify: true,
highlight: (code, lang) => highlight(code, lang),
})
}
let trusted: MarkdownIt | null = null
let untrusted: MarkdownIt | null = null
export function renderMarkdown(content: string, allowHtml: boolean): string {
if (allowHtml) return (trusted ??= create(true)).render(content)
return (untrusted ??= create(false)).render(content)
}
+10 -78
View File
@@ -42,6 +42,7 @@
"dependencies": { "dependencies": {
"@codemirror/autocomplete": "^6.20.3", "@codemirror/autocomplete": "^6.20.3",
"@codemirror/lang-cpp": "^6.0.3", "@codemirror/lang-cpp": "^6.0.3",
"@codemirror/lang-markdown": "^6.5.2",
"@codemirror/lang-python": "^6.2.1", "@codemirror/lang-python": "^6.2.1",
"@codemirror/lang-sql": "^6.10.0", "@codemirror/lang-sql": "^6.10.0",
"@codemirror/language": "^6.12.4", "@codemirror/language": "^6.12.4",
@@ -69,7 +70,7 @@
"fflate": "^0.8.3", "fflate": "^0.8.3",
"highlight.js": "^11.12.0", "highlight.js": "^11.12.0",
"lib0": "0.2.117", "lib0": "0.2.117",
"md-editor-v3": "^6.5.6", "markdown-it": "^14.3.0",
"mermaid": "^11.17.2", "mermaid": "^11.17.2",
"naive-ui": "^2.45.2", "naive-ui": "^2.45.2",
"nanoid": "^6.0.1", "nanoid": "^6.0.1",
@@ -87,6 +88,7 @@
"devDependencies": { "devDependencies": {
"@iconify/vue": "^5.0.1", "@iconify/vue": "^5.0.1",
"@types/canvas-confetti": "^1.9.0", "@types/canvas-confetti": "^1.9.0",
"@types/markdown-it": "^14.1.2",
"@types/node": "^26.3.0", "@types/node": "^26.3.0",
"@vitejs/plugin-legacy": "^8.2.3", "@vitejs/plugin-legacy": "^8.2.3",
"@vitejs/plugin-vue": "^6.0.8", "@vitejs/plugin-vue": "^6.0.8",
@@ -300,54 +302,22 @@
"@codemirror/commands": ["@codemirror/commands@6.10.4", "https://registry.npmjs.com/@codemirror/commands/-/commands-6.10.4.tgz", { "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.7.0", "@codemirror/view": "^6.27.0", "@lezer/common": "^1.1.0" } }, "sha512-Ryk9y9T0FFVF0cUGhAknveAyUOl/A1qReTFi+qPKtOh2Z9F4AUBz3XOrYD4ZEgZirdugVzHvd/2/Wcwy5OliTg=="], "@codemirror/commands": ["@codemirror/commands@6.10.4", "https://registry.npmjs.com/@codemirror/commands/-/commands-6.10.4.tgz", { "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.7.0", "@codemirror/view": "^6.27.0", "@lezer/common": "^1.1.0" } }, "sha512-Ryk9y9T0FFVF0cUGhAknveAyUOl/A1qReTFi+qPKtOh2Z9F4AUBz3XOrYD4ZEgZirdugVzHvd/2/Wcwy5OliTg=="],
"@codemirror/lang-angular": ["@codemirror/lang-angular@0.1.4", "https://registry.npmjs.com/@codemirror/lang-angular/-/lang-angular-0.1.4.tgz", { "dependencies": { "@codemirror/lang-html": "^6.0.0", "@codemirror/lang-javascript": "^6.1.2", "@codemirror/language": "^6.0.0", "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.3.3" } }, "sha512-oap+gsltb/fzdlTQWD6BFF4bSLKcDnlxDsLdePiJpCVNKWXSTAbiiQeYI3UmES+BLAdkmIC1WjyztC1pi/bX4g=="],
"@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", "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-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-go": ["@codemirror/lang-go@6.0.1", "https://registry.npmjs.com/@codemirror/lang-go/-/lang-go-6.0.1.tgz", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/language": "^6.6.0", "@codemirror/state": "^6.0.0", "@lezer/common": "^1.0.0", "@lezer/go": "^1.0.0" } }, "sha512-7fNvbyNylvqCphW9HD6WFnRpcDjr+KXX/FgqXy5H5ZS0eC5edDljukm/yNgYkwTsgp2busdod50AOTIy6Jikfg=="],
"@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-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-java": ["@codemirror/lang-java@6.0.2", "https://registry.npmjs.com/@codemirror/lang-java/-/lang-java-6.0.2.tgz", { "dependencies": { "@codemirror/language": "^6.0.0", "@lezer/java": "^1.0.0" } }, "sha512-m5Nt1mQ/cznJY7tMfQTJchmrjdjQ71IDs+55d1GAa8DGaB8JXWsVCkVT284C3RTASaY43YknrK2X3hPO/J3MOQ=="],
"@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-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-jinja": ["@codemirror/lang-jinja@6.0.1", "https://registry.npmjs.com/@codemirror/lang-jinja/-/lang-jinja-6.0.1.tgz", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/lang-html": "^6.0.0", "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.2.0", "@lezer/lr": "^1.4.0" } }, "sha512-P5kyHLObzjtbGj16h+hyvZTxJhSjBEeSx4wMjbnAf3b0uwTy2+F0zGjMZL4PQOm/mh2eGZ5xUDVZXgwP783Nsw=="],
"@codemirror/lang-json": ["@codemirror/lang-json@6.0.2", "https://registry.npmjs.com/@codemirror/lang-json/-/lang-json-6.0.2.tgz", { "dependencies": { "@codemirror/language": "^6.0.0", "@lezer/json": "^1.0.0" } }, "sha512-x2OtO+AvwEHrEwR0FyyPtfDUiloG3rnVTSZV1W8UteaLL8/MajQd8DpvUb2YVzC+/T18aSDv0H9mu+xw0EStoQ=="],
"@codemirror/lang-less": ["@codemirror/lang-less@6.0.2", "https://registry.npmjs.com/@codemirror/lang-less/-/lang-less-6.0.2.tgz", { "dependencies": { "@codemirror/lang-css": "^6.2.0", "@codemirror/language": "^6.0.0", "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0" } }, "sha512-EYdQTG22V+KUUk8Qq582g7FMnCZeEHsyuOJisHRft/mQ+ZSZ2w51NupvDUHiqtsOy7It5cHLPGfHQLpMh9bqpQ=="],
"@codemirror/lang-liquid": ["@codemirror/lang-liquid@6.3.2", "https://registry.npmjs.com/@codemirror/lang-liquid/-/lang-liquid-6.3.2.tgz", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/lang-html": "^6.0.0", "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", "@lezer/common": "^1.0.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.3.1" } }, "sha512-6PDVU3ZnfeYyz1at1E/ttorErZvZFXXt1OPhtfe1EZJ2V2iDFa0CwPqPgG5F7NXN0yONGoBogKmFAafKTqlwIw=="],
"@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-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-php": ["@codemirror/lang-php@6.0.2", "https://registry.npmjs.com/@codemirror/lang-php/-/lang-php-6.0.2.tgz", { "dependencies": { "@codemirror/lang-html": "^6.0.0", "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@lezer/common": "^1.0.0", "@lezer/php": "^1.0.0" } }, "sha512-ZKy2v1n8Fc8oEXj0Th0PUMXzQJ0AIR6TaZU+PbDHExFwdu+guzOA4jmCHS1Nz4vbFezwD7LyBdDnddSJeScMCA=="],
"@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=="],
"@codemirror/lang-rust": ["@codemirror/lang-rust@6.0.2", "https://registry.npmjs.com/@codemirror/lang-rust/-/lang-rust-6.0.2.tgz", { "dependencies": { "@codemirror/language": "^6.0.0", "@lezer/rust": "^1.0.0" } }, "sha512-EZaGjCUegtiU7kSMvOfEZpaCReowEf3yNidYu7+vfuGTm9ow4mthAparY5hisJqOHmJowVH3Upu+eJlUji6qqA=="],
"@codemirror/lang-sass": ["@codemirror/lang-sass@6.0.2", "https://registry.npmjs.com/@codemirror/lang-sass/-/lang-sass-6.0.2.tgz", { "dependencies": { "@codemirror/lang-css": "^6.2.0", "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@lezer/common": "^1.0.2", "@lezer/sass": "^1.0.0" } }, "sha512-l/bdzIABvnTo1nzdY6U+kPAC51czYQcOErfzQ9zSm9D8GmNPD0WTW8st/CJwBTPLO8jlrbyvlSEcN20dc4iL0Q=="],
"@codemirror/lang-sql": ["@codemirror/lang-sql@6.10.0", "https://registry.npmjs.com/@codemirror/lang-sql/-/lang-sql-6.10.0.tgz", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0" } }, "sha512-6ayPkEd/yRw0XKBx5uAiToSgGECo/GY2NoJIHXIIQh1EVwLuKoU8BP/qK0qH5NLXAbtJRLuT73hx7P9X34iO4w=="], "@codemirror/lang-sql": ["@codemirror/lang-sql@6.10.0", "https://registry.npmjs.com/@codemirror/lang-sql/-/lang-sql-6.10.0.tgz", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0" } }, "sha512-6ayPkEd/yRw0XKBx5uAiToSgGECo/GY2NoJIHXIIQh1EVwLuKoU8BP/qK0qH5NLXAbtJRLuT73hx7P9X34iO4w=="],
"@codemirror/lang-vue": ["@codemirror/lang-vue@0.1.3", "https://registry.npmjs.com/@codemirror/lang-vue/-/lang-vue-0.1.3.tgz", { "dependencies": { "@codemirror/lang-html": "^6.0.0", "@codemirror/lang-javascript": "^6.1.2", "@codemirror/language": "^6.0.0", "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.3.1" } }, "sha512-QSKdtYTDRhEHCfo5zOShzxCmqKJvgGrZwDQSdbvCRJ5pRLWBS7pD/8e/tH44aVQT6FKm0t6RVNoSUWHOI5vNug=="],
"@codemirror/lang-wast": ["@codemirror/lang-wast@6.0.2", "https://registry.npmjs.com/@codemirror/lang-wast/-/lang-wast-6.0.2.tgz", { "dependencies": { "@codemirror/language": "^6.0.0", "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0" } }, "sha512-Imi2KTpVGm7TKuUkqyJ5NRmeFWF7aMpNiwHnLQe0x9kmrxElndyH0K6H/gXtWwY6UshMRAhpENsgfpSwsgmC6Q=="],
"@codemirror/lang-xml": ["@codemirror/lang-xml@6.1.0", "https://registry.npmjs.com/@codemirror/lang-xml/-/lang-xml-6.1.0.tgz", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/language": "^6.4.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", "@lezer/common": "^1.0.0", "@lezer/xml": "^1.0.0" } }, "sha512-3z0blhicHLfwi2UgkZYRPioSgVTo9PV5GP5ducFH6FaHy0IAJRg+ixj5gTR1gnT/glAIC8xv4w2VL1LoZfs+Jg=="],
"@codemirror/lang-yaml": ["@codemirror/lang-yaml@6.1.3", "https://registry.npmjs.com/@codemirror/lang-yaml/-/lang-yaml-6.1.3.tgz", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.2.0", "@lezer/lr": "^1.0.0", "@lezer/yaml": "^1.0.0" } }, "sha512-AZ8DJBuXGVHybpBQhmZtgew5//4hv3tdkXnr3vDmOUMJRuB6vn/uuwtmTOTlqEaQFg3hQSVeA90NmvIQyUV6FQ=="],
"@codemirror/language": ["@codemirror/language@6.12.4", "https://registry.npmjs.com/@codemirror/language/-/language-6.12.4.tgz", { "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.23.0", "@lezer/common": "^1.5.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0", "style-mod": "^4.0.0" } }, "sha512-1q4PaT+o6PbgpkJt4Q8Fv5XJxTy4FUZ4MWETtyiDw3J0Pyr9E2vqcKL+k9wcvjNTIsauxvE7OfmWj3FRPHQ76A=="], "@codemirror/language": ["@codemirror/language@6.12.4", "https://registry.npmjs.com/@codemirror/language/-/language-6.12.4.tgz", { "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.23.0", "@lezer/common": "^1.5.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0", "style-mod": "^4.0.0" } }, "sha512-1q4PaT+o6PbgpkJt4Q8Fv5XJxTy4FUZ4MWETtyiDw3J0Pyr9E2vqcKL+k9wcvjNTIsauxvE7OfmWj3FRPHQ76A=="],
"@codemirror/language-data": ["@codemirror/language-data@6.5.2", "https://registry.npmjs.com/@codemirror/language-data/-/language-data-6.5.2.tgz", { "dependencies": { "@codemirror/lang-angular": "^0.1.0", "@codemirror/lang-cpp": "^6.0.0", "@codemirror/lang-css": "^6.0.0", "@codemirror/lang-go": "^6.0.0", "@codemirror/lang-html": "^6.0.0", "@codemirror/lang-java": "^6.0.0", "@codemirror/lang-javascript": "^6.0.0", "@codemirror/lang-jinja": "^6.0.0", "@codemirror/lang-json": "^6.0.0", "@codemirror/lang-less": "^6.0.0", "@codemirror/lang-liquid": "^6.0.0", "@codemirror/lang-markdown": "^6.0.0", "@codemirror/lang-php": "^6.0.0", "@codemirror/lang-python": "^6.0.0", "@codemirror/lang-rust": "^6.0.0", "@codemirror/lang-sass": "^6.0.0", "@codemirror/lang-sql": "^6.0.0", "@codemirror/lang-vue": "^0.1.1", "@codemirror/lang-wast": "^6.0.0", "@codemirror/lang-xml": "^6.0.0", "@codemirror/lang-yaml": "^6.0.0", "@codemirror/language": "^6.0.0", "@codemirror/legacy-modes": "^6.4.0" } }, "sha512-CPkWBKrNS8stYbEU5kwBwTf3JB1kghlbh4FSAwzGW2TEscdeHHH4FGysREW86Mqnj3Qn09s0/6Ea/TutmoTobg=="],
"@codemirror/legacy-modes": ["@codemirror/legacy-modes@6.5.3", "https://registry.npmjs.com/@codemirror/legacy-modes/-/legacy-modes-6.5.3.tgz", { "dependencies": { "@codemirror/language": "^6.0.0" } }, "sha512-xCsmIzH78MyWkib9jlPaaun57XNkfbMIhagfaZVd0iLTqlpw3jXaIcbZm72MTmmn64eTZpBVNjbyYh+QXnxRsg=="],
"@codemirror/lint": ["@codemirror/lint@6.9.7", "https://registry.npmjs.com/@codemirror/lint/-/lint-6.9.7.tgz", { "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.42.0", "crelt": "^1.0.5" } }, "sha512-28/+iWLYxKxsvGYhSYL7zaCZqLz5+FFFDq9tVsvGv9kv8RY4fFAchJ5WX9M3YrrRlTIsECjsXPqeNgnSmNP2dg=="], "@codemirror/lint": ["@codemirror/lint@6.9.7", "https://registry.npmjs.com/@codemirror/lint/-/lint-6.9.7.tgz", { "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.42.0", "crelt": "^1.0.5" } }, "sha512-28/+iWLYxKxsvGYhSYL7zaCZqLz5+FFFDq9tVsvGv9kv8RY4fFAchJ5WX9M3YrrRlTIsECjsXPqeNgnSmNP2dg=="],
"@codemirror/search": ["@codemirror/search@6.7.1", "https://registry.npmjs.com/@codemirror/search/-/search-6.7.1.tgz", { "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.37.0", "crelt": "^1.0.5" } }, "sha512-uMe5UO6PamJtSHrXhhHOzSX3ReWtiJrva6GnPMwSOrZtiExb5X5eExhr2OUZQVvdxPsKpY3Ro2mFbQadpPWmHA=="], "@codemirror/search": ["@codemirror/search@6.7.1", "https://registry.npmjs.com/@codemirror/search/-/search-6.7.1.tgz", { "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.37.0", "crelt": "^1.0.5" } }, "sha512-uMe5UO6PamJtSHrXhhHOzSX3ReWtiJrva6GnPMwSOrZtiExb5X5eExhr2OUZQVvdxPsKpY3Ro2mFbQadpPWmHA=="],
@@ -448,38 +418,20 @@
"@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.6", "https://registry.npmjs.com/@lezer/css/-/css-1.3.6.tgz", { "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.3.0" } }, "sha512-YJE78Wcg+zX8f10hiHWQ4Az48Qr/c13eId0VtRQYLBpxHDmDeSrXIlkbl+fJGW42rWC/uoUco9mhBZeVWP/A1g=="], "@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/go": ["@lezer/go@1.0.1", "https://registry.npmjs.com/@lezer/go/-/go-1.0.1.tgz", { "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.3.0" } }, "sha512-xToRsYxwsgJNHTgNdStpcvmbVuKxTapV0dM0wey1geMMRc9aggoVyKgzYp41D2/vVOx+Ii4hmE206kvxIXBVXQ=="],
"@lezer/highlight": ["@lezer/highlight@1.2.3", "https://registry.npmjs.com/@lezer/highlight/-/highlight-1.2.3.tgz", { "dependencies": { "@lezer/common": "^1.3.0" } }, "sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g=="], "@lezer/highlight": ["@lezer/highlight@1.2.3", "https://registry.npmjs.com/@lezer/highlight/-/highlight-1.2.3.tgz", { "dependencies": { "@lezer/common": "^1.3.0" } }, "sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g=="],
"@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/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/java": ["@lezer/java@1.1.3", "https://registry.npmjs.com/@lezer/java/-/java-1.1.3.tgz", { "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0" } }, "sha512-yHquUfujwg6Yu4Fd1GNHCvidIvJwi/1Xu2DaKl/pfWIA2c1oXkVvawH3NyXhCaFx4OdlYBVX5wvz2f7Aoa/4Xw=="], "@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/javascript": ["@lezer/javascript@1.5.4", "https://registry.npmjs.com/@lezer/javascript/-/javascript-1.5.4.tgz", { "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.1.3", "@lezer/lr": "^1.3.0" } }, "sha512-vvYx3MhWqeZtGPwDStM2dwgljd5smolYD2lR2UyFcHfxbBQebqx8yjmFmxtJ/E6nN6u1D9srOiVWm3Rb4tmcUA=="],
"@lezer/json": ["@lezer/json@1.0.3", "https://registry.npmjs.com/@lezer/json/-/json-1.0.3.tgz", { "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0" } }, "sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ=="],
"@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.7.2", "https://registry.npmjs.com/@lezer/markdown/-/markdown-1.7.2.tgz", { "dependencies": { "@lezer/common": "^1.5.0", "@lezer/highlight": "^1.0.0" } }, "sha512-iTkYvoVcKt3WkeL7qUDyXHONZEwLio4wj8KTNi2dnjQEXBZKMV63BpQrPqfsM+OkvuRbiSTAcycYAsQzLhRNoQ=="], "@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/php": ["@lezer/php@1.0.5", "https://registry.npmjs.com/@lezer/php/-/php-1.0.5.tgz", { "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.1.0" } }, "sha512-W7asp9DhM6q0W6DYNwIkLSKOvxlXRrif+UXBMxzsJUuqmhE7oVU+gS3THO4S/Puh7Xzgm858UNaFi6dxTP8dJA=="],
"@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=="],
"@lezer/rust": ["@lezer/rust@1.0.2", "https://registry.npmjs.com/@lezer/rust/-/rust-1.0.2.tgz", { "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0" } }, "sha512-Lz5sIPBdF2FUXcWeCu1//ojFAZqzTQNRga0aYv6dYXqJqPfMdCAI0NzajWUd4Xijj1IKJLtjoXRPMvTKWBcqKg=="],
"@lezer/sass": ["@lezer/sass@1.1.0", "https://registry.npmjs.com/@lezer/sass/-/sass-1.1.0.tgz", { "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0" } }, "sha512-3mMGdCTUZ/84ArHOuXWQr37pnf7f+Nw9ycPUeKX+wu19b7pSMcZGLbaXwvD2APMBDOGxPmpK/O6S1v1EvLoqgQ=="],
"@lezer/xml": ["@lezer/xml@1.0.6", "https://registry.npmjs.com/@lezer/xml/-/xml-1.0.6.tgz", { "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0" } }, "sha512-CdDwirL0OEaStFue/66ZmFSeppuL6Dwjlk8qk153mSQwiSH/Dlri4GNymrNWnUmPl2Um7QfV1FO9KFUyX3Twww=="],
"@lezer/yaml": ["@lezer/yaml@1.0.4", "https://registry.npmjs.com/@lezer/yaml/-/yaml-1.0.4.tgz", { "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.4.0" } }, "sha512-2lrrHqxalACEbxIbsjhqGpSW8kWpUKuY6RHgnSAFZa6qK62wvnPxA8hGOwOoDbwHcOFs5M4o27mjGu+P7TvBmw=="],
"@lucide/vue": ["@lucide/vue@1.29.0", "https://registry.npmjs.com/@lucide/vue/-/vue-1.29.0.tgz", { "peerDependencies": { "vue": ">=3.0.1" } }, "sha512-UnbPPAdxWGqABrjcQJZFqawSgZTBmeKOrNFPI9sqKaDkgLoEbYyx+ivIdiYRR1YoYhWWg7dCdvjtCwK6zBxWDQ=="],
"@marijn/find-cluster-break": ["@marijn/find-cluster-break@1.0.3", "https://registry.npmjs.com/@marijn/find-cluster-break/-/find-cluster-break-1.0.3.tgz", {}, "sha512-FY+MKLBoTsLNJF/eLWaOsXGdz6uh3Iu1axjPf6TUq92IYumcTcXWHoS747JARLkcdlJ/Waiaxc5wQfFO8jC6NA=="], "@marijn/find-cluster-break": ["@marijn/find-cluster-break@1.0.3", "https://registry.npmjs.com/@marijn/find-cluster-break/-/find-cluster-break-1.0.3.tgz", {}, "sha512-FY+MKLBoTsLNJF/eLWaOsXGdz6uh3Iu1axjPf6TUq92IYumcTcXWHoS747JARLkcdlJ/Waiaxc5wQfFO8jC6NA=="],
"@mermaid-js/parser": ["@mermaid-js/parser@1.2.1", "https://registry.npmjs.com/@mermaid-js/parser/-/parser-1.2.1.tgz", { "dependencies": { "@chevrotain/types": "~11.1.2" } }, "sha512-n12NohV3mrUyUL2o93IgG/ifeW9FTyeJn3zDxkhwa8MJ9Fxg3HQMlA3RiGmD/3UnJvheztkjjQAjA2T4LmUcpw=="], "@mermaid-js/parser": ["@mermaid-js/parser@1.2.1", "https://registry.npmjs.com/@mermaid-js/parser/-/parser-1.2.1.tgz", { "dependencies": { "@chevrotain/types": "~11.1.2" } }, "sha512-n12NohV3mrUyUL2o93IgG/ifeW9FTyeJn3zDxkhwa8MJ9Fxg3HQMlA3RiGmD/3UnJvheztkjjQAjA2T4LmUcpw=="],
@@ -748,15 +700,15 @@
"@types/jsesc": ["@types/jsesc@2.5.1", "https://registry.npmjs.com/@types/jsesc/-/jsesc-2.5.1.tgz", {}, "sha512-9VN+6yxLOPLOav+7PwjZbxiID2bVaeq0ED4qSQmdQTdjnXJSaCVKTR58t15oqH1H5t8Ng2ZX1SabJVoN9Q34bw=="], "@types/jsesc": ["@types/jsesc@2.5.1", "https://registry.npmjs.com/@types/jsesc/-/jsesc-2.5.1.tgz", {}, "sha512-9VN+6yxLOPLOav+7PwjZbxiID2bVaeq0ED4qSQmdQTdjnXJSaCVKTR58t15oqH1H5t8Ng2ZX1SabJVoN9Q34bw=="],
"@types/linkify-it": ["@types/linkify-it@5.0.0", "https://registry.npmjs.com/@types/linkify-it/-/linkify-it-5.0.0.tgz", {}, "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q=="], "@types/linkify-it": ["@types/linkify-it@5.0.0", "", {}, "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q=="],
"@types/lodash": ["@types/lodash@4.17.25", "https://registry.npmjs.com/@types/lodash/-/lodash-4.17.25.tgz", {}, "sha512-+K1NIO8I+F9/wNulfVvu23QYd0Pe9/OCqRrim4NoYIf1VoEDL90Ve4ClzpyqBLc7NpGGWRvYNCKZ1BE/Jpf8dQ=="], "@types/lodash": ["@types/lodash@4.17.25", "https://registry.npmjs.com/@types/lodash/-/lodash-4.17.25.tgz", {}, "sha512-+K1NIO8I+F9/wNulfVvu23QYd0Pe9/OCqRrim4NoYIf1VoEDL90Ve4ClzpyqBLc7NpGGWRvYNCKZ1BE/Jpf8dQ=="],
"@types/lodash-es": ["@types/lodash-es@4.17.12", "https://registry.npmjs.com/@types/lodash-es/-/lodash-es-4.17.12.tgz", { "dependencies": { "@types/lodash": "*" } }, "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ=="], "@types/lodash-es": ["@types/lodash-es@4.17.12", "https://registry.npmjs.com/@types/lodash-es/-/lodash-es-4.17.12.tgz", { "dependencies": { "@types/lodash": "*" } }, "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ=="],
"@types/markdown-it": ["@types/markdown-it@14.1.2", "https://registry.npmjs.com/@types/markdown-it/-/markdown-it-14.1.2.tgz", { "dependencies": { "@types/linkify-it": "^5", "@types/mdurl": "^2" } }, "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog=="], "@types/markdown-it": ["@types/markdown-it@14.2.0", "", { "dependencies": { "@types/linkify-it": "^5", "@types/mdurl": "^2" } }, "sha512-NoQ2yGlLWj4wpxMs+TYmRKk3thDrQ97agr7sFqfLsAlvoS8SNQuTrlObhFqG9iugdTtgOE9jpJ6FNM4ZGsa5xQ=="],
"@types/mdurl": ["@types/mdurl@2.0.0", "https://registry.npmjs.com/@types/mdurl/-/mdurl-2.0.0.tgz", {}, "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg=="], "@types/mdurl": ["@types/mdurl@2.0.0", "", {}, "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg=="],
"@types/node": ["@types/node@26.3.0", "https://registry.npmjs.com/@types/node/-/node-26.3.0.tgz", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-L3fgrnchriRC2ExBflb8j4uZZURHZfQsmQeyVzhjcHW4kkwVyo8/0h1B2MVzMTrYUJYu6G7EWs14hW/L9putqw=="], "@types/node": ["@types/node@26.3.0", "https://registry.npmjs.com/@types/node/-/node-26.3.0.tgz", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-L3fgrnchriRC2ExBflb8j4uZZURHZfQsmQeyVzhjcHW4kkwVyo8/0h1B2MVzMTrYUJYu6G7EWs14hW/L9putqw=="],
@@ -820,12 +772,6 @@
"@upsetjs/venn.js": ["@upsetjs/venn.js@2.0.0", "https://registry.npmjs.com/@upsetjs/venn.js/-/venn.js-2.0.0.tgz", { "optionalDependencies": { "d3-selection": "^3.0.0", "d3-transition": "^3.0.1" } }, "sha512-WbBhLrooyePuQ1VZxrJjtLvTc4NVfpOyKx0sKqioq9bX1C1m7Jgykkn8gLrtwumBioXIqam8DLxp88Adbue6Hw=="], "@upsetjs/venn.js": ["@upsetjs/venn.js@2.0.0", "https://registry.npmjs.com/@upsetjs/venn.js/-/venn.js-2.0.0.tgz", { "optionalDependencies": { "d3-selection": "^3.0.0", "d3-transition": "^3.0.1" } }, "sha512-WbBhLrooyePuQ1VZxrJjtLvTc4NVfpOyKx0sKqioq9bX1C1m7Jgykkn8gLrtwumBioXIqam8DLxp88Adbue6Hw=="],
"@vavt/copy2clipboard": ["@vavt/copy2clipboard@1.0.3", "https://registry.npmjs.com/@vavt/copy2clipboard/-/copy2clipboard-1.0.3.tgz", {}, "sha512-HtG48r2FBYp9eRvGB3QGmtRBH1zzRRAVvFbGgFstOwz4/DDaNiX0uZc3YVKPydqgOav26pibr9MtoCaWxn7aeA=="],
"@vavt/markdown-theme": ["@vavt/markdown-theme@5.0.2", "https://registry.npmjs.com/@vavt/markdown-theme/-/markdown-theme-5.0.2.tgz", {}, "sha512-cGYEV2VIUmhT9p8Wua9yXh7sKN1f3cbztTFHlkYyH9SzbpiKUnQrcbDts/0fP6cmvZPOe9SWWsDujmyuHepJdQ=="],
"@vavt/util": ["@vavt/util@2.1.2", "https://registry.npmjs.com/@vavt/util/-/util-2.1.2.tgz", {}, "sha512-L3UbSJthJwr3wq0x93O5TrCepimrmVZaIl2ciZbeL18G5++gBhJXNhcH7RcVk/6rr3SavWOvwhig0mqRLoR7dw=="],
"@vitejs/plugin-legacy": ["@vitejs/plugin-legacy@8.2.3", "https://registry.npmjs.com/@vitejs/plugin-legacy/-/plugin-legacy-8.2.3.tgz", { "dependencies": { "@babel/core": "^7.29.7", "@babel/plugin-transform-dynamic-import": "^7.29.7", "@babel/plugin-transform-modules-systemjs": "^7.29.8", "@babel/preset-env": "^7.29.7", "babel-plugin-polyfill-corejs3": "^0.14.2", "babel-plugin-polyfill-regenerator": "^0.6.8", "browserslist": "^4.28.7", "browserslist-to-esbuild": "^2.1.1", "core-js": "^3.49.0", "magic-string": "^1.1.0", "regenerator-runtime": "^0.14.1", "systemjs": "^6.15.1" }, "peerDependencies": { "terser": "^5.16.0", "vite": "^8.0.0" } }, "sha512-MMHLsn/0FrBkCQyb1x44cPYGwkfqcGr2FblcEP2ne79aXe7d5tFKoZ09xs5C4wuh8fOu2JRaNhgAS3K3uvUeJA=="], "@vitejs/plugin-legacy": ["@vitejs/plugin-legacy@8.2.3", "https://registry.npmjs.com/@vitejs/plugin-legacy/-/plugin-legacy-8.2.3.tgz", { "dependencies": { "@babel/core": "^7.29.7", "@babel/plugin-transform-dynamic-import": "^7.29.7", "@babel/plugin-transform-modules-systemjs": "^7.29.8", "@babel/preset-env": "^7.29.7", "babel-plugin-polyfill-corejs3": "^0.14.2", "babel-plugin-polyfill-regenerator": "^0.6.8", "browserslist": "^4.28.7", "browserslist-to-esbuild": "^2.1.1", "core-js": "^3.49.0", "magic-string": "^1.1.0", "regenerator-runtime": "^0.14.1", "systemjs": "^6.15.1" }, "peerDependencies": { "terser": "^5.16.0", "vite": "^8.0.0" } }, "sha512-MMHLsn/0FrBkCQyb1x44cPYGwkfqcGr2FblcEP2ne79aXe7d5tFKoZ09xs5C4wuh8fOu2JRaNhgAS3K3uvUeJA=="],
"@vitejs/plugin-vue": ["@vitejs/plugin-vue@6.0.8", "https://registry.npmjs.com/@vitejs/plugin-vue/-/plugin-vue-6.0.8.tgz", { "dependencies": { "@rolldown/pluginutils": "^1.0.1" }, "peerDependencies": { "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", "vue": "^3.2.25" } }, "sha512-0ZjgOg7oO6farnNGup7yvoM/YXZV84OZxHAwtflItNa/6zzQyVb5LNxyea3FEKEX2XlagIKzrlH7wwxkKgtiew=="], "@vitejs/plugin-vue": ["@vitejs/plugin-vue@6.0.8", "https://registry.npmjs.com/@vitejs/plugin-vue/-/plugin-vue-6.0.8.tgz", { "dependencies": { "@rolldown/pluginutils": "^1.0.1" }, "peerDependencies": { "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", "vue": "^3.2.25" } }, "sha512-0ZjgOg7oO6farnNGup7yvoM/YXZV84OZxHAwtflItNa/6zzQyVb5LNxyea3FEKEX2XlagIKzrlH7wwxkKgtiew=="],
@@ -1074,8 +1020,6 @@
"css-render": ["css-render@0.15.14", "https://registry.npmjs.com/css-render/-/css-render-0.15.14.tgz", { "dependencies": { "@emotion/hash": "~0.8.0", "csstype": "~3.0.5" } }, "sha512-9nF4PdUle+5ta4W5SyZdLCCmFd37uVimSjg1evcTqKJCyvCEEj12WKzOSBNak6r4im4J4iYXKH1OWpUV5LBYFg=="], "css-render": ["css-render@0.15.14", "https://registry.npmjs.com/css-render/-/css-render-0.15.14.tgz", { "dependencies": { "@emotion/hash": "~0.8.0", "csstype": "~3.0.5" } }, "sha512-9nF4PdUle+5ta4W5SyZdLCCmFd37uVimSjg1evcTqKJCyvCEEj12WKzOSBNak6r4im4J4iYXKH1OWpUV5LBYFg=="],
"cssfilter": ["cssfilter@0.0.10", "https://registry.npmjs.com/cssfilter/-/cssfilter-0.0.10.tgz", {}, "sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw=="],
"csstype": ["csstype@3.2.3", "https://registry.npmjs.com/csstype/-/csstype-3.2.3.tgz", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], "csstype": ["csstype@3.2.3", "https://registry.npmjs.com/csstype/-/csstype-3.2.3.tgz", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
"cytoscape": ["cytoscape@3.34.0", "https://registry.npmjs.com/cytoscape/-/cytoscape-3.34.0.tgz", {}, "sha512-62rNSrioXw93uliKFBwjukeQyeWwH2PqDrTac31r2P6464u3AUvTk0xS4LVvT251g7IgkFunrI48ZEZGjywSOg=="], "cytoscape": ["cytoscape@3.34.0", "https://registry.npmjs.com/cytoscape/-/cytoscape-3.34.0.tgz", {}, "sha512-62rNSrioXw93uliKFBwjukeQyeWwH2PqDrTac31r2P6464u3AUvTk0xS4LVvT251g7IgkFunrI48ZEZGjywSOg=="],
@@ -1360,24 +1304,14 @@
"magic-string-ast": ["magic-string-ast@1.0.3", "https://registry.npmjs.com/magic-string-ast/-/magic-string-ast-1.0.3.tgz", { "dependencies": { "magic-string": "^0.30.19" } }, "sha512-CvkkH1i81zl7mmb94DsRiFeG9V2fR2JeuK8yDgS8oiZSFa++wWLEgZ5ufEOyLHbvSbD1gTRKv9NdX69Rnvr9JA=="], "magic-string-ast": ["magic-string-ast@1.0.3", "https://registry.npmjs.com/magic-string-ast/-/magic-string-ast-1.0.3.tgz", { "dependencies": { "magic-string": "^0.30.19" } }, "sha512-CvkkH1i81zl7mmb94DsRiFeG9V2fR2JeuK8yDgS8oiZSFa++wWLEgZ5ufEOyLHbvSbD1gTRKv9NdX69Rnvr9JA=="],
"markdown-it": ["markdown-it@14.3.0", "https://registry.npmjs.com/markdown-it/-/markdown-it-14.3.0.tgz", { "dependencies": { "argparse": "^2.0.1", "entities": "^4.5.0", "linkify-it": "^5.0.2", "mdurl": "^2.0.0", "punycode.js": "^2.3.1", "uc.micro": "^2.1.0" }, "bin": { "markdown-it": "bin/markdown-it.mjs" } }, "sha512-RCEsPjR+sr0x+AuYp601tKTkgFG4YEPLCzHST3cQ/fhlJkqAkz1L2/Qbp1j9qw5SBwQHFBoW8+hoN5xssOF0Tw=="], "markdown-it": ["markdown-it@14.3.2", "https://registry.npmjs.com/markdown-it/-/markdown-it-14.3.2.tgz", { "dependencies": { "argparse": "^2.0.1", "entities": "^4.5.0", "linkify-it": "^5.0.2", "mdurl": "^2.0.0", "punycode.js": "^2.3.1", "uc.micro": "^2.1.0" }, "bin": { "markdown-it": "bin/markdown-it.mjs" } }, "sha512-sHHjZ5fJKlgrG4qns2YwVcdNep35h5fERrfkD2YNsb9UFk0UIHarbiTaHKVMlPuWAoiilyK8Fv/jAm11slsY7Q=="],
"markdown-it-image-figures": ["markdown-it-image-figures@2.1.1", "https://registry.npmjs.com/markdown-it-image-figures/-/markdown-it-image-figures-2.1.1.tgz", { "peerDependencies": { "markdown-it": "*" } }, "sha512-mwXSQ2nPeVUzCMIE3HlLvjRioopiqyJLNph0pyx38yf9mpqFDhNGnMpAXF9/A2Xv0oiF2cVyg9xwfF0HNAz05g=="],
"markdown-it-sub": ["markdown-it-sub@2.0.0", "https://registry.npmjs.com/markdown-it-sub/-/markdown-it-sub-2.0.0.tgz", {}, "sha512-iCBKgwCkfQBRg2vApy9vx1C1Tu6D8XYo8NvevI3OlwzBRmiMtsJ2sXupBgEA7PPxiDwNni3qIUkhZ6j5wofDUA=="],
"markdown-it-sup": ["markdown-it-sup@2.0.0", "https://registry.npmjs.com/markdown-it-sup/-/markdown-it-sup-2.0.0.tgz", {}, "sha512-5VgmdKlkBd8sgXuoDoxMpiU+BiEt3I49GItBzzw7Mxq9CxvnhE/k09HFli09zgfFDRixDQDfDxi0mgBCXtaTvA=="],
"marked": ["marked@16.4.2", "https://registry.npmjs.com/marked/-/marked-16.4.2.tgz", { "bin": { "marked": "bin/marked.js" } }, "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA=="], "marked": ["marked@16.4.2", "https://registry.npmjs.com/marked/-/marked-16.4.2.tgz", { "bin": { "marked": "bin/marked.js" } }, "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA=="],
"math-intrinsics": ["math-intrinsics@1.1.0", "https://registry.npmjs.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], "math-intrinsics": ["math-intrinsics@1.1.0", "https://registry.npmjs.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
"md-editor-v3": ["md-editor-v3@6.5.6", "https://registry.npmjs.com/md-editor-v3/-/md-editor-v3-6.5.6.tgz", { "dependencies": { "@codemirror/autocomplete": "^6.18.7", "@codemirror/commands": "^6.8.1", "@codemirror/lang-markdown": "^6.3.4", "@codemirror/language": "^6.11.3", "@codemirror/language-data": "^6.5.1", "@codemirror/search": "^6.5.11", "@codemirror/state": "^6.5.2", "@codemirror/view": "^6.38.2", "@lezer/highlight": "^1.2.1", "@lucide/vue": "^1.16.0", "@types/markdown-it": "^14.0.1", "@vavt/copy2clipboard": "^1.0.1", "@vavt/markdown-theme": "^5.0.2", "@vavt/util": "^2.1.2", "codemirror": "^6.0.2", "markdown-it": "^14.0.0", "markdown-it-image-figures": "^2.1.1", "markdown-it-sub": "^2.0.0", "markdown-it-sup": "^2.0.0", "medium-zoom": "^1.1.0", "xss": "^1.0.15" }, "peerDependencies": { "vue": "^3.5.3" } }, "sha512-bD+xKTpaC9mGDE7W+9x25Y5mEsv21Y735J2Q0dxV+lWQTXH21/sKNdwaUYQ5dhXU2fl+oqrOJsEjSd58FLyNSA=="],
"mdurl": ["mdurl@2.1.0", "https://registry.npmjs.com/mdurl/-/mdurl-2.1.0.tgz", {}, "sha512-1+HBaOx0zi/dQWht8rNv9MYf9qqpqL/kxI0hXImU6Y547zM6Sni8BQibt7ifgMcYtQg41ao3Ivd6cnSM86inpg=="], "mdurl": ["mdurl@2.1.0", "https://registry.npmjs.com/mdurl/-/mdurl-2.1.0.tgz", {}, "sha512-1+HBaOx0zi/dQWht8rNv9MYf9qqpqL/kxI0hXImU6Y547zM6Sni8BQibt7ifgMcYtQg41ao3Ivd6cnSM86inpg=="],
"medium-zoom": ["medium-zoom@1.1.0", "https://registry.npmjs.com/medium-zoom/-/medium-zoom-1.1.0.tgz", {}, "sha512-ewyDsp7k4InCUp3jRmwHBRFGyjBimKps/AJLjRSox+2q/2H4p/PNpQf+pwONWlJiOudkBXtbdmVbFjqyybfTmQ=="],
"meow": ["meow@13.2.0", "https://registry.npmjs.com/meow/-/meow-13.2.0.tgz", {}, "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA=="], "meow": ["meow@13.2.0", "https://registry.npmjs.com/meow/-/meow-13.2.0.tgz", {}, "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA=="],
"mermaid": ["mermaid@11.17.2", "https://registry.npmjs.com/mermaid/-/mermaid-11.17.2.tgz", { "dependencies": { "@braintree/sanitize-url": "^7.1.2", "@iconify/utils": "^3.0.2", "@mermaid-js/parser": "^1.2.1", "@types/d3": "^7.4.3", "@upsetjs/venn.js": "^2.0.0", "cytoscape": "^3.34.0", "cytoscape-cose-bilkent": "^4.1.0", "cytoscape-fcose": "^2.2.0", "d3": "^7.9.0", "d3-sankey": "^0.12.3", "dagre-d3-es": "7.0.14", "dayjs": "^1.11.21", "dompurify": "^3.3.3", "es-toolkit": "^1.45.1", "fastdom": "1.0.12", "katex": "^0.16.47", "khroma": "^2.1.0", "marked": "^16.3.0", "roughjs": "^4.6.6", "stylis": "^4.3.6", "ts-dedent": "^2.2.0", "uuid": "^11.1.0 || ^12 || ^13 || ^14.0.0" } }, "sha512-V6K3C8EBdEsPFZXSKMJe6ppQOENxuHARr9GvHX4hh47lAbhMRD9qf4oEK7LoaRQxULMa80/qt5gHO73aCleBBg=="], "mermaid": ["mermaid@11.17.2", "https://registry.npmjs.com/mermaid/-/mermaid-11.17.2.tgz", { "dependencies": { "@braintree/sanitize-url": "^7.1.2", "@iconify/utils": "^3.0.2", "@mermaid-js/parser": "^1.2.1", "@types/d3": "^7.4.3", "@upsetjs/venn.js": "^2.0.0", "cytoscape": "^3.34.0", "cytoscape-cose-bilkent": "^4.1.0", "cytoscape-fcose": "^2.2.0", "d3": "^7.9.0", "d3-sankey": "^0.12.3", "dagre-d3-es": "7.0.14", "dayjs": "^1.11.21", "dompurify": "^3.3.3", "es-toolkit": "^1.45.1", "fastdom": "1.0.12", "katex": "^0.16.47", "khroma": "^2.1.0", "marked": "^16.3.0", "roughjs": "^4.6.6", "stylis": "^4.3.6", "ts-dedent": "^2.2.0", "uuid": "^11.1.0 || ^12 || ^13 || ^14.0.0" } }, "sha512-V6K3C8EBdEsPFZXSKMJe6ppQOENxuHARr9GvHX4hh47lAbhMRD9qf4oEK7LoaRQxULMa80/qt5gHO73aCleBBg=="],
@@ -1654,8 +1588,6 @@
"ws": ["ws@8.22.0", "https://registry.npmjs.com/ws/-/ws-8.22.0.tgz", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-Ydggc987+RO0AnWtZ/7Wq9FtNvcrL1b/RO0ud9mWjUPgDrsAAwQSF51sm2hm1XofbU/4jkpGEsLFsZZxU+1DOg=="], "ws": ["ws@8.22.0", "https://registry.npmjs.com/ws/-/ws-8.22.0.tgz", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-Ydggc987+RO0AnWtZ/7Wq9FtNvcrL1b/RO0ud9mWjUPgDrsAAwQSF51sm2hm1XofbU/4jkpGEsLFsZZxU+1DOg=="],
"xss": ["xss@1.0.15", "https://registry.npmjs.com/xss/-/xss-1.0.15.tgz", { "dependencies": { "commander": "^2.20.3", "cssfilter": "0.0.10" }, "bin": { "xss": "bin/xss" } }, "sha512-FVdlVVC67WOIPvfOwhoMETV72f6GbW7aOabBC3WxN/oUdoEMDyLz4OgRv5/gck2ZeNqEQu+Tb0kloovXOfpYVg=="],
"y-codemirror.next": ["y-codemirror.next@0.3.6", "https://registry.npmjs.com/y-codemirror.next/-/y-codemirror.next-0.3.6.tgz", { "dependencies": { "lib0": "^0.2.42" }, "peerDependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", "yjs": "^13.5.6" } }, "sha512-GnmVXhTe+UtoFbbaSdwhq6gdAQZdIY9az0Xj6HR2J4PO6Yw4w3xaaSssU+6T72WhXAI0wf9FbuY2s0Ms+WrexA=="], "y-codemirror.next": ["y-codemirror.next@0.3.6", "https://registry.npmjs.com/y-codemirror.next/-/y-codemirror.next-0.3.6.tgz", { "dependencies": { "lib0": "^0.2.42" }, "peerDependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", "yjs": "^13.5.6" } }, "sha512-GnmVXhTe+UtoFbbaSdwhq6gdAQZdIY9az0Xj6HR2J4PO6Yw4w3xaaSssU+6T72WhXAI0wf9FbuY2s0Ms+WrexA=="],
"y-protocols": ["y-protocols@1.0.7", "https://registry.npmjs.com/y-protocols/-/y-protocols-1.0.7.tgz", { "dependencies": { "lib0": "^0.2.85" }, "peerDependencies": { "yjs": "^13.0.0" } }, "sha512-YSVsLoXxO67J6eE/nV4AtFtT3QEotZf5sK5BHxFBXso7VDUT3Tx07IfA6hsu5Q5OmBdMkQVmFZ9QOA7fikWvnw=="], "y-protocols": ["y-protocols@1.0.7", "https://registry.npmjs.com/y-protocols/-/y-protocols-1.0.7.tgz", { "dependencies": { "lib0": "^0.2.85" }, "peerDependencies": { "yjs": "^13.0.0" } }, "sha512-YSVsLoXxO67J6eE/nV4AtFtT3QEotZf5sK5BHxFBXso7VDUT3Tx07IfA6hsu5Q5OmBdMkQVmFZ9QOA7fikWvnw=="],