// Configuration Monaco isolée dans son propre module, chargé UNIQUEMENT en import dynamique // (cf. composables/useMonaco) → chunk séparé, zéro impact sur le bundle initial. // Workers via Vite (?worker) : on ne fournit que le worker de base. La colorisation syntaxique // (Monarch) tourne sur le thread principal et ne dépend d'aucun worker ; les services de langage // avancés (TS/JSON) dégradent proprement : suffisant pour éditer + sauver dans le navigateur. import * as monaco from 'monaco-editor'; import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'; import TsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'; import JsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'; import CssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker'; import HtmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'; import type { ResolvedTheme } from './theme'; // Un worker par famille de langage. Ne fournir que le worker de base ne « dégradait » PAS // proprement : dès qu'on ouvrait un .ts, le service TypeScript appelait un worker qui ne connaissait // pas ses méthodes, et chaque ouverture jetait un rejet non géré dans la console (getSyntacticDiagnostics, // provideInlayHints, ...). Ces workers sont des chunks séparés, téléchargés seulement quand un fichier // du langage correspondant est ouvert. (self as unknown as { MonacoEnvironment: monaco.Environment }).MonacoEnvironment = { getWorker: (_id: string, label: string) => { if (label === 'typescript' || label === 'javascript') return new TsWorker(); if (label === 'json') return new JsonWorker(); if (label === 'css' || label === 'scss' || label === 'less') return new CssWorker(); if (label === 'html' || label === 'handlebars' || label === 'razor') return new HtmlWorker(); return new EditorWorker(); }, }; // Les diagnostics SÉMANTIQUES restent coupés, workers ou pas : le worker ne voit qu'un fichier isolé, // sans tsconfig ni node_modules, donc il signalerait des dizaines de fausses erreurs (imports non // résolus) sur du code parfaitement valide. On garde la coloration, la complétion de base et le // pliage ; la vraie vérification de types reste le rôle du terminal. monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({ noSemanticValidation: true, noSyntaxValidation: true, noSuggestionDiagnostics: true, }); monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({ noSemanticValidation: true, noSyntaxValidation: true, noSuggestionDiagnostics: true, }); monaco.languages.json.jsonDefaults.setDiagnosticsOptions({ validate: false }); monaco.languages.css.cssDefaults.setOptions({ validate: false }); monaco.languages.html.htmlDefaults.setOptions({}); // Deux thèmes « Emerald » (hex concrets : Monaco n'accepte pas de var CSS). Les couleurs de token // (rules) sont SANS '#', les couleurs de chrome (colors) AVEC '#'. À garder synchronisé avec style.css. monaco.editor.defineTheme('arboretum-dark', { base: 'vs-dark', inherit: true, rules: [ { token: 'comment', foreground: '52525b', fontStyle: 'italic' }, { token: 'keyword', foreground: '34d399' }, { token: 'storage', foreground: '34d399' }, { token: 'string', foreground: 'fcd34d' }, { token: 'number', foreground: '7dd3fc' }, { token: 'constant', foreground: '7dd3fc' }, { token: 'type', foreground: '5eead4' }, { token: 'function', foreground: '7dd3fc' }, { token: 'variable', foreground: 'f4f4f5' }, { token: 'operator', foreground: 'a1a1aa' }, { token: 'delimiter', foreground: 'a1a1aa' }, { token: 'tag', foreground: 'f87171' }, { token: 'attribute.name', foreground: 'fcd34d' }, { token: 'attribute.value', foreground: '34d399' }, ], colors: { 'editor.background': '#09090b', 'editor.foreground': '#f4f4f5', 'editorCursor.foreground': '#34d399', 'editor.selectionBackground': '#3f3f46', 'editor.lineHighlightBackground': '#18181b', 'editorLineNumber.foreground': '#52525b', 'editorLineNumber.activeForeground': '#a1a1aa', 'editorIndentGuide.background1': '#27272a', 'editorGutter.background': '#09090b', 'editorWidget.background': '#18181b', 'editorWidget.border': '#27272a', }, }); monaco.editor.defineTheme('arboretum-light', { base: 'vs', inherit: true, rules: [ { token: 'comment', foreground: 'a1a1aa', fontStyle: 'italic' }, { token: 'keyword', foreground: '059669' }, { token: 'storage', foreground: '059669' }, { token: 'string', foreground: 'b45309' }, { token: 'number', foreground: '0284c7' }, { token: 'constant', foreground: '0284c7' }, { token: 'type', foreground: '0d9488' }, { token: 'function', foreground: '0284c7' }, { token: 'variable', foreground: '18181b' }, { token: 'operator', foreground: '52525b' }, { token: 'delimiter', foreground: '52525b' }, { token: 'tag', foreground: 'dc2626' }, { token: 'attribute.name', foreground: 'b45309' }, { token: 'attribute.value', foreground: '059669' }, ], colors: { 'editor.background': '#fafafa', 'editor.foreground': '#18181b', 'editorCursor.foreground': '#059669', 'editor.selectionBackground': '#d4d4d8', 'editor.lineHighlightBackground': '#f4f4f5', 'editorLineNumber.foreground': '#a1a1aa', 'editorLineNumber.activeForeground': '#52525b', 'editorIndentGuide.background1': '#e4e4e7', 'editorGutter.background': '#fafafa', 'editorWidget.background': '#ffffff', 'editorWidget.border': '#e4e4e7', }, }); /** Nom du thème Monaco pour le thème résolu courant. */ export function monacoThemeName(resolved: ResolvedTheme): 'arboretum-dark' | 'arboretum-light' { return resolved === 'light' ? 'arboretum-light' : 'arboretum-dark'; } export { monaco };