@fsegurai/codemirror-theme-forest 6.2.5 → 6.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/README.md +40 -32
  2. package/dist/index.cjs +660 -354
  3. package/dist/index.js +660 -354
  4. package/package.json +12 -3
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { EditorView } from '@codemirror/view';
2
1
  import { HighlightStyle, syntaxHighlighting } from '@codemirror/language';
2
+ import { EditorView } from '@codemirror/view';
3
3
  import { tags } from '@lezer/highlight';
4
4
 
5
5
  // Helper module for styling options
@@ -8,9 +8,6 @@ const generalContent = {
8
8
  fontFamily: 'JetBrains Mono, Consolas, monospace',
9
9
  lineHeight: '1.6',
10
10
  };
11
- const generalCursor = {
12
- borderLeftWidth: '2px',
13
- };
14
11
  const generalDiff = {
15
12
  insertedTextDecoration: 'none',
16
13
  deletedTextDecoration: 'line-through',
@@ -20,11 +17,9 @@ const generalGutter = {
20
17
  border: 'none',
21
18
  paddingRight: '8px',
22
19
  fontSize: '0.9em',
23
- fontWeight: '500',
24
20
  lineHeight: '1.78', // Adjusted to compensate for 0.9em fontSize (1.6 / 0.9 ≈ 1.78)
25
21
  };
26
22
  const generalPanel = {
27
- border: 'none',
28
23
  borderRadius: '4px',
29
24
  padding: '2px 10px',
30
25
  };
@@ -104,6 +99,498 @@ function applyMergeRevertStyles(styles) {
104
99
  document.head.appendChild(styleEl);
105
100
  }
106
101
 
102
+ // Shared theme core: every theme package describes a palette (`ThemeDefinition`) and this module turns it into the
103
+ // CodeMirror extension. Generated into each package by `bun run generate:helpers`; edit only the copy in
104
+ // `packages/.helper/utils/`.
105
+ /** Parent of every fine role: an omitted fine role resolves to its parent. */
106
+ const ROLE_PARENTS = {
107
+ controlKeyword: 'keyword',
108
+ moduleKeyword: 'keyword',
109
+ definitionKeyword: 'keyword',
110
+ operatorKeyword: 'operator',
111
+ modifier: 'keyword',
112
+ arithmeticOperator: 'operator',
113
+ logicOperator: 'operator',
114
+ compareOperator: 'operator',
115
+ bitwiseOperator: 'operator',
116
+ updateOperator: 'operator',
117
+ derefOperator: 'operator',
118
+ definitionOperator: 'operator',
119
+ typeOperator: 'operator',
120
+ controlOperator: 'operator',
121
+ separator: 'punctuation',
122
+ bracket: 'punctuation',
123
+ paren: 'bracket',
124
+ brace: 'bracket',
125
+ squareBracket: 'bracket',
126
+ angleBracket: 'bracket',
127
+ character: 'name',
128
+ macroName: 'name',
129
+ variable: 'name',
130
+ localVariable: 'variable',
131
+ variableDefinition: 'variable',
132
+ nameDefinition: 'variableDefinition',
133
+ functionDefinition: 'function',
134
+ self: 'variable',
135
+ label: 'name',
136
+ propertyDefinition: 'property',
137
+ method: 'property',
138
+ methodDefinition: 'method',
139
+ specialProperty: 'property',
140
+ typeDefinition: 'type',
141
+ className: 'type',
142
+ namespace: 'type',
143
+ standardTag: 'tag',
144
+ annotation: 'meta',
145
+ documentMeta: 'meta',
146
+ processingInstruction: 'meta',
147
+ attributeValue: 'string',
148
+ literal: 'string',
149
+ docString: 'string',
150
+ regexp: 'string',
151
+ specialString: 'regexp',
152
+ escape: 'string',
153
+ unit: 'number',
154
+ atom: 'constant',
155
+ bool: 'atom',
156
+ null: 'constant',
157
+ constantName: 'constant',
158
+ standardName: 'constant',
159
+ color: 'standardName',
160
+ specialVariable: 'constant',
161
+ docComment: 'comment',
162
+ headingLevel: 'heading',
163
+ heading1: 'headingLevel',
164
+ heading2: 'headingLevel',
165
+ heading3: 'headingLevel',
166
+ heading4: 'headingLevel',
167
+ heading5: 'headingLevel',
168
+ heading6: 'headingLevel',
169
+ list: 'name',
170
+ quote: 'string',
171
+ monospace: 'string',
172
+ contentSeparator: 'punctuation',
173
+ };
174
+ /**
175
+ * Canonical tag → role table shared by every theme: every Lezer base tag and the modifier combinations that the
176
+ * official grammars emit. Each tag appears once, so no rule is shadowed by a later one.
177
+ */
178
+ const SYNTAX_TAGS = [
179
+ ['keyword', [tags.keyword]],
180
+ ['controlKeyword', [tags.controlKeyword]],
181
+ ['moduleKeyword', [tags.moduleKeyword]],
182
+ ['definitionKeyword', [tags.definitionKeyword]],
183
+ ['operatorKeyword', [tags.operatorKeyword]],
184
+ ['modifier', [tags.modifier]],
185
+ ['operator', [tags.operator]],
186
+ ['arithmeticOperator', [tags.arithmeticOperator]],
187
+ ['logicOperator', [tags.logicOperator]],
188
+ ['compareOperator', [tags.compareOperator]],
189
+ ['bitwiseOperator', [tags.bitwiseOperator]],
190
+ ['updateOperator', [tags.updateOperator]],
191
+ ['derefOperator', [tags.derefOperator]],
192
+ ['definitionOperator', [tags.definitionOperator]],
193
+ ['typeOperator', [tags.typeOperator]],
194
+ ['controlOperator', [tags.controlOperator]],
195
+ ['punctuation', [tags.punctuation, /*@__PURE__*/tags.function(tags.punctuation)]],
196
+ ['separator', [tags.separator]],
197
+ ['bracket', [tags.bracket]],
198
+ ['paren', [tags.paren]],
199
+ ['brace', [tags.brace, /*@__PURE__*/tags.special(tags.brace)]],
200
+ ['squareBracket', [tags.squareBracket]],
201
+ ['angleBracket', [tags.angleBracket]],
202
+ ['name', [tags.name, /*@__PURE__*/tags.special(tags.name)]],
203
+ ['character', [tags.character]],
204
+ ['macroName', [tags.macroName]],
205
+ ['variable', [tags.variableName, /*@__PURE__*/tags.standard(tags.variableName)]],
206
+ ['localVariable', [/*@__PURE__*/tags.local(tags.variableName)]],
207
+ ['variableDefinition', [/*@__PURE__*/tags.definition(tags.variableName)]],
208
+ ['nameDefinition', [/*@__PURE__*/tags.definition(tags.name)]],
209
+ ['function', [/*@__PURE__*/tags.function(tags.variableName)]],
210
+ ['functionDefinition', [/*@__PURE__*/tags.definition(/*@__PURE__*/tags.function(tags.variableName))]],
211
+ ['self', [tags.self]],
212
+ ['label', [tags.labelName]],
213
+ ['property', [tags.propertyName]],
214
+ ['propertyDefinition', [/*@__PURE__*/tags.definition(tags.propertyName)]],
215
+ ['method', [/*@__PURE__*/tags.function(tags.propertyName)]],
216
+ ['methodDefinition', [/*@__PURE__*/tags.definition(/*@__PURE__*/tags.function(tags.propertyName))]],
217
+ ['specialProperty', [/*@__PURE__*/tags.special(tags.propertyName), /*@__PURE__*/tags.definition(/*@__PURE__*/tags.special(tags.propertyName))]],
218
+ ['type', [tags.typeName, /*@__PURE__*/tags.standard(tags.typeName)]],
219
+ ['typeDefinition', [/*@__PURE__*/tags.definition(tags.typeName)]],
220
+ ['className', [tags.className, /*@__PURE__*/tags.definition(tags.className), /*@__PURE__*/tags.constant(tags.className)]],
221
+ ['namespace', [tags.namespace]],
222
+ ['tag', [tags.tagName]],
223
+ ['standardTag', [/*@__PURE__*/tags.standard(tags.tagName)]],
224
+ ['attribute', [tags.attributeName, /*@__PURE__*/tags.special(tags.attributeName)]],
225
+ ['attributeValue', [tags.attributeValue]],
226
+ ['literal', [tags.literal]],
227
+ ['string', [tags.string]],
228
+ ['docString', [tags.docString]],
229
+ ['regexp', [tags.regexp]],
230
+ ['specialString', [/*@__PURE__*/tags.special(tags.string), /*@__PURE__*/tags.special(tags.docString)]],
231
+ ['escape', [tags.escape]],
232
+ ['number', [tags.number, tags.integer, tags.float]],
233
+ ['unit', [tags.unit]],
234
+ ['atom', [tags.atom]],
235
+ ['bool', [tags.bool]],
236
+ ['null', [tags.null]],
237
+ ['constantName', [/*@__PURE__*/tags.constant(tags.name)]],
238
+ ['standardName', [/*@__PURE__*/tags.standard(tags.name)]],
239
+ ['color', [tags.color]],
240
+ ['specialVariable', [/*@__PURE__*/tags.special(tags.variableName)]],
241
+ ['comment', [tags.comment, tags.lineComment, tags.blockComment]],
242
+ ['docComment', [tags.docComment]],
243
+ ['meta', [tags.meta]],
244
+ ['documentMeta', [tags.documentMeta]],
245
+ ['processingInstruction', [tags.processingInstruction]],
246
+ ['annotation', [tags.annotation]],
247
+ ['content', [tags.content, /*@__PURE__*/tags.special(tags.content)]],
248
+ ['heading', [tags.heading]],
249
+ ['heading1', [tags.heading1]],
250
+ ['heading2', [tags.heading2]],
251
+ ['heading3', [tags.heading3]],
252
+ ['heading4', [tags.heading4]],
253
+ ['heading5', [tags.heading5]],
254
+ ['heading6', [tags.heading6]],
255
+ ['list', [tags.list]],
256
+ ['quote', [tags.quote]],
257
+ ['monospace', [tags.monospace]],
258
+ ['contentSeparator', [tags.contentSeparator]],
259
+ ['link', [tags.link]],
260
+ ['url', [tags.url]],
261
+ ['emphasis', [tags.emphasis]],
262
+ ['strong', [tags.strong]],
263
+ ['strikethrough', [tags.strikethrough]],
264
+ ['invalid', [tags.invalid]],
265
+ ['inserted', [tags.inserted]],
266
+ ['deleted', [tags.deleted]],
267
+ ['changed', [tags.changed]],
268
+ ];
269
+ /** Inline SVG image (same encoding as `@codemirror/lint`), used to draw lint markers in the theme colors. */
270
+ function svg(content, attrs = 'viewBox="0 0 40 40"') {
271
+ return `url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" ${attrs}>${encodeURIComponent(content)}</svg>')`;
272
+ }
273
+ /** Wavy underline of a lint range. */
274
+ function lintUnderline(color) {
275
+ return svg(`<path d="m0 2.5 l2 -1.5 l1 0 l2 1.5 l1 0" stroke="${color}" fill="none" stroke-width=".7"/>`, 'width="6" height="3"');
276
+ }
277
+ /**
278
+ * Canonical UI template: the same selectors for every theme, only palette values differ. Rules of equal specificity
279
+ * keep the order of the original theme files (later rules win).
280
+ */
281
+ function uiTemplate(ui) {
282
+ return {
283
+ '&': {
284
+ color: ui.foreground,
285
+ backgroundColor: ui.background,
286
+ border: ui.border,
287
+ fontSize: generalContent.fontSize,
288
+ fontFamily: generalContent.fontFamily,
289
+ },
290
+ '.cm-content': { caretColor: ui.cursor, lineHeight: generalContent.lineHeight },
291
+ '.cm-cursor, .cm-dropCursor': {
292
+ borderLeftColor: ui.cursor,
293
+ borderLeftWidth: ui.cursorWidth,
294
+ boxShadow: ui.cursorShadow,
295
+ },
296
+ '.cm-cursor-secondary': { borderLeftColor: ui.cursor, opacity: '0.6' },
297
+ '.cm-fat-cursor': {
298
+ backgroundColor: ui.fatCursor.background,
299
+ color: ui.background,
300
+ border: ui.fatCursor.border,
301
+ boxShadow: ui.cursorShadow,
302
+ },
303
+ '&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection': { backgroundColor: ui.selection, color: ui.selectionForeground, outline: ui.selectionOutline },
304
+ '&:not(.cm-focused) .cm-selectionBackground': { backgroundColor: ui.selectionInactive },
305
+ '.cm-selectionLayer': { zIndex: 100 },
306
+ '.cm-searchMatch': {
307
+ backgroundColor: ui.searchMatch.background,
308
+ outline: `${ui.outlineWidth} solid ${ui.searchMatch.outline}`,
309
+ color: ui.searchMatch.foreground,
310
+ borderRadius: generalSearchField.borderRadius,
311
+ boxShadow: ui.searchMatch.shadow,
312
+ },
313
+ '.cm-searchMatch span': { color: ui.searchMatch.foreground },
314
+ '.cm-searchMatch.cm-searchMatch-selected': {
315
+ backgroundColor: ui.searchMatch.selectedBackground,
316
+ color: ui.searchMatch.selectedForeground,
317
+ padding: generalSearchField.padding,
318
+ outline: ui.searchMatch.selectedOutline,
319
+ boxShadow: ui.searchMatch.selectedShadow,
320
+ },
321
+ '.cm-searchMatch.cm-searchMatch-selected span': { color: ui.searchMatch.selectedForeground },
322
+ '.cm-search.cm-panel.cm-textfield': {
323
+ color: ui.panel.foreground,
324
+ borderRadius: generalSearchField.borderRadius,
325
+ padding: generalSearchField.padding,
326
+ },
327
+ '.cm-textfield': {
328
+ backgroundColor: ui.panel.inputBackground,
329
+ color: ui.panel.foreground,
330
+ border: ui.panel.inputBorder,
331
+ borderRadius: generalSearchField.borderRadius,
332
+ padding: generalSearchField.padding,
333
+ },
334
+ '.cm-panels': {
335
+ backgroundColor: ui.panel.background,
336
+ color: ui.panel.foreground,
337
+ border: ui.panel.outline,
338
+ borderRadius: generalPanel.borderRadius,
339
+ boxShadow: ui.panel.shadow,
340
+ },
341
+ '.cm-panels.cm-panels-top': { borderBottom: `${ui.panel.borderWidth} solid ${ui.panel.border}` },
342
+ '.cm-panels.cm-panels-bottom': { borderTop: `${ui.panel.borderWidth} solid ${ui.panel.border}` },
343
+ '.cm-panel.cm-gotoLine': { color: ui.panel.foreground, padding: generalPanel.padding },
344
+ '.cm-panel button, .cm-button': {
345
+ backgroundColor: ui.panel.buttonBackground,
346
+ backgroundImage: 'none',
347
+ color: ui.panel.buttonForeground,
348
+ border: ui.panel.buttonBorder,
349
+ borderRadius: generalPanel.borderRadius,
350
+ padding: generalPanel.padding,
351
+ },
352
+ '.cm-panel button:hover, .cm-button:hover': {
353
+ backgroundColor: ui.panel.buttonHoverBackground,
354
+ color: ui.panel.buttonHoverForeground,
355
+ border: ui.panel.buttonHoverBorder,
356
+ boxShadow: ui.panel.buttonHoverShadow,
357
+ },
358
+ '.cm-activeLine': {
359
+ backgroundColor: ui.activeLine,
360
+ borderLeft: ui.activeLineBorder.left,
361
+ borderRight: ui.activeLineBorder.right,
362
+ borderRadius: generalLine.borderRadius,
363
+ zIndex: 1,
364
+ },
365
+ '.cm-gutters': {
366
+ backgroundColor: ui.gutter.background,
367
+ color: ui.gutter.foreground,
368
+ border: generalGutter.border,
369
+ borderRight: `${ui.outlineWidth} solid ${ui.gutter.border}`,
370
+ paddingRight: generalGutter.paddingRight,
371
+ },
372
+ '.cm-activeLineGutter': {
373
+ backgroundColor: ui.gutter.activeBackground,
374
+ color: ui.gutter.activeForeground,
375
+ fontWeight: ui.gutter.activeFontWeight,
376
+ border: ui.gutter.activeBorder,
377
+ },
378
+ '.cm-lineNumbers': { fontSize: generalGutter.fontSize, lineHeight: generalGutter.lineHeight },
379
+ '.cm-foldGutter': { fontSize: generalGutter.fontSize, lineHeight: generalGutter.lineHeight },
380
+ '.cm-foldGutter .cm-gutterElement': { color: ui.gutter.foreground, cursor: 'pointer' },
381
+ '.cm-foldGutter .cm-gutterElement:hover': { color: ui.gutter.foldHover },
382
+ '.cm-gutter-lint': { color: ui.gutter.foreground },
383
+ '.cm-lint-marker': { width: '1em', height: '1em' },
384
+ '.cm-lint-marker-error': {
385
+ content: svg(`<circle cx="20" cy="20" r="15" fill="${ui.diagnostic.error}" stroke="${ui.background}" stroke-width="4"/>`),
386
+ },
387
+ '.cm-lint-marker-warning': {
388
+ content: svg(`<path fill="${ui.diagnostic.warning}" stroke="${ui.background}" stroke-width="4" stroke-linejoin="round" d="M20 6L37 35L3 35Z"/>`),
389
+ },
390
+ '.cm-lint-marker-info': {
391
+ content: svg(`<path fill="${ui.diagnostic.info}" stroke="${ui.background}" stroke-width="4" stroke-linejoin="round" d="M5 5L35 5L35 35L5 35Z"/>`),
392
+ },
393
+ '.cm-changeGutter': { backgroundColor: ui.gutter.background },
394
+ '.cm-merge-b .cm-changedLineGutter, .cm-inlineChangedLineGutter': { background: ui.diff.insertedForeground },
395
+ '.cm-merge-a .cm-changedLineGutter, .cm-deletedLineGutter': { background: ui.diff.deletedForeground },
396
+ '.cm-insertedLine': {
397
+ textDecoration: generalDiff.insertedTextDecoration,
398
+ backgroundColor: ui.diff.insertedBackground,
399
+ color: ui.diff.insertedForeground,
400
+ padding: generalDiff.insertedLinePadding,
401
+ borderRadius: generalDiff.borderRadius,
402
+ },
403
+ 'ins.cm-insertedLine, ins.cm-insertedLine:not(:has(.cm-changedText))': {
404
+ textDecoration: generalDiff.insertedTextDecoration,
405
+ backgroundColor: `${ui.diff.insertedBackground} !important`,
406
+ color: ui.diff.insertedForeground,
407
+ padding: generalDiff.insertedLinePadding,
408
+ borderRadius: generalDiff.borderRadius,
409
+ border: ui.diff.insertedBorder,
410
+ },
411
+ 'ins.cm-insertedLine .cm-changedText': { background: 'transparent !important' },
412
+ '.cm-deletedLine': {
413
+ textDecoration: generalDiff.deletedTextDecoration,
414
+ backgroundColor: ui.diff.deletedBackground,
415
+ color: ui.diff.deletedForeground,
416
+ padding: generalDiff.insertedLinePadding,
417
+ borderRadius: generalDiff.borderRadius,
418
+ },
419
+ // Merge view deletions only: `del` decorations, inline deletion widgets and the lines of deleted chunks. `:where()`
420
+ // keeps the specificity of the former bare `del` selector without styling other `del` elements.
421
+ 'del.cm-deletedLine, del.cm-deletedText, :where(.cm-deletedChunk) del, :where(.cm-deletedChunk) del:not(:has(.cm-deletedText))': {
422
+ textDecoration: generalDiff.deletedTextDecoration,
423
+ backgroundColor: `${ui.diff.deletedBackground} !important`,
424
+ color: ui.diff.deletedForeground,
425
+ padding: generalDiff.insertedLinePadding,
426
+ borderRadius: generalDiff.borderRadius,
427
+ border: ui.diff.deletedBorder,
428
+ },
429
+ ':where(.cm-deletedChunk) del .cm-deletedText, :where(.cm-deletedChunk) del .cm-changedText, del:where(.cm-deletedLine) .cm-deletedText, del:where(.cm-deletedLine) .cm-changedText': { background: 'transparent !important' },
430
+ '.cm-merge-b .cm-changedLine, .cm-inlineChangedLine': { backgroundColor: ui.diff.insertedBackground },
431
+ '.cm-merge-a .cm-changedLine, .cm-deletedChunk': { backgroundColor: ui.diff.deletedBackground },
432
+ '.cm-collapsedLines': {
433
+ background: ui.foldPlaceholder.background,
434
+ color: ui.foldPlaceholder.foreground,
435
+ },
436
+ '.cm-mergeSpacer': { background: ui.merge.backgroundColor },
437
+ '.cm-tooltip': {
438
+ backgroundColor: ui.tooltip.background,
439
+ color: ui.tooltip.foreground,
440
+ border: `${ui.outlineWidth} solid ${ui.tooltip.border}`,
441
+ borderRadius: generalTooltip.borderRadius,
442
+ padding: generalTooltip.padding,
443
+ boxShadow: ui.tooltip.shadow,
444
+ },
445
+ '.cm-tooltip-autocomplete > ul': { backgroundColor: ui.tooltip.listBackground, border: ui.tooltip.listBorder },
446
+ '.cm-tooltip-autocomplete > ul > li': { padding: generalTooltip.padding, lineHeight: generalTooltip.lineHeight },
447
+ '.cm-tooltip-autocomplete > ul > li:hover': { backgroundColor: ui.tooltip.hoverBackground },
448
+ '.cm-tooltip-autocomplete > ul > li[aria-selected]': {
449
+ backgroundColor: ui.tooltip.selectedBackground,
450
+ color: ui.tooltip.selectedForeground,
451
+ border: ui.tooltip.selectedBorder,
452
+ borderRadius: generalTooltip.borderRadiusSelected,
453
+ },
454
+ '.cm-tooltip-autocomplete > ul > li > span.cm-completionIcon': {
455
+ color: ui.tooltip.icon,
456
+ paddingRight: generalTooltip.paddingRight,
457
+ },
458
+ '.cm-tooltip-autocomplete > ul > li > span.cm-completionDetail': { color: ui.tooltip.detail, fontStyle: 'italic' },
459
+ '.cm-completionMatchedText': {
460
+ color: 'inherit',
461
+ fontWeight: 'bold',
462
+ textDecoration: 'underline',
463
+ textDecorationColor: ui.matchingBracket.outline,
464
+ },
465
+ '.cm-completionInfo': {
466
+ backgroundColor: ui.tooltip.background,
467
+ color: ui.tooltip.foreground,
468
+ border: `${ui.outlineWidth} solid ${ui.tooltip.border}`,
469
+ padding: generalTooltip.padding,
470
+ },
471
+ '.cm-tooltip .cm-tooltip-arrow:before': { borderTopColor: 'transparent', borderBottomColor: 'transparent' },
472
+ '.cm-tooltip .cm-tooltip-arrow:after': {
473
+ borderTopColor: ui.tooltip.background,
474
+ borderBottomColor: ui.tooltip.background,
475
+ },
476
+ '.cm-tooltip-lint': { color: ui.tooltip.foreground, padding: '0' },
477
+ '.cm-tooltip-section:not(:first-child)': { borderTop: `1px solid ${ui.tooltip.border}` },
478
+ '.cm-diagnostic-error': {
479
+ borderLeft: `${ui.diagnostic.borderWidth} solid ${ui.diagnostic.error}`,
480
+ backgroundColor: ui.diagnostic.errorBackground,
481
+ },
482
+ '.cm-diagnostic-warning': {
483
+ borderLeft: `${ui.diagnostic.borderWidth} solid ${ui.diagnostic.warning}`,
484
+ backgroundColor: ui.diagnostic.warningBackground,
485
+ },
486
+ '.cm-diagnostic-info': {
487
+ borderLeft: `${ui.diagnostic.borderWidth} solid ${ui.diagnostic.info}`,
488
+ backgroundColor: ui.diagnostic.infoBackground,
489
+ },
490
+ '.cm-diagnostic-hint': { borderLeft: `${ui.diagnostic.borderWidth} solid ${ui.diagnostic.hint}` },
491
+ '.cm-diagnosticAction': {
492
+ backgroundColor: ui.panel.buttonBackground,
493
+ color: ui.panel.buttonForeground,
494
+ border: ui.panel.buttonBorder,
495
+ borderRadius: generalPanel.borderRadius,
496
+ },
497
+ '.cm-lintRange-error': { backgroundImage: lintUnderline(ui.diagnostic.error) },
498
+ '.cm-lintRange-warning': { backgroundImage: lintUnderline(ui.diagnostic.warning) },
499
+ '.cm-lintRange-info': { backgroundImage: lintUnderline(ui.diagnostic.info) },
500
+ '.cm-lintRange-hint': { backgroundImage: lintUnderline(ui.diagnostic.hint) },
501
+ '.cm-lintPoint-error': { borderBottom: `${ui.diagnostic.underlineWidth} wavy ${ui.diagnostic.error}` },
502
+ '.cm-lintPoint-warning': { borderBottom: `${ui.diagnostic.underlineWidth} wavy ${ui.diagnostic.warning}` },
503
+ '.cm-lintPoint-info': { borderBottom: `${ui.diagnostic.underlineWidth} wavy ${ui.diagnostic.info}` },
504
+ '.cm-matchingBracket': {
505
+ backgroundColor: ui.matchingBracket.background,
506
+ outline: `${ui.outlineWidth} solid ${ui.matchingBracket.outline}`,
507
+ borderRadius: generalMatching.borderRadius,
508
+ boxShadow: ui.matchingBracket.shadow,
509
+ },
510
+ '.cm-nonmatchingBracket': {
511
+ backgroundColor: ui.nonMatchingBracket.background,
512
+ outline: `${ui.outlineWidth} solid ${ui.nonMatchingBracket.outline}`,
513
+ borderRadius: generalMatching.borderRadius,
514
+ },
515
+ '.cm-selectionMatch': {
516
+ backgroundColor: ui.selectionMatch.background,
517
+ outline: `${ui.outlineWidth} solid ${ui.selectionMatch.outline}`,
518
+ borderRadius: generalMatching.borderRadius,
519
+ },
520
+ '.cm-snippetField': {
521
+ backgroundColor: ui.selectionMatch.background,
522
+ outline: `1px dashed ${ui.selectionMatch.outline}`,
523
+ borderRadius: generalMatching.borderRadius,
524
+ },
525
+ '.cm-snippetFieldPosition': { borderLeft: `1px dotted ${ui.cursor}` },
526
+ '.cm-foldPlaceholder': {
527
+ backgroundColor: ui.foldPlaceholder.background,
528
+ color: ui.foldPlaceholder.foreground,
529
+ border: `${ui.outlineWidth} ${ui.foldPlaceholder.borderStyle} ${ui.foldPlaceholder.border}`,
530
+ borderRadius: generalPlaceholder.borderRadius,
531
+ padding: generalPlaceholder.padding,
532
+ margin: generalPlaceholder.margin,
533
+ },
534
+ // Transparent outline: invisible normally, repainted with the system color in forced-colors mode (drops box-shadow).
535
+ '&.cm-focused': { outline: '2px solid transparent', boxShadow: ui.focusRing },
536
+ '& .cm-scroller::-webkit-scrollbar': { width: generalScroller.width, height: generalScroller.height },
537
+ '& .cm-scroller::-webkit-scrollbar-track': { background: ui.scrollbar.track, border: ui.scrollbar.trackBorder },
538
+ '& .cm-scroller::-webkit-scrollbar-thumb': {
539
+ backgroundColor: ui.scrollbar.thumb,
540
+ borderRadius: generalScroller.borderRadius,
541
+ border: ui.scrollbar.thumbBorder,
542
+ },
543
+ '& .cm-scroller::-webkit-scrollbar-thumb:hover': {
544
+ backgroundColor: ui.scrollbar.thumbHover,
545
+ boxShadow: ui.scrollbar.thumbHoverShadow,
546
+ },
547
+ '.cm-ghostText': { opacity: ui.ghostTextOpacity, color: ui.ghostText },
548
+ '.cm-placeholder': { color: ui.ghostText },
549
+ '.cm-specialChar': { color: ui.specialChar },
550
+ '.cm-trailingSpace': { backgroundColor: ui.diff.deletedBackground },
551
+ '.cm-highlightSpace': {
552
+ backgroundImage: `radial-gradient(circle at 50% 55%, ${ui.gutter.foreground} 20%, transparent 0)`,
553
+ },
554
+ '.cm-crosshair': { cursor: 'crosshair' },
555
+ };
556
+ }
557
+ /** Drops `null` declarations and selectors left without declarations. */
558
+ function emittedRules(spec) {
559
+ const result = {};
560
+ for (const [selector, declarations] of Object.entries(spec)) {
561
+ const emitted = Object.entries(declarations).filter((entry) => entry[1] !== null);
562
+ if (emitted.length > 0)
563
+ result[selector] = Object.fromEntries(emitted);
564
+ }
565
+ return result;
566
+ }
567
+ /** Style of a role, falling back through `ROLE_PARENTS` for omitted fine roles. */
568
+ function resolveRole(syntax, role) {
569
+ let current = role;
570
+ while (current) {
571
+ const style = syntax[current];
572
+ if (style)
573
+ return style;
574
+ current = ROLE_PARENTS[current];
575
+ }
576
+ return {};
577
+ }
578
+ /** Highlight rules of a theme: one rule per entry of the canonical table. */
579
+ function highlightRules(definition) {
580
+ return SYNTAX_TAGS.map(([role, tagList]) => (Object.assign({ tag: [...tagList] }, resolveRole(definition.syntax, role))));
581
+ }
582
+ /** Builds the editor theme, the syntax highlighting and the merge view styles of a theme definition. */
583
+ function defineTheme(definition) {
584
+ const theme = EditorView.theme(emittedRules(uiTemplate(definition.ui)), { dark: definition.dark });
585
+ const highlightStyle = HighlightStyle.define(highlightRules(definition));
586
+ return {
587
+ extension: [theme, syntaxHighlighting(highlightStyle)],
588
+ theme,
589
+ highlightStyle,
590
+ mergeStyles: Object.assign({}, definition.ui.merge),
591
+ };
592
+ }
593
+
107
594
  /**
108
595
  * Enhanced Forest theme color palette
109
596
  * -----------------------------------
@@ -113,386 +600,205 @@ function applyMergeRevertStyles(styles) {
113
600
  const base00 = '#1a2a33'; // Background - deeper forest shade for better contrast
114
601
  const base01 = '#d0d8e0'; // Foreground - clearer moonlight for better readability
115
602
  // const base02 = '#2d3c44'; // Selection - dark forest floor, more defined
116
- const base03 = '#607d8b'; // Comments - silvery bark gray, more legible
603
+ const base03 = '#8faebd'; // Comments - silvery bark gray, more legible
117
604
  // Flora elements (accent colors)
118
605
  const base04 = '#c594c5'; // Cursor - forest wildflower
119
606
  const base05 = '#a9d3ab'; // Keywords - lighter, fresher leaf green
120
- const base06 = '#4db6ac'; // Variables - clearer water reflection
121
- const base07 = '#78aadc'; // Functions - brighter dusk sky
122
- const base08 = '#ef5350'; // Strings - vibrant woodland berries
123
- const base09 = '#bc8f6a'; // Numbers - rich forest soil
607
+ const base06 = '#51baaf'; // Variables - clearer water reflection
608
+ const base07 = '#7caee0'; // Functions - brighter dusk sky
609
+ const base08 = '#fd887f'; // Strings - vibrant woodland berries
610
+ const base09 = '#cfa17b'; // Numbers - rich forest soil
124
611
  const base0A = '#ffb74d'; // Classes - golden sunlight through canopy
125
612
  const base0B = '#9ccc65'; // Properties - fresh moss
126
613
  const base0C = '#4dd0e1'; // Special chars - forest stream
127
- const base0D = '#7986cb'; // Tags - morning mist
128
- const base0E = '#ba68c8'; // Operators - purple wildflowers
614
+ const base0D = '#97a6ed'; // Tags - morning mist
615
+ const base0E = '#de8aed'; // Operators - purple wildflowers
129
616
  // const base0F = '#f57f17'; // Metadata - autumn leaves
130
617
  // UI-specific colors
131
- const invalid = '#ff5252'; // Error highlight - warning red berry
618
+ const invalid = '#fe8780'; // Error highlight - warning red berry
132
619
  const darkBackground = '#233039'; // Panel background - shadowy forest
133
620
  const highlightBackground = '#314443aa'; // Active line - forest clearing with dappled light
134
621
  const tooltipBackground = '#2a3b42'; // Tooltip background - darker canopy shadow
135
- const cursor = base04; // Cursor color
136
622
  const selection = '#2c5a3acc'; // Selection - translucent forest green
137
623
  const selectionMatch = '#5d482faa'; // Selection match - amber forest light
138
- const lineNumbers = '#607d8b90'; // Line numbers - faded tree bark
624
+ const lineNumbers = '#7c9aa8'; // Line numbers - faded tree bark
139
625
  const activeBracketBg = '#2c5a3a80'; // Active bracket - forest green
140
- const activeBracketBorder = base0A; // Active bracket border - golden sunlight
141
626
  // Diff/merge specific colors
142
627
  const addedBackground = '#28513a80', // Forest green with transparency for insertions
143
- removedBackground = '#763c3c70', // Deep red with transparency for deletions
144
- addedText = '#9ccc65', // Moss green for added text
145
- removedText = '#ef5350'; // Berry red for removed text
146
- /**
147
- * Enhanced editor theme styles for Forest
148
- */
149
- const forestTheme = /*@__PURE__*/EditorView.theme({
150
- // Base editor styles
151
- '&': {
152
- color: base01,
153
- backgroundColor: base00,
154
- fontSize: generalContent.fontSize,
155
- fontFamily: generalContent.fontFamily,
156
- },
157
- // Content and cursor
158
- '.cm-content': {
159
- caretColor: cursor,
160
- lineHeight: generalContent.lineHeight,
161
- },
162
- '.cm-cursor, .cm-dropCursor': {
163
- borderLeftColor: cursor,
164
- borderLeftWidth: generalCursor.borderLeftWidth,
165
- },
166
- '.cm-fat-cursor': {
167
- backgroundColor: `${cursor}99`,
168
- color: base00,
169
- },
170
- // Selection
171
- '&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection': {
172
- backgroundColor: selection,
173
- color: base01,
174
- },
175
- // Make sure selection appears above active line
176
- '.cm-selectionLayer': {
177
- zIndex: 100,
178
- },
179
- // Search functionality
180
- '.cm-searchMatch': {
181
- backgroundColor: '#4d653b80',
182
- outline: `1px solid ${base0A}90`,
183
- color: base01,
184
- borderRadius: generalSearchField.borderRadius,
185
- '& span': {
186
- color: base01,
628
+ removedBackground = '#763c3c70'; // Deep red with transparency for deletions
629
+ const theme = /*@__PURE__*/defineTheme({
630
+ dark: true,
631
+ ui: {
632
+ background: base00,
633
+ foreground: base01,
634
+ border: 'none',
635
+ cursor: base04,
636
+ cursorWidth: '2px',
637
+ cursorShadow: 'none',
638
+ fatCursor: { background: `${base04}99`, border: 'none' },
639
+ selection: '#2c5a3a92',
640
+ selectionInactive: '#2c5a3a92',
641
+ selectionForeground: base01,
642
+ selectionOutline: 'none',
643
+ activeLine: '#31444366',
644
+ activeLineBorder: { left: 'none', right: 'none' },
645
+ ghostText: '#8fa7b5',
646
+ ghostTextOpacity: '0.5',
647
+ specialChar: invalid,
648
+ focusRing: `0 0 0 2px ${base00}, 0 0 0 4px ${base0A}`,
649
+ outlineWidth: '1px',
650
+ searchMatch: {
651
+ background: '#4d653b80',
652
+ outline: `${base0A}90`,
653
+ foreground: base01,
654
+ shadow: 'none',
655
+ selectedBackground: '#42855c',
656
+ selectedForeground: base01,
657
+ selectedOutline: `1px solid ${base0A}90`,
658
+ selectedShadow: 'none',
187
659
  },
188
- },
189
- '.cm-searchMatch.cm-searchMatch-selected': {
190
- backgroundColor: '#42855c',
191
- color: base01,
192
- padding: generalSearchField.padding,
193
- '& span': {
194
- color: base01,
660
+ selectionMatch: { background: selectionMatch, outline: `${base0A}40` },
661
+ matchingBracket: { background: activeBracketBg, outline: `${base0A}80`, shadow: 'none' },
662
+ nonMatchingBracket: { background: '#5d482f80', outline: `${invalid}80` },
663
+ panel: {
664
+ background: darkBackground,
665
+ foreground: base01,
666
+ border: '#3e5059',
667
+ borderWidth: '1px',
668
+ outline: 'none',
669
+ shadow: 'none',
670
+ buttonBackground: darkBackground,
671
+ buttonForeground: base01,
672
+ buttonBorder: 'none',
673
+ buttonHoverBackground: '#2d3d47',
674
+ buttonHoverForeground: base01,
675
+ buttonHoverBorder: 'none',
676
+ buttonHoverShadow: 'none',
677
+ inputBackground: base00,
678
+ inputBorder: '1px solid #3e5059',
195
679
  },
196
- },
197
- '.cm-search.cm-panel.cm-textfield': {
198
- color: base01,
199
- borderRadius: generalSearchField.borderRadius,
200
- padding: generalSearchField.padding,
201
- },
202
- // Panels
203
- '.cm-panels': {
204
- backgroundColor: darkBackground,
205
- color: base01,
206
- borderRadius: '0 0 4px 4px',
207
- },
208
- '.cm-panels.cm-panels-top': {
209
- borderBottom: '1px solid #3e5059',
210
- },
211
- '.cm-panels.cm-panels-bottom': {
212
- borderTop: '1px solid #3e5059',
213
- },
214
- '.cm-panel button': {
215
- backgroundColor: darkBackground,
216
- color: base01,
217
- border: generalPanel.border,
218
- borderRadius: generalPanel.borderRadius,
219
- padding: generalPanel.padding,
220
- },
221
- '.cm-panel button:hover': {
222
- backgroundColor: '#2d3d47',
223
- },
224
- // Line highlighting
225
- '.cm-activeLine': {
226
- backgroundColor: highlightBackground,
227
- borderRadius: generalLine.borderRadius,
228
- zIndex: 1,
229
- },
230
- // Gutters
231
- '.cm-gutters': {
232
- backgroundColor: darkBackground,
233
- color: lineNumbers,
234
- border: generalGutter.border,
235
- borderRight: '1px solid #3e505980',
236
- paddingRight: generalGutter.paddingRight,
237
- },
238
- '.cm-activeLineGutter': {
239
- backgroundColor: highlightBackground,
240
- color: base01,
241
- fontWeight: generalGutter.fontWeight,
242
- },
243
- '.cm-lineNumbers': {
244
- fontSize: generalGutter.fontSize,
245
- lineHeight: generalGutter.lineHeight,
246
- },
247
- '.cm-foldGutter': {
248
- fontSize: generalGutter.fontSize,
249
- lineHeight: generalGutter.lineHeight,
250
- },
251
- '.cm-foldGutter .cm-gutterElement': {
252
- color: lineNumbers,
253
- cursor: 'pointer',
254
- },
255
- '.cm-foldGutter .cm-gutterElement:hover': {
256
- color: base01,
257
- },
258
- // Diff/Merge View Styles
259
- // Inserted/Added Content
260
- '.cm-insertedLine': {
261
- textDecoration: generalDiff.insertedTextDecoration,
262
- backgroundColor: addedBackground,
263
- color: addedText,
264
- padding: generalDiff.insertedLinePadding,
265
- borderRadius: generalDiff.borderRadius,
266
- },
267
- 'ins.cm-insertedLine, ins.cm-insertedLine:not(:has(.cm-changedText))': {
268
- textDecoration: generalDiff.insertedTextDecoration,
269
- backgroundColor: `${addedBackground} !important`,
270
- color: addedText,
271
- padding: generalDiff.insertedLinePadding,
272
- borderRadius: generalDiff.borderRadius,
273
- border: `1px solid ${addedText}40`,
274
- },
275
- 'ins.cm-insertedLine .cm-changedText': {
276
- background: 'transparent !important',
277
- },
278
- // Deleted/Removed Content
279
- '.cm-deletedLine': {
280
- textDecoration: generalDiff.deletedTextDecoration,
281
- backgroundColor: removedBackground,
282
- color: removedText,
283
- padding: generalDiff.insertedLinePadding,
284
- borderRadius: generalDiff.borderRadius,
285
- },
286
- 'del.cm-deletedLine, del, del:not(:has(.cm-deletedText))': {
287
- textDecoration: generalDiff.deletedTextDecoration,
288
- backgroundColor: `${removedBackground} !important`,
289
- color: removedText,
290
- padding: generalDiff.insertedLinePadding,
291
- borderRadius: generalDiff.borderRadius,
292
- border: `1px solid ${removedText}40`,
293
- },
294
- 'del .cm-deletedText, del .cm-changedText': {
295
- background: 'transparent !important',
296
- },
297
- // Tooltips and autocomplete
298
- '.cm-tooltip': {
299
- backgroundColor: tooltipBackground,
300
- border: '1px solid #3e5059',
301
- borderRadius: generalTooltip.borderRadius,
302
- padding: generalTooltip.padding,
303
- boxShadow: '0 2px 8px rgba(0, 0, 0, 0.3)',
304
- },
305
- '.cm-tooltip-autocomplete': {
306
- '& > ul': {
307
- backgroundColor: tooltipBackground,
308
- border: 'none',
680
+ gutter: {
681
+ background: darkBackground,
682
+ foreground: lineNumbers,
683
+ border: '#3e505980',
684
+ activeBackground: highlightBackground,
685
+ activeForeground: base01,
686
+ activeFontWeight: '500',
687
+ activeBorder: 'none',
688
+ foldHover: base01,
309
689
  },
310
- '& > ul > li': {
311
- padding: generalTooltip.padding,
312
- lineHeight: generalTooltip.lineHeight,
690
+ foldPlaceholder: { background: 'transparent', foreground: base03, border: `${base0A}70`, borderStyle: 'dotted' },
691
+ tooltip: {
692
+ background: tooltipBackground,
693
+ foreground: base01,
694
+ border: '#3e5059',
695
+ shadow: '0 2px 8px rgba(0, 0, 0, 0.3)',
696
+ listBackground: tooltipBackground,
697
+ listBorder: 'none',
698
+ hoverBackground: 'transparent',
699
+ selectedBackground: selection,
700
+ selectedForeground: base01,
701
+ selectedBorder: 'none',
702
+ icon: base03,
703
+ detail: base03,
313
704
  },
314
- '& > ul > li[aria-selected]': {
315
- backgroundColor: selection,
316
- color: base01,
317
- borderRadius: generalTooltip.borderRadiusSelected,
705
+ diff: {
706
+ insertedBackground: addedBackground,
707
+ insertedForeground: base0B,
708
+ insertedBorder: `1px solid ${base0B}40`,
709
+ deletedBackground: removedBackground,
710
+ deletedForeground: base08,
711
+ deletedBorder: `1px solid ${base08}40`,
318
712
  },
319
- '& > ul > li > span.cm-completionIcon': {
320
- color: base03,
321
- paddingRight: generalTooltip.paddingRight,
713
+ diagnostic: {
714
+ error: invalid,
715
+ warning: base0A,
716
+ info: base0C,
717
+ hint: base0C,
718
+ errorBackground: 'transparent',
719
+ warningBackground: 'transparent',
720
+ infoBackground: 'transparent',
721
+ borderWidth: '3px',
722
+ underlineWidth: '2px',
322
723
  },
323
- '& > ul > li > span.cm-completionDetail': {
324
- color: base03,
325
- fontStyle: 'italic',
724
+ scrollbar: {
725
+ track: darkBackground,
726
+ trackBorder: 'none',
727
+ thumb: '#3e5059',
728
+ thumbBorder: `3px solid ${darkBackground}`,
729
+ thumbHover: '#4e616a',
730
+ thumbHoverShadow: 'none',
326
731
  },
327
- },
328
- '.cm-tooltip .cm-tooltip-arrow:before': {
329
- borderTopColor: 'transparent',
330
- borderBottomColor: 'transparent',
331
- },
332
- '.cm-tooltip .cm-tooltip-arrow:after': {
333
- borderTopColor: tooltipBackground,
334
- borderBottomColor: tooltipBackground,
335
- },
336
- // Diagnostics styling
337
- '.cm-diagnostic': {
338
- '&-error': {
339
- borderLeft: `3px solid ${invalid}`,
732
+ merge: {
733
+ backgroundColor: darkBackground,
734
+ borderColor: '#3e5059',
735
+ buttonColor: base01,
736
+ buttonHoverColor: '#2d3d47',
340
737
  },
341
- '&-warning': {
342
- borderLeft: `3px solid ${base0A}`,
738
+ },
739
+ syntax: {
740
+ keyword: { color: base05, fontWeight: 'bold' },
741
+ definitionKeyword: { color: base05 },
742
+ modifier: { color: base09, fontStyle: 'italic' },
743
+ operator: { color: base0E },
744
+ punctuation: { color: base0E },
745
+ name: { color: base06 },
746
+ localVariable: { color: base07 },
747
+ variableDefinition: { color: base07 },
748
+ nameDefinition: { color: base06 },
749
+ function: { color: base07 },
750
+ self: { color: base09 },
751
+ label: { color: base07 },
752
+ property: { color: base0B, fontStyle: 'normal' },
753
+ type: { color: base0A },
754
+ typeDefinition: { color: base0A, fontWeight: 'bold' },
755
+ className: { color: base0A, fontStyle: 'italic' },
756
+ namespace: { color: base06, fontStyle: 'italic' },
757
+ tag: { color: base0D },
758
+ attribute: { color: base0C },
759
+ content: { color: base01 },
760
+ string: { color: base08 },
761
+ number: { color: base09 },
762
+ constant: { color: base09 },
763
+ comment: { fontStyle: 'italic', color: base03 },
764
+ meta: { color: base03 },
765
+ processingInstruction: { color: base08 },
766
+ standardName: { color: base09, fontWeight: 'bold' },
767
+ heading5: { color: base0A },
768
+ heading6: { color: base0A },
769
+ annotation: { color: invalid, fontStyle: 'italic' },
770
+ heading: { fontWeight: 'bold', color: base0A },
771
+ list: { color: base0A },
772
+ quote: { color: base03 },
773
+ monospace: { color: base01 },
774
+ contentSeparator: { color: base0C },
775
+ link: {
776
+ color: base0A,
777
+ fontWeight: '500',
778
+ textDecoration: 'underline',
779
+ textUnderlinePosition: 'under',
343
780
  },
344
- '&-info': {
345
- borderLeft: `3px solid ${base0C}`,
781
+ url: { color: base0C, textDecoration: 'underline', textUnderlineOffset: '2px' },
782
+ emphasis: { fontStyle: 'italic', color: base06 },
783
+ strong: { fontWeight: 'bold', color: base05 },
784
+ strikethrough: { color: invalid, textDecoration: 'line-through' },
785
+ invalid: {
786
+ color: base01,
787
+ textDecoration: 'underline wavy',
788
+ borderBottom: `1px wavy ${invalid}`,
346
789
  },
790
+ inserted: { color: base08 },
791
+ deleted: { color: invalid },
792
+ changed: { color: base09 },
347
793
  },
348
- '.cm-lintPoint-error': {
349
- borderBottom: `2px wavy ${invalid}`,
350
- },
351
- '.cm-lintPoint-warning': {
352
- borderBottom: `2px wavy ${base0A}`,
353
- },
354
- // Matching brackets
355
- '.cm-matchingBracket': {
356
- backgroundColor: activeBracketBg,
357
- outline: `1px solid ${activeBracketBorder}80`,
358
- borderRadius: generalMatching.borderRadius,
359
- },
360
- '.cm-nonmatchingBracket': {
361
- backgroundColor: '#5d482f80',
362
- outline: `1px solid ${invalid}80`,
363
- borderRadius: generalMatching.borderRadius,
364
- },
365
- // Selection matches
366
- '.cm-selectionMatch': {
367
- backgroundColor: selectionMatch,
368
- outline: `1px solid ${base0A}40`,
369
- borderRadius: generalMatching.borderRadius,
370
- },
371
- // Fold placeholder
372
- '.cm-foldPlaceholder': {
373
- backgroundColor: 'transparent',
374
- color: base03,
375
- border: `1px dotted ${base0A}70`,
376
- borderRadius: generalPlaceholder.borderRadius,
377
- padding: generalPlaceholder.padding,
378
- margin: generalPlaceholder.margin,
379
- },
380
- // Focus outline
381
- '&.cm-focused': {
382
- outline: 'none',
383
- boxShadow: `0 0 0 2px ${base00}, 0 0 0 3px ${base0A}40`,
384
- },
385
- // Scrollbars
386
- '& .cm-scroller::-webkit-scrollbar': {
387
- width: generalScroller.width,
388
- height: generalScroller.height,
389
- },
390
- '& .cm-scroller::-webkit-scrollbar-track': {
391
- background: darkBackground,
392
- },
393
- '& .cm-scroller::-webkit-scrollbar-thumb': {
394
- backgroundColor: '#3e5059',
395
- borderRadius: generalScroller.borderRadius,
396
- border: `3px solid ${darkBackground}`,
397
- },
398
- '& .cm-scroller::-webkit-scrollbar-thumb:hover': {
399
- backgroundColor: '#4e616a',
400
- },
401
- // Ghost text
402
- '.cm-ghostText': {
403
- opacity: '0.5',
404
- color: '#8fa7b5',
405
- },
406
- }, { dark: true });
407
- /**
408
- * Enhanced syntax highlighting for Forest theme
409
- */
410
- const forestHighlightStyle = /*@__PURE__*/HighlightStyle.define([
411
- // Keywords and language constructs
412
- { tag: tags.keyword, color: base05, fontWeight: 'bold' },
413
- { tag: tags.controlKeyword, color: base05, fontWeight: 'bold' },
414
- { tag: tags.moduleKeyword, color: base05, fontWeight: 'bold' },
415
- // Names and variables
416
- { tag: [tags.name, tags.deleted, tags.character, tags.macroName], color: base06 },
417
- { tag: [tags.variableName], color: base06 },
418
- { tag: [tags.propertyName], color: base0B, fontStyle: 'normal' },
419
- // Classes and types
420
- { tag: [tags.typeName], color: base0A },
421
- { tag: [tags.className], color: base0A, fontStyle: 'italic' },
422
- { tag: [tags.namespace], color: base06, fontStyle: 'italic' },
423
- // Operators and punctuation
424
- { tag: [tags.operator, tags.operatorKeyword], color: base0E },
425
- { tag: [tags.bracket], color: base0E },
426
- { tag: [tags.brace], color: base0E },
427
- { tag: [tags.punctuation], color: base0E },
428
- // Functions and parameters
429
- { tag: [/*@__PURE__*/tags.function(tags.variableName), tags.labelName], color: base07 },
430
- { tag: [/*@__PURE__*/tags.definition(tags.variableName)], color: base07 },
431
- // Constants and literals
432
- { tag: tags.number, color: base09 },
433
- { tag: tags.changed, color: base09 },
434
- { tag: tags.annotation, color: invalid, fontStyle: 'italic' },
435
- { tag: tags.modifier, color: base09, fontStyle: 'italic' },
436
- { tag: tags.self, color: base09 },
437
- { tag: [tags.color, /*@__PURE__*/tags.constant(tags.name), /*@__PURE__*/tags.standard(tags.name)], color: base09, fontWeight: 'bold' },
438
- { tag: [tags.atom, tags.bool, /*@__PURE__*/tags.special(tags.variableName)], color: base09 },
439
- // Strings and regex
440
- { tag: [tags.processingInstruction, tags.inserted], color: base08 },
441
- { tag: [/*@__PURE__*/tags.special(tags.string), tags.regexp], color: base08 },
442
- { tag: tags.string, color: base08 },
443
- // Punctuation and structure
444
- { tag: /*@__PURE__*/tags.definition(tags.typeName), color: base0A, fontWeight: 'bold' },
445
- // Comments and documentation
446
- { tag: tags.meta, color: base03 },
447
- { tag: tags.comment, fontStyle: 'italic', color: base03 },
448
- { tag: tags.docComment, fontStyle: 'italic', color: base03 },
449
- // HTML/XML elements
450
- { tag: [tags.tagName], color: base0D },
451
- { tag: [tags.attributeName], color: base0C },
452
- // Markdown and text formatting
453
- { tag: [tags.heading], fontWeight: 'bold', color: base0A },
454
- { tag: [tags.strong], fontWeight: 'bold', color: base05 },
455
- { tag: [tags.emphasis], fontStyle: 'italic', color: base06 },
456
- // Links and URLs
457
- { tag: [tags.link], color: base0A, fontWeight: '500', textDecoration: 'underline', textUnderlinePosition: 'under' },
458
- {
459
- tag: [tags.url],
460
- color: base0C,
461
- textDecoration: 'underline',
462
- textUnderlineOffset: '2px',
463
- },
464
- // Special states
465
- { tag: [tags.invalid], color: base01, textDecoration: 'underline wavy', borderBottom: `1px wavy ${invalid}` },
466
- { tag: [tags.strikethrough], color: invalid, textDecoration: 'line-through' },
467
- // Enhanced syntax highlighting
468
- { tag: /*@__PURE__*/tags.constant(tags.name), color: base09 },
469
- { tag: tags.deleted, color: invalid },
470
- { tag: tags.squareBracket, color: base0E },
471
- { tag: tags.angleBracket, color: base0E },
472
- // Additional specific styles
473
- { tag: tags.heading1, fontWeight: 'bold', color: base0A },
474
- { tag: /*@__PURE__*/tags.special(tags.heading1), fontWeight: 'bold', color: base0A },
475
- { tag: [tags.heading2, tags.heading3, tags.heading4], fontWeight: 'bold', color: base0A },
476
- { tag: [tags.heading5, tags.heading6], color: base0A },
477
- { tag: tags.monospace, color: base01 },
478
- { tag: [tags.contentSeparator], color: base0C },
479
- { tag: tags.quote, color: base03 },
480
- ]);
794
+ });
481
795
  /**
482
796
  * Combined Forest theme extension
483
797
  */
484
- const forest = [
485
- forestTheme,
486
- /*@__PURE__*/syntaxHighlighting(forestHighlightStyle),
487
- ];
798
+ const forest = theme.extension;
488
799
  /**
489
800
  * Forest merge revert styles configuration
490
801
  */
491
- const forestMergeStyles = {
492
- backgroundColor: darkBackground,
493
- borderColor: '#3e5059',
494
- buttonColor: base01,
495
- buttonHoverColor: '#2d3d47',
496
- };
802
+ const forestMergeStyles = theme.mergeStyles;
497
803
 
498
804
  export { applyMergeRevertStyles, forest, forestMergeStyles };