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