From 263a33ffb2554c2755ab7c0afdf4b3b4dcb04e5f Mon Sep 17 00:00:00 2001 From: Bohdan Triapitsyn Date: Tue, 10 Feb 2026 12:57:43 +0200 Subject: [PATCH] chore: simplify CodeMirror theme --- bun.lock | 24 --- package.json | 2 - packages/ui/package.json | 2 - .../ui/src/components/ui/CodeMirrorEditor.tsx | 17 ++- packages/ui/src/index.css | 137 ++++++++++++++++++ .../ui/src/lib/codemirror/flexokiTheme.ts | 96 ++++-------- 6 files changed, 184 insertions(+), 94 deletions(-) diff --git a/bun.lock b/bun.lock index 11f19fda..2c18bde1 100644 --- a/bun.lock +++ b/bun.lock @@ -7,8 +7,6 @@ "dependencies": { "@codemirror/autocomplete": "^6.20.0", "@codemirror/commands": "^6.10.1", - "@codemirror/highlight": "^0.19.8", - "@codemirror/history": "^0.19.2", "@codemirror/lang-css": "^6.3.1", "@codemirror/lang-html": "^6.4.11", "@codemirror/lang-javascript": "^6.2.4", @@ -110,8 +108,6 @@ "dependencies": { "@codemirror/autocomplete": "^6.20.0", "@codemirror/commands": "^6.10.1", - "@codemirror/highlight": "^0.19.8", - "@codemirror/history": "^0.19.2", "@codemirror/lang-css": "^6.3.1", "@codemirror/lang-html": "^6.4.11", "@codemirror/lang-javascript": "^6.2.4", @@ -539,10 +535,6 @@ "@codemirror/commands": ["@codemirror/commands@6.10.2", "", { "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.4.0", "@codemirror/view": "^6.27.0", "@lezer/common": "^1.1.0" } }, "sha512-vvX1fsih9HledO1c9zdotZYUZnE4xV0m6i3m25s5DIfXofuprk6cRcLUZvSk3CASUbwjQX21tOGbkY2BH8TpnQ=="], - "@codemirror/highlight": ["@codemirror/highlight@0.19.8", "", { "dependencies": { "@codemirror/language": "^0.19.0", "@codemirror/rangeset": "^0.19.0", "@codemirror/state": "^0.19.3", "@codemirror/view": "^0.19.39", "@lezer/common": "^0.15.0", "style-mod": "^4.0.0" } }, "sha512-v/lzuHjrYR8MN2mEJcUD6fHSTXXli9C1XGYpr+ElV6fLBIUhMTNKR3qThp611xuWfXfwDxeL7ppcbkM/MzPV3A=="], - - "@codemirror/history": ["@codemirror/history@0.19.2", "", { "dependencies": { "@codemirror/state": "^0.19.2", "@codemirror/view": "^0.19.0" } }, "sha512-unhP4t3N2smzmHoo/Yio6ueWi+il8gm9VKrvi6wlcdGH5fOfVDNkmjHQ495SiR+EdOG35+3iNebSPYww0vN7ow=="], - "@codemirror/lang-angular": ["@codemirror/lang-angular@0.1.4", "", { "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", "", { "dependencies": { "@codemirror/language": "^6.0.0", "@lezer/cpp": "^1.0.0" } }, "sha512-URM26M3vunFFn9/sm6rzqrBzDgfWuDixp85uTY49wKudToc2jTHUrKIGGKs+QWND+YLofNNZpxcNGRynFJfvgA=="], @@ -593,14 +585,10 @@ "@codemirror/lint": ["@codemirror/lint@6.9.3", "", { "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.35.0", "crelt": "^1.0.5" } }, "sha512-y3YkYhdnhjDBAe0VIA0c4wVoFOvnp8CnAvfLqi0TqotIv92wIlAAP7HELOpLBsKwjAX6W92rSflA6an/2zBvXw=="], - "@codemirror/rangeset": ["@codemirror/rangeset@0.19.9", "", { "dependencies": { "@codemirror/state": "^0.19.0" } }, "sha512-V8YUuOvK+ew87Xem+71nKcqu1SXd5QROMRLMS/ljT5/3MCxtgrRie1Cvild0G/Z2f1fpWxzX78V0U4jjXBorBQ=="], - "@codemirror/search": ["@codemirror/search@6.6.0", "", { "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.37.0", "crelt": "^1.0.5" } }, "sha512-koFuNXcDvyyotWcgOnZGmY7LZqEOXZaaxD/j6n18TCLx2/9HieZJ5H6hs1g8FiRxBD0DNfs0nXn17g872RmYdw=="], "@codemirror/state": ["@codemirror/state@6.5.4", "", { "dependencies": { "@marijn/find-cluster-break": "^1.0.0" } }, "sha512-8y7xqG/hpB53l25CIoit9/ngxdfoG+fx+V3SHBrinnhOtLvKHRyAJJuHzkWrR4YXXLX8eXBsejgAAxHUOdW1yw=="], - "@codemirror/text": ["@codemirror/text@0.19.6", "", {}, "sha512-T9jnREMIygx+TPC1bOuepz18maGq/92q2a+n4qTqObKwvNMg+8cMTslb8yxeEDEq7S3kpgGWxgO1UWbQRij0dA=="], - "@codemirror/view": ["@codemirror/view@6.39.13", "", { "dependencies": { "@codemirror/state": "^6.5.0", "crelt": "^1.0.6", "style-mod": "^4.1.0", "w3c-keyname": "^2.2.4" } }, "sha512-QBO8ZsgJLCbI28KdY0/oDy5NQLqOQVZCozBknxc2/7L98V+TVYFHnfaCsnGh1U+alpd2LOkStVwYY7nW2R1xbw=="], "@develar/schema-utils": ["@develar/schema-utils@2.6.5", "", { "dependencies": { "ajv": "^6.12.0", "ajv-keywords": "^3.4.1" } }, "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig=="], @@ -3229,16 +3217,6 @@ "@chevrotain/gast/lodash-es": ["lodash-es@4.17.21", "", {}, "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="], - "@codemirror/highlight/@codemirror/language": ["@codemirror/language@0.19.10", "", { "dependencies": { "@codemirror/state": "^0.19.0", "@codemirror/text": "^0.19.0", "@codemirror/view": "^0.19.0", "@lezer/common": "^0.15.5", "@lezer/lr": "^0.15.0" } }, "sha512-yA0DZ3RYn2CqAAGW62VrU8c4YxscMQn45y/I9sjBlqB1e2OTQLg4CCkMBuMSLXk4xaqjlsgazeOQWaJQOKfV8Q=="], - - "@codemirror/highlight/@codemirror/state": ["@codemirror/state@0.19.9", "", { "dependencies": { "@codemirror/text": "^0.19.0" } }, "sha512-psOzDolKTZkx4CgUqhBQ8T8gBc0xN5z4gzed109aF6x7D7umpDRoimacI/O6d9UGuyl4eYuDCZmDFr2Rq7aGOw=="], - - "@codemirror/highlight/@lezer/common": ["@lezer/common@0.15.12", "", {}, "sha512-edfwCxNLnzq5pBA/yaIhwJ3U3Kz8VAUOTRg0hhxaizaI1N+qxV7EXDv/kLCkLeq2RzSFvxexlaj5Mzfn2kY0Ig=="], - - "@codemirror/history/@codemirror/state": ["@codemirror/state@0.19.9", "", { "dependencies": { "@codemirror/text": "^0.19.0" } }, "sha512-psOzDolKTZkx4CgUqhBQ8T8gBc0xN5z4gzed109aF6x7D7umpDRoimacI/O6d9UGuyl4eYuDCZmDFr2Rq7aGOw=="], - - "@codemirror/rangeset/@codemirror/state": ["@codemirror/state@0.19.9", "", { "dependencies": { "@codemirror/text": "^0.19.0" } }, "sha512-psOzDolKTZkx4CgUqhBQ8T8gBc0xN5z4gzed109aF6x7D7umpDRoimacI/O6d9UGuyl4eYuDCZmDFr2Rq7aGOw=="], - "@electron/asar/commander": ["commander@5.1.0", "", {}, "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg=="], "@electron/asar/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], @@ -3525,8 +3503,6 @@ "@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], - "@codemirror/highlight/@codemirror/language/@lezer/lr": ["@lezer/lr@0.15.8", "", { "dependencies": { "@lezer/common": "^0.15.0" } }, "sha512-bM6oE6VQZ6hIFxDNKk8bKPa14hqFrV07J/vHGOeiAbJReIaQXmkVb6xQu4MR+JBTLa5arGRyAAjJe1qaQt3Uvg=="], - "@electron/get/fs-extra/jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="], "@electron/get/fs-extra/universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="], diff --git a/package.json b/package.json index 929996aa..7a8aeaab 100644 --- a/package.json +++ b/package.json @@ -60,8 +60,6 @@ "dependencies": { "@codemirror/autocomplete": "^6.20.0", "@codemirror/commands": "^6.10.1", - "@codemirror/highlight": "^0.19.8", - "@codemirror/history": "^0.19.2", "@codemirror/lang-css": "^6.3.1", "@codemirror/lang-html": "^6.4.11", "@codemirror/lang-javascript": "^6.2.4", diff --git a/packages/ui/package.json b/packages/ui/package.json index 9726d27f..ab7565cc 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -13,8 +13,6 @@ "dependencies": { "@codemirror/autocomplete": "^6.20.0", "@codemirror/commands": "^6.10.1", - "@codemirror/highlight": "^0.19.8", - "@codemirror/history": "^0.19.2", "@codemirror/lang-css": "^6.3.1", "@codemirror/lang-html": "^6.4.11", "@codemirror/lang-javascript": "^6.2.4", diff --git a/packages/ui/src/components/ui/CodeMirrorEditor.tsx b/packages/ui/src/components/ui/CodeMirrorEditor.tsx index 9664166a..b2e198c3 100644 --- a/packages/ui/src/components/ui/CodeMirrorEditor.tsx +++ b/packages/ui/src/components/ui/CodeMirrorEditor.tsx @@ -4,7 +4,7 @@ import type { Extension } from '@codemirror/state'; import { Compartment, EditorState, RangeSetBuilder, StateField } from '@codemirror/state'; import { Decoration, type DecorationSet, EditorView, type KeyBinding, ViewPlugin, WidgetType, gutters, keymap, lineNumbers } from '@codemirror/view'; import { defaultKeymap, indentWithTab, history, historyKeymap } from '@codemirror/commands'; -import { indentUnit } from '@codemirror/language'; +import { forceParsing, indentUnit } from '@codemirror/language'; import { search, searchKeymap, openSearchPanel, closeSearchPanel } from '@codemirror/search'; import { createPortal } from 'react-dom'; @@ -182,9 +182,18 @@ export function CodeMirrorEditor({ return; } + const cspNonce = (() => { + if (typeof document === 'undefined') return null; + const metaNonce = document.querySelector('meta[name="csp-nonce"]')?.getAttribute('content'); + if (metaNonce) return metaNonce; + const windowNonce = (window as Window & { __OPENCHAMBER_CSP_NONCE__?: string }).__OPENCHAMBER_CSP_NONCE__; + return typeof windowNonce === 'string' && windowNonce.length > 0 ? windowNonce : null; + })(); + const state = EditorState.create({ doc: valueRef.current, extensions: [ + ...(cspNonce ? [EditorView.cspNonce.of(cspNonce)] : []), gutters({ fixed: true }), lineNumbersCompartment.of(lineNumbers(lineNumbersConfig)), history(), @@ -214,6 +223,9 @@ export function CodeMirrorEditor({ parent: hostRef.current, }); + forceParsing(viewRef.current, viewRef.current.state.doc.length, 200); + viewRef.current.requestMeasure(); + if (viewRef.current) { onViewReadyRef.current?.(viewRef.current); } @@ -243,6 +255,9 @@ export function CodeMirrorEditor({ ], }); + forceParsing(view, view.state.doc.length, 200); + view.requestMeasure(); + // Force a re-render to ensure Portals can find the new widget containers in the DOM // The containers are created synchronously by CodeMirror during dispatch -> toDOM forceUpdate(); diff --git a/packages/ui/src/index.css b/packages/ui/src/index.css index aa19e7ca..e284f5e8 100644 --- a/packages/ui/src/index.css +++ b/packages/ui/src/index.css @@ -33,6 +33,143 @@ textarea[data-chat-input="true"]:focus-visible { font-family: "IBM Plex Sans", "SF Pro Text", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif !important; } +/* Codemirror syntax fallback for classHighlighter tokens */ +.cm-editor .tok-comment, +.cm-editor .tok-docComment, +.cm-editor .tok-meta, +.cm-editor .tok-documentMeta { + color: var(--syntax-comment); +} + +.cm-editor .tok-keyword, +.cm-editor .tok-controlKeyword, +.cm-editor .tok-definitionKeyword, +.cm-editor .tok-modifier, +.cm-editor .tok-moduleKeyword { + color: var(--syntax-keyword); +} + +.cm-editor .tok-operator, +.cm-editor .tok-operatorKeyword, +.cm-editor .tok-derefOperator, +.cm-editor .tok-updateOperator, +.cm-editor .tok-definitionOperator, +.cm-editor .tok-typeOperator, +.cm-editor .tok-controlOperator, +.cm-editor .tok-logicOperator, +.cm-editor .tok-bitwiseOperator, +.cm-editor .tok-arithmeticOperator, +.cm-editor .tok-compareOperator { + color: var(--syntax-operator); +} + +.cm-editor .tok-string, +.cm-editor .tok-special.tok-string, +.cm-editor .tok-escape, +.cm-editor .tok-regexp, +.cm-editor .tok-attributeValue, +.cm-editor .tok-monospace { + color: var(--syntax-string); +} + +.cm-editor .tok-number, +.cm-editor .tok-bool, +.cm-editor .tok-atom, +.cm-editor .tok-null, +.cm-editor .tok-self { + color: var(--syntax-number); +} + +.cm-editor .tok-function.tok-variableName, +.cm-editor .tok-function.tok-propertyName, +.cm-editor .tok-standard.tok-variableName, +.cm-editor .tok-special.tok-variableName { + color: var(--syntax-function); +} + +.cm-editor .tok-variableName, +.cm-editor .tok-definition.tok-variableName, +.cm-editor .tok-local.tok-variableName, +.cm-editor .tok-constant.tok-variableName, +.cm-editor .tok-propertyName, +.cm-editor .tok-attributeName { + color: var(--syntax-variable); +} + +.cm-editor .tok-className, +.cm-editor .tok-typeName, +.cm-editor .tok-namespace { + color: var(--syntax-type); +} + +.cm-editor .tok-tagName, +.cm-editor .tok-labelName, +.cm-editor .tok-annotation, +.cm-editor .tok-macroName { + color: var(--syntax-keyword); +} + +.cm-editor .tok-link { + color: var(--syntax-function); + text-decoration: underline; +} + +.cm-editor .tok-punctuation, +.cm-editor .tok-separator, +.cm-editor .tok-bracket, +.cm-editor .tok-paren, +.cm-editor .tok-brace, +.cm-editor .tok-squareBracket, +.cm-editor .tok-angleBracket { + color: color-mix(in srgb, var(--syntax-comment) 85%, var(--syntax-foreground) 15%); +} + +/* Codemirror syntax fallback for class-based HighlightStyle tokens */ +.cm-editor .cm-comment, +.cm-editor .cm-meta { + color: var(--syntax-comment); +} + +.cm-editor .cm-keyword, +.cm-editor .cm-tag { + color: var(--syntax-keyword); +} + +.cm-editor .cm-operator { + color: var(--syntax-operator); +} + +.cm-editor .cm-string, +.cm-editor .cm-string-2, +.cm-editor .cm-link { + color: var(--syntax-string); +} + +.cm-editor .cm-number, +.cm-editor .cm-atom { + color: var(--syntax-number); +} + +.cm-editor .cm-builtin, +.cm-editor .cm-def { + color: var(--syntax-function); +} + +.cm-editor .cm-variable, +.cm-editor .cm-variable-2, +.cm-editor .cm-property, +.cm-editor .cm-attribute { + color: var(--syntax-variable); +} + +.cm-editor .cm-variable-3 { + color: var(--syntax-type); +} + +.cm-editor .cm-punctuation { + color: color-mix(in srgb, var(--syntax-comment) 85%, var(--syntax-foreground) 15%); +} + :root.vscode-runtime textarea[data-chat-input="true"]::placeholder { color: color-mix(in srgb, var(--vscode-input-placeholderForeground, var(--muted-foreground)) 65%, transparent); } diff --git a/packages/ui/src/lib/codemirror/flexokiTheme.ts b/packages/ui/src/lib/codemirror/flexokiTheme.ts index 6d5d9ebf..e0273fa8 100644 --- a/packages/ui/src/lib/codemirror/flexokiTheme.ts +++ b/packages/ui/src/lib/codemirror/flexokiTheme.ts @@ -1,8 +1,8 @@ import type { Extension } from '@codemirror/state'; import { EditorView } from '@codemirror/view'; -import { HighlightStyle, syntaxHighlighting } from '@codemirror/language'; -import { tags as t } from '@lezer/highlight'; +import { HighlightStyle, defaultHighlightStyle, syntaxHighlighting } from '@codemirror/language'; +import { classHighlighter, tags as t } from '@lezer/highlight'; import type { Theme } from '@/types/theme'; @@ -41,6 +41,12 @@ export function createFlexokiCodeMirrorTheme(theme: Theme): Extension { '.cm-number': { color: theme.colors.syntax.base.number, }, + '.cm-operator': { + color: theme.colors.syntax.base.operator, + }, + '.cm-punctuation': { + color: tokens.punctuation || theme.colors.syntax.base.comment, + }, '.cm-atom': { color: tokens.boolean || theme.colors.syntax.base.number, }, @@ -76,6 +82,7 @@ export function createFlexokiCodeMirrorTheme(theme: Theme): Extension { color: tokens.url || theme.colors.syntax.base.keyword, textDecoration: 'underline', }, + '.cm-content': { caretColor: theme.colors.interactive.cursor, }, @@ -121,73 +128,32 @@ export function createFlexokiCodeMirrorTheme(theme: Theme): Extension { }, { dark: isDark }); const syntax = HighlightStyle.define([ - { tag: t.comment, color: theme.colors.syntax.base.comment }, - { tag: t.docComment, color: tokens.commentDoc || theme.colors.syntax.base.comment }, + { tag: [t.comment, t.docComment, t.meta, t.documentMeta], class: 'cm-comment' }, + { tag: [t.keyword, t.controlKeyword, t.moduleKeyword, t.definitionKeyword, t.modifier], class: 'cm-keyword' }, + { tag: [t.operatorKeyword, t.operator, t.derefOperator, t.updateOperator, t.definitionOperator, t.typeOperator, t.controlOperator, t.logicOperator, t.bitwiseOperator, t.arithmeticOperator, t.compareOperator], class: 'cm-operator' }, + { tag: [t.punctuation, t.separator, t.bracket, t.paren, t.brace, t.squareBracket, t.angleBracket], class: 'cm-punctuation' }, - { tag: t.keyword, color: theme.colors.syntax.base.keyword }, - { tag: t.controlKeyword, color: theme.colors.syntax.base.keyword }, - { tag: t.operatorKeyword, color: theme.colors.syntax.base.operator }, - { tag: t.moduleKeyword, color: tokens.keywordImport || theme.colors.syntax.base.keyword }, - { tag: [t.definitionKeyword, t.modifier], color: tokens.storageModifier || theme.colors.syntax.base.keyword }, + { tag: [t.string, t.regexp, t.attributeValue, t.special(t.string), t.monospace], class: 'cm-string' }, + { tag: t.escape, class: 'cm-string-2' }, + { tag: [t.number, t.bool, t.atom, t.null, t.self], class: 'cm-number' }, - { tag: t.atom, color: tokens.boolean || theme.colors.syntax.base.number }, - { tag: [t.null, t.self], color: theme.colors.syntax.base.number }, - { tag: [t.meta, t.documentMeta], color: theme.colors.syntax.base.comment }, + { tag: [t.function(t.variableName), t.function(t.definition(t.variableName)), t.function(t.propertyName), t.standard(t.variableName), t.special(t.variableName)], class: 'cm-builtin' }, + { tag: t.definition(t.variableName), class: 'cm-def' }, + { tag: [t.variableName, t.local(t.variableName), t.constant(t.variableName), t.literal], class: 'cm-variable' }, + { tag: t.propertyName, class: 'cm-property' }, + { tag: t.attributeName, class: 'cm-attribute' }, - { tag: t.string, color: theme.colors.syntax.base.string }, - { tag: t.escape, color: tokens.stringEscape || theme.colors.syntax.base.foreground }, - { tag: t.regexp, color: tokens.regex || theme.colors.syntax.base.string }, + { tag: [t.className, t.typeName, t.namespace], class: 'cm-variable-3' }, + { tag: [t.tagName, t.labelName, t.annotation, t.macroName], class: 'cm-tag' }, + { tag: t.link, class: 'cm-link' }, - { tag: t.number, color: theme.colors.syntax.base.number }, - { tag: t.bool, color: tokens.boolean || theme.colors.syntax.base.number }, - - // Operators + punctuation - { tag: t.operator, color: theme.colors.syntax.base.operator }, - { tag: [t.derefOperator, t.updateOperator, t.definitionOperator, t.typeOperator, t.controlOperator], color: theme.colors.syntax.base.operator }, - { tag: [t.logicOperator, t.bitwiseOperator, t.arithmeticOperator], color: theme.colors.syntax.base.operator }, - { tag: [t.compareOperator], color: tokens.diffModified || theme.colors.syntax.base.operator }, - { tag: [t.punctuation, t.separator, t.bracket, t.paren, t.brace, t.squareBracket, t.angleBracket], color: tokens.punctuation || theme.colors.syntax.base.comment }, - - // Calls vs definitions - { tag: t.function(t.variableName), color: tokens.functionCall || theme.colors.syntax.base.function }, - { tag: t.function(t.definition(t.variableName)), color: theme.colors.syntax.base.function }, - { tag: t.function(t.propertyName), color: tokens.method || tokens.functionCall || theme.colors.syntax.base.function }, - - // Names - { tag: t.namespace, color: tokens.namespace || theme.colors.syntax.base.type }, - { tag: t.moduleKeyword, color: tokens.module || theme.colors.syntax.base.keyword }, - { tag: t.macroName, color: tokens.macro || theme.colors.syntax.base.keyword }, - { tag: t.labelName, color: tokens.label || theme.colors.syntax.base.keyword }, - { tag: t.annotation, color: tokens.decorator || theme.colors.syntax.base.keyword }, - - // Variables/properties - { tag: t.propertyName, color: tokens.variableProperty || theme.colors.syntax.base.keyword }, - { tag: t.attributeName, color: tokens.tagAttribute || theme.colors.syntax.base.keyword }, - - // StreamLanguage/legacy token tags resolve to these - { tag: t.standard(t.variableName), color: tokens.method || theme.colors.syntax.base.function }, - { tag: t.definition(t.variableName), color: theme.colors.syntax.base.variable }, - { tag: t.local(t.variableName), color: theme.colors.syntax.base.variable }, - { tag: t.special(t.variableName), color: tokens.variableOther || theme.colors.syntax.base.function }, - { tag: t.variableName, color: theme.colors.syntax.base.variable }, - { tag: t.special(t.string), color: theme.colors.syntax.base.string }, - - // Types/constants - { tag: t.className, color: tokens.className || theme.colors.syntax.base.type }, - { tag: t.typeName, color: theme.colors.syntax.base.type }, - { tag: t.constant(t.variableName), color: tokens.constant || theme.colors.syntax.base.variable }, - { tag: t.literal, color: tokens.constant || theme.colors.syntax.base.variable }, - - // Markup - { tag: t.tagName, color: tokens.tag || theme.colors.syntax.base.keyword }, - { tag: t.attributeValue, color: tokens.tagAttributeValue || theme.colors.syntax.base.string }, - - // Markdown-ish - { tag: [t.heading, t.heading1, t.heading2, t.heading3, t.heading4, t.heading5, t.heading6], color: theme.colors.syntax.base.keyword, fontWeight: '600' }, - { tag: t.monospace, color: theme.colors.syntax.base.string }, - - { tag: t.link, color: tokens.url || theme.colors.syntax.base.keyword, textDecoration: 'underline' }, + { tag: [t.heading, t.heading1, t.heading2, t.heading3, t.heading4, t.heading5, t.heading6], class: 'cm-keyword' }, ]); - return [ui, syntaxHighlighting(syntax)]; + return [ + ui, + syntaxHighlighting(defaultHighlightStyle, { fallback: true }), + syntaxHighlighting(classHighlighter), + syntaxHighlighting(syntax), + ]; }