diff --git a/apps/client/package.json b/apps/client/package.json index 6d78075d8..f3f6213df 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -5,6 +5,10 @@ "type": "module", "dependencies": { "@base-ui/react": "1.0.0", + "@codemirror/commands": "^6.0.0", + "@codemirror/lang-css": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", "@dnd-kit/core": "^6.3.1", "@dnd-kit/sortable": "^10.0.0", "@dnd-kit/utilities": "^3.2.2", @@ -15,10 +19,10 @@ "@tanstack/react-query": "^5.85.9", "@tanstack/react-query-devtools": "^5.85.9", "@tanstack/react-table": "^8.21.3", + "@uiw/codemirror-theme-vscode": "^4.25.9", "autosize": "^6.0.1", "axios": "^1.12.2", "csv-stringify": "^6.6.0", - "prismjs": "^1.30.0", "qrcode": "^1.5.4", "react": "^19.2.3", "react-colorful": "^5.6.1", @@ -27,7 +31,6 @@ "react-hook-form": "^7.62.0", "react-icons": "5.5.0", "react-router": "^7.11.0", - "react-simple-code-editor": "^0.14.1", "react-virtuoso": "^4.17.0", "web-vitals": "^5.1.0", "zustand": "^5.0.9" @@ -58,7 +61,6 @@ }, "devDependencies": { "@sentry/vite-plugin": "5.1.1", - "@types/prismjs": "^1.26.6", "@types/qrcode": "^1.5.6", "@types/react": "^19.1.12", "@types/react-dom": "^19.1.9", @@ -70,7 +72,6 @@ "typescript": "catalog:", "vite": "8.0.1", "vite-plugin-compression2": "2.5.1", - "vite-plugin-prismjs-plus": "1.1.1", "vite-plugin-svgr": "4.5.0", "vite-tsconfig-paths": "6.1.1", "vitest": "catalog:" diff --git a/apps/client/src/declarations/virtual-prismjs.d.ts b/apps/client/src/declarations/virtual-prismjs.d.ts deleted file mode 100644 index d72bd0088..000000000 --- a/apps/client/src/declarations/virtual-prismjs.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module 'virtual:prismjs' { - const prism: typeof import('prismjs'); - export default prism; -} diff --git a/apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditor.module.scss b/apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditor.module.scss index 29c11e012..0b9f3e378 100644 --- a/apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditor.module.scss +++ b/apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditor.module.scss @@ -1,5 +1,13 @@ -.wrapper { - min-height: 500px; - max-height: 500px; - overflow-y: auto; +.editor { + width: 100%; + height: 100%; + + :global(.cm-editor) { + height: 100%; + } + + :global(.cm-scroller) { + height: 100%; + overflow: auto; + } } diff --git a/apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditor.tsx b/apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditor.tsx index 5f6096c42..ec3dda9d9 100644 --- a/apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditor.tsx +++ b/apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditor.tsx @@ -1,38 +1,86 @@ -import { memo } from 'react'; -import Editor from 'react-simple-code-editor'; - -import 'prismjs/themes/prism-tomorrow.min.css'; -import Prism from 'virtual:prismjs'; +import { defaultKeymap, indentWithTab } from '@codemirror/commands'; +import { css } from '@codemirror/lang-css'; +import { Annotation, EditorState } from '@codemirror/state'; +import { EditorView, keymap } from '@codemirror/view'; +import { vscodeDark } from '@uiw/codemirror-theme-vscode'; +import { memo, useEffect, useRef } from 'react'; import style from './StyleEditor.module.scss'; -interface CodeEditorProps { - language: string; +interface StyleEditorProps { value: string; onChange: (value: string) => void; } -export default memo(CodeEditor); -function CodeEditor({ language, onChange, value }: CodeEditorProps) { - const highlight = (code: string) => { - const grammar = Prism.languages[language]; - return grammar ? Prism.highlight(code, grammar, language) : code; - }; +const editorExtensions = [keymap.of([indentWithTab, ...defaultKeymap]), css(), vscodeDark]; +const externalValueSync = Annotation.define(); - return ( -
- -
- ); +export default memo(StyleEditor); +function StyleEditor({ onChange, value }: StyleEditorProps) { + const hostRef = useRef(null); + const viewRef = useRef(null); + const onChangeRef = useRef(onChange); + + // Keep the latest callback available to the editor listener without recreating the editor instance. + useEffect(() => { + onChangeRef.current = onChange; + }, [onChange]); + + // Create the CodeMirror editor once and wire document changes back to React state. + useEffect(() => { + if (viewRef.current) { + return; + } + + const parent = hostRef.current; + if (!parent) { + return; + } + + const updateListener = EditorView.updateListener.of((update) => { + if (!update.docChanged) { + return; + } + if (update.transactions.some((transaction) => transaction.annotation(externalValueSync))) { + return; + } + onChangeRef.current(update.state.doc.toString()); + }); + + const state = EditorState.create({ + doc: value, + extensions: [...editorExtensions, updateListener], + }); + + const view = new EditorView({ state, parent }); + viewRef.current = view; + + return () => { + view.destroy(); + viewRef.current = null; + }; + }, []); + + // Apply external value updates to the editor when they differ from the current document. + useEffect(() => { + const view = viewRef.current; + if (!view) { + return; + } + + const currentValue = view.state.doc.toString(); + if (currentValue === value) { + return; + } + if (view.hasFocus) { + return; + } + + view.dispatch({ + changes: { from: 0, to: view.state.doc.length, insert: value }, + annotations: externalValueSync.of(true), + }); + }, [value]); + + return
; } diff --git a/apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditorModal.module.scss b/apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditorModal.module.scss index 4418f2a34..874df30d4 100644 --- a/apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditorModal.module.scss +++ b/apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditorModal.module.scss @@ -16,7 +16,7 @@ .editorBody { position: relative; - min-height: 500px; + height: 500px; background-color: $gray-1350; border: 1px solid $gray-1100; border-radius: 3px; diff --git a/apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditorModal.tsx b/apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditorModal.tsx index 58023911f..76a53e6ae 100644 --- a/apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditorModal.tsx +++ b/apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditorModal.tsx @@ -51,11 +51,11 @@ export default function CodeEditorModal({ isOpen, onClose }: CodeEditorModalProp const clear = () => setDraftCss(''); + // Load the latest CSS from the server whenever the modal opens, and ignore stale responses on close. useEffect(() => { let isCancelled = false; async function fetchServerCSS() { - // check for isOpen to fetch recent css if (isOpen) { try { setError(null); @@ -97,11 +97,9 @@ export default function CodeEditorModal({ isOpen, onClose }: CodeEditorModalProp showBackdrop bodyElements={
- {!isLoadingCss && ( - }> - - - )} + }> + +
} diff --git a/apps/client/tsconfig.app.json b/apps/client/tsconfig.app.json index 31e2bef00..1e137b539 100644 --- a/apps/client/tsconfig.app.json +++ b/apps/client/tsconfig.app.json @@ -10,7 +10,6 @@ "types": [ "vite/client", "vite-plugin-svgr/client", - "vite-plugin-prismjs-plus/client", ], "module": "esnext", "moduleResolution": "bundler", diff --git a/apps/client/vite.config.js b/apps/client/vite.config.js index cafeeeacd..b74040684 100644 --- a/apps/client/vite.config.js +++ b/apps/client/vite.config.js @@ -4,7 +4,6 @@ import { sentryVitePlugin } from '@sentry/vite-plugin'; import react from '@vitejs/plugin-react'; import { defineConfig } from 'vite'; import { compression } from 'vite-plugin-compression2'; -import prismjsPlugin from 'vite-plugin-prismjs-plus'; import svgrPlugin from 'vite-plugin-svgr'; import { ONTIME_VERSION } from './src/ONTIME_VERSION'; @@ -17,11 +16,6 @@ const ReactCompilerConfig = { export default defineConfig({ base: './', // Ontime cloud: we use relative paths to allow them to reference a dynamic base set at runtime - legacy: { - // Temporary compatibility for CJS packages affected by Vite 8 interop changes. - // ie: react-simple-code-editor - inconsistentCjsInterop: true, - }, define: { // we pass along the NODE_ENV here in case it is a docker build 'import.meta.env.IS_DOCKER': process.env.NODE_ENV === 'docker', @@ -54,11 +48,6 @@ export default defineConfig({ algorithm: 'brotliCompress', exclude: /\.(html)$/, // Ontime cloud: Exclude HTML files from compression so we can change the base property at runtime }), - prismjsPlugin({ - manual: true, - languages: ['css'], - css: true, - }), ], server: { port: 3000, diff --git a/apps/server/src/models/demoProject.ts b/apps/server/src/models/demoProject.ts index bff7a6857..05f90bf71 100644 --- a/apps/server/src/models/demoProject.ts +++ b/apps/server/src/models/demoProject.ts @@ -1,4 +1,5 @@ import { DatabaseModel, OntimeView } from 'ontime-types'; + import { backstageRundown, broadcastRundown, stageRundown } from './demoRundowns.js'; export const demoDb: DatabaseModel = { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ae9890730..6d72360a7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -61,6 +61,18 @@ importers: '@base-ui/react': specifier: 1.0.0 version: 1.0.0(@types/react@19.1.12)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@codemirror/commands': + specifier: ^6.0.0 + version: 6.10.3 + '@codemirror/lang-css': + specifier: ^6.0.0 + version: 6.3.1 + '@codemirror/state': + specifier: ^6.0.0 + version: 6.6.0 + '@codemirror/view': + specifier: ^6.0.0 + version: 6.40.0 '@dnd-kit/core': specifier: ^6.3.1 version: 6.3.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -91,6 +103,9 @@ importers: '@tanstack/react-table': specifier: ^8.21.3 version: 8.21.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@uiw/codemirror-theme-vscode': + specifier: ^4.25.9 + version: 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0) autosize: specifier: ^6.0.1 version: 6.0.1 @@ -100,9 +115,6 @@ importers: csv-stringify: specifier: ^6.6.0 version: 6.6.0 - prismjs: - specifier: ^1.30.0 - version: 1.30.0 qrcode: specifier: ^1.5.4 version: 1.5.4 @@ -127,9 +139,6 @@ importers: react-router: specifier: ^7.11.0 version: 7.11.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - react-simple-code-editor: - specifier: ^0.14.1 - version: 0.14.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3) react-virtuoso: specifier: ^4.17.0 version: 4.17.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -143,9 +152,6 @@ importers: '@sentry/vite-plugin': specifier: 5.1.1 version: 5.1.1(encoding@0.1.13)(rollup@4.59.0) - '@types/prismjs': - specifier: ^1.26.6 - version: 1.26.6 '@types/qrcode': specifier: ^1.5.6 version: 1.5.6 @@ -179,9 +185,6 @@ importers: vite-plugin-compression2: specifier: 2.5.1 version: 2.5.1(rollup@4.59.0) - vite-plugin-prismjs-plus: - specifier: 1.1.1 - version: 1.1.1(prismjs@1.30.0)(vite@8.0.1(@types/node@25.4.0)(esbuild@0.27.4)(jiti@2.6.1)(sass@1.92.0)(tsx@4.20.5)) vite-plugin-svgr: specifier: 4.5.0 version: 4.5.0(rollup@4.59.0)(typescript@6.0.0-beta)(vite@8.0.1(@types/node@25.4.0)(esbuild@0.27.4)(jiti@2.6.1)(sass@1.92.0)(tsx@4.20.5)) @@ -522,6 +525,24 @@ packages: '@types/react': optional: true + '@codemirror/autocomplete@6.20.1': + resolution: {integrity: sha512-1cvg3Vz1dSSToCNlJfRA2WSI4ht3K+WplO0UMOgmUYPivCyy2oueZY6Lx7M9wThm7SDUBViRmuT+OG/i8+ON9A==} + + '@codemirror/commands@6.10.3': + resolution: {integrity: sha512-JFRiqhKu+bvSkDLI+rUhJwSxQxYb759W5GBezE8Uc8mHLqC9aV/9aTC7yJSqCtB3F00pylrLCwnyS91Ap5ej4Q==} + + '@codemirror/lang-css@6.3.1': + resolution: {integrity: sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==} + + '@codemirror/language@6.12.3': + resolution: {integrity: sha512-QwCZW6Tt1siP37Jet9Tb02Zs81TQt6qQrZR2H+eGMcFsL1zMrk2/b9CLC7/9ieP1fjIUMgviLWMmgiHoJrj+ZA==} + + '@codemirror/state@6.6.0': + resolution: {integrity: sha512-4nbvra5R5EtiCzr9BTHiTLc+MLXK2QGiAVYMyi8PkQd3SR+6ixar/Q/01Fa21TBIDOZXgeWV4WppsQolSreAPQ==} + + '@codemirror/view@6.40.0': + resolution: {integrity: sha512-WA0zdU7xfF10+5I3HhUUq3kqOx3KjqmtQ9lqZjfK7jtYk4G72YW9rezcSywpaUMCWOMlq+6E0pO1IWg1TNIhtg==} + '@develar/schema-utils@2.6.5': resolution: {integrity: sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==} engines: {node: '>= 8.9.0'} @@ -1122,6 +1143,18 @@ packages: '@jridgewell/trace-mapping@0.3.30': resolution: {integrity: sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==} + '@lezer/common@1.5.1': + resolution: {integrity: sha512-6YRVG9vBkaY7p1IVxL4s44n5nUnaNnGM2/AckNgYOnxTG2kWh1vR8BMxPseWPjRNpb5VtXnMpeYAEAADoRV1Iw==} + + '@lezer/css@1.3.3': + resolution: {integrity: sha512-RzBo8r+/6QJeow7aPHIpGVIH59xTcJXp399820gZoMo9noQDRVpJLheIBUicYwKcsbOYoBRoLZlf2720dG/4Tg==} + + '@lezer/highlight@1.2.3': + resolution: {integrity: sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==} + + '@lezer/lr@1.4.8': + resolution: {integrity: sha512-bPWa0Pgx69ylNlMlPvBPryqeLYQjyJjqPx+Aupm5zydLIF3NE+6MMLT8Yi23Bd9cif9VS00aUebn+6fDIGBcDA==} + '@malept/cross-spawn-promise@1.1.1': resolution: {integrity: sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==} engines: {node: '>= 10'} @@ -1139,6 +1172,9 @@ packages: peerDependencies: react: ^18.x || ^19.x + '@marijn/find-cluster-break@1.0.2': + resolution: {integrity: sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==} + '@napi-rs/wasm-runtime@1.1.1': resolution: {integrity: sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==} @@ -2156,9 +2192,6 @@ packages: '@types/plist@3.0.5': resolution: {integrity: sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==} - '@types/prismjs@1.26.6': - resolution: {integrity: sha512-vqlvI7qlMvcCBbVe0AKAb4f97//Hy0EBTaiW8AalRnG/xAN5zOiWWyrNqNXeq8+KAuvRewjCVY1+IPxk4RdNYw==} - '@types/qrcode@1.5.6': resolution: {integrity: sha512-te7NQcV2BOvdj2b1hCAHzAoMNuj65kNBMz0KBaxM6c3VGBOhU0dURQKOtH8CFNI/dsKkwlv32p26qYQTWoB5bw==} @@ -2197,6 +2230,16 @@ packages: '@types/yauzl@2.10.3': resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} + '@uiw/codemirror-theme-vscode@4.25.9': + resolution: {integrity: sha512-9KTnScHTSk97yGnyNYvDm6QZuBCdbO1OzMQ5bHtoBSPSVtH0LjY3bS6CXsBagb22v8OLPx/XwrBYOjKFp409CQ==} + + '@uiw/codemirror-themes@4.25.9': + resolution: {integrity: sha512-DAHKb/L9ELwjY4nCf/MP/mIllHOn4GQe7RR4x8AMJuNeh9nGRRoo1uPxrxMmUL/bKqe6kDmDbIZ2AlhlqyIJuw==} + peerDependencies: + '@codemirror/language': '>=6.0.0' + '@codemirror/state': '>=6.0.0' + '@codemirror/view': '>=6.0.0' + '@vitejs/plugin-react@5.2.0': resolution: {integrity: sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2689,6 +2732,9 @@ packages: crc@3.8.0: resolution: {integrity: sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==} + crelt@1.0.6: + resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==} + cross-env@7.0.3: resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==} engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} @@ -4073,10 +4119,6 @@ packages: resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==} engines: {node: ^10 || ^12 || >=14} - prismjs@1.30.0: - resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==} - engines: {node: '>=6'} - proc-log@2.0.1: resolution: {integrity: sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} @@ -4187,12 +4229,6 @@ packages: react-dom: optional: true - react-simple-code-editor@0.14.1: - resolution: {integrity: sha512-BR5DtNRy+AswWJECyA17qhUDvrrCZ6zXOCfkQY5zSmb96BVUbpVAv03WpcjcwtCwiLbIANx3gebHOcXYn1EHow==} - peerDependencies: - react: '>=16.8.0' - react-dom: '>=16.8.0' - react-virtuoso@4.17.0: resolution: {integrity: sha512-od3pi2v13v31uzn5zPXC2u3ouISFCVhjFVFch2VvS2Cx7pWA2F1aJa3XhNTN2F07M3lhfnMnsmGeH+7wZICr7w==} peerDependencies: @@ -4523,6 +4559,9 @@ packages: resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} engines: {node: '>=12'} + style-mod@4.1.3: + resolution: {integrity: sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==} + sucrase@3.35.0: resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} engines: {node: '>=16 || 14 >=14.17'} @@ -4821,12 +4860,6 @@ packages: vite-plugin-compression2@2.5.1: resolution: {integrity: sha512-2YpLZWs1ZRo9XwtSFA6/NVuBgOR+kvFk8M0HNDsP7Wu7OfJDOKT6fHB8kzuvw6jhgC9KYgDOttfaG2qC0wE9AQ==} - vite-plugin-prismjs-plus@1.1.1: - resolution: {integrity: sha512-RFmWuC3KiyXWe/Si3K2B2DOSITqUwVUtaSPoq+ss/7uo5tIdSi9lmrLjHlPe3G8AJCqhgTtKcPzM2HXUhwZ00A==} - peerDependencies: - prismjs: ^1.29.0 - vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 - vite-plugin-svgr@4.5.0: resolution: {integrity: sha512-W+uoSpmVkSmNOGPSsDCWVW/DDAyv+9fap9AZXBvWiQqrboJ08j2vh0tFxTD/LjwqwAd3yYSVJgm54S/1GhbdnA==} peerDependencies: @@ -4954,6 +4987,9 @@ packages: jsdom: optional: true + w3c-keyname@2.2.8: + resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==} + w3c-xmlserializer@4.0.0: resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} engines: {node: '>=14'} @@ -5379,6 +5415,48 @@ snapshots: optionalDependencies: '@types/react': 19.1.12 + '@codemirror/autocomplete@6.20.1': + dependencies: + '@codemirror/language': 6.12.3 + '@codemirror/state': 6.6.0 + '@codemirror/view': 6.40.0 + '@lezer/common': 1.5.1 + + '@codemirror/commands@6.10.3': + dependencies: + '@codemirror/language': 6.12.3 + '@codemirror/state': 6.6.0 + '@codemirror/view': 6.40.0 + '@lezer/common': 1.5.1 + + '@codemirror/lang-css@6.3.1': + dependencies: + '@codemirror/autocomplete': 6.20.1 + '@codemirror/language': 6.12.3 + '@codemirror/state': 6.6.0 + '@lezer/common': 1.5.1 + '@lezer/css': 1.3.3 + + '@codemirror/language@6.12.3': + dependencies: + '@codemirror/state': 6.6.0 + '@codemirror/view': 6.40.0 + '@lezer/common': 1.5.1 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.8 + style-mod: 4.1.3 + + '@codemirror/state@6.6.0': + dependencies: + '@marijn/find-cluster-break': 1.0.2 + + '@codemirror/view@6.40.0': + dependencies: + '@codemirror/state': 6.6.0 + crelt: 1.0.6 + style-mod: 4.1.3 + w3c-keyname: 2.2.8 + '@develar/schema-utils@2.6.5': dependencies: ajv: 6.14.0 @@ -5845,6 +5923,22 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@lezer/common@1.5.1': {} + + '@lezer/css@1.3.3': + dependencies: + '@lezer/common': 1.5.1 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.8 + + '@lezer/highlight@1.2.3': + dependencies: + '@lezer/common': 1.5.1 + + '@lezer/lr@1.4.8': + dependencies: + '@lezer/common': 1.5.1 + '@malept/cross-spawn-promise@1.1.1': dependencies: cross-spawn: 7.0.6 @@ -5866,6 +5960,8 @@ snapshots: dependencies: react: 19.2.3 + '@marijn/find-cluster-break@1.0.2': {} + '@napi-rs/wasm-runtime@1.1.1': dependencies: '@emnapi/core': 1.9.1 @@ -6629,8 +6725,6 @@ snapshots: xmlbuilder: 15.1.1 optional: true - '@types/prismjs@1.26.6': {} - '@types/qrcode@1.5.6': dependencies: '@types/node': 25.4.0 @@ -6677,6 +6771,20 @@ snapshots: '@types/node': 22.15.26 optional: true + '@uiw/codemirror-theme-vscode@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)': + dependencies: + '@uiw/codemirror-themes': 4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0) + transitivePeerDependencies: + - '@codemirror/language' + - '@codemirror/state' + - '@codemirror/view' + + '@uiw/codemirror-themes@4.25.9(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)': + dependencies: + '@codemirror/language': 6.12.3 + '@codemirror/state': 6.6.0 + '@codemirror/view': 6.40.0 + '@vitejs/plugin-react@5.2.0(vite@8.0.1(@types/node@25.4.0)(esbuild@0.27.4)(jiti@2.6.1)(sass@1.92.0)(tsx@4.20.5))': dependencies: '@babel/core': 7.29.0 @@ -7314,6 +7422,8 @@ snapshots: buffer: 5.7.1 optional: true + crelt@1.0.6: {} + cross-env@7.0.3: dependencies: cross-spawn: 7.0.3 @@ -8887,8 +8997,6 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 - prismjs@1.30.0: {} - proc-log@2.0.1: {} process-nextick-args@2.0.1: {} @@ -8981,11 +9089,6 @@ snapshots: optionalDependencies: react-dom: 19.2.3(react@19.2.3) - react-simple-code-editor@0.14.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3): - dependencies: - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - react-virtuoso@4.17.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3): dependencies: react: 19.2.3 @@ -9409,6 +9512,8 @@ snapshots: dependencies: ansi-regex: 6.2.0 + style-mod@4.1.3: {} + sucrase@3.35.0: dependencies: '@jridgewell/gen-mapping': 0.3.13 @@ -9695,11 +9800,6 @@ snapshots: transitivePeerDependencies: - rollup - vite-plugin-prismjs-plus@1.1.1(prismjs@1.30.0)(vite@8.0.1(@types/node@25.4.0)(esbuild@0.27.4)(jiti@2.6.1)(sass@1.92.0)(tsx@4.20.5)): - dependencies: - prismjs: 1.30.0 - vite: 8.0.1(@types/node@25.4.0)(esbuild@0.27.4)(jiti@2.6.1)(sass@1.92.0)(tsx@4.20.5) - vite-plugin-svgr@4.5.0(rollup@4.59.0)(typescript@6.0.0-beta)(vite@8.0.1(@types/node@25.4.0)(esbuild@0.27.4)(jiti@2.6.1)(sass@1.92.0)(tsx@4.20.5)): dependencies: '@rollup/pluginutils': 5.3.0(rollup@4.59.0) @@ -9846,6 +9946,8 @@ snapshots: - tsx - yaml + w3c-keyname@2.2.8: {} + w3c-xmlserializer@4.0.0: dependencies: xml-name-validator: 4.0.0