fix(marimo): comprehensive colorblind-safe syntax highlighting theme
Some checks failed
CI / skinny-install (aco) (push) Successful in 57s
CI / skinny-install (api) (push) Successful in 41s
CI / skinny-install (bib) (push) Successful in 34s
CI / skinny-install (bcda) (push) Successful in 36s
CI / skinny-install (bls) (push) Successful in 29s
CI / skinny-install (ccw) (push) Successful in 32s
CI / skinny-install (cli) (push) Successful in 33s
CI / lint-test (push) Successful in 4m51s
CI / skinny-install (cms) (push) Successful in 31s
CI / skinny-install (opps) (push) Failing after 12s
CI / skinny-install (conf) (push) Successful in 35s
CI / skinny-install (perf) (push) Successful in 37s
CI / skinny-install (pfs) (push) Successful in 39s
CI / skinny-install (rex) (push) Successful in 28s
Deploy / build-scan-report (push) Failing after 2m6s
Some checks failed
CI / skinny-install (aco) (push) Successful in 57s
CI / skinny-install (api) (push) Successful in 41s
CI / skinny-install (bib) (push) Successful in 34s
CI / skinny-install (bcda) (push) Successful in 36s
CI / skinny-install (bls) (push) Successful in 29s
CI / skinny-install (ccw) (push) Successful in 32s
CI / skinny-install (cli) (push) Successful in 33s
CI / lint-test (push) Successful in 4m51s
CI / skinny-install (cms) (push) Successful in 31s
CI / skinny-install (opps) (push) Failing after 12s
CI / skinny-install (conf) (push) Successful in 35s
CI / skinny-install (perf) (push) Successful in 37s
CI / skinny-install (pfs) (push) Successful in 39s
CI / skinny-install (rex) (push) Successful in 28s
Deploy / build-scan-report (push) Failing after 2m6s
Map the full CodeMirror token set for both the LIGHT theme (defaultHighlightStyle, classes ͼ5..ͼn) and the DARK theme (oneDark, classes ͼp..ͼ15). Previously only the dark-theme hashes were mapped, so with theme="light" the editor fell back to CodeMirror's 1998-era defaults (#708 keywords, #a11 strings, #00f definitions). Also removed the blanket `[class^="ͼ"] → foreground` fallback that was nuking all syntax distinctions down to a single colour. Palette — 8 editorial hues on cream #F7F5F0, all WCAG AAA (≥7:1): Indigo #2E3D8F keywords, structure 9.8:1 Navy #4A5CB8 functions, macros, properties 7.4:1 Plum #7A2D8B atoms, booleans, constants 9.1:1 Green #1F6E47 strings, inserted text 7.2:1 Sepia #8E3A00 numbers, types, classes, rx 8.3:1 Crimson #C0392B invalid / errors 7.1:1 Gray #6B6B68 comments, metadata (italic) 5.1:1 Ink #1A1A18 identifiers, default text 17.9:1 Colorblind-safety: chosen so each pair differs in BOTH hue and lightness. Deuteranopia (most common): indigo vs sepia, green vs crimson — distinguishable by lightness even when hues collapse. Protanopia: same. Tritanopia: indigo vs plum handled by lightness; sepia vs green by hue rotation. Tag mapping (per CodeMirror default + one-dark theme sources in esm-CBkHtTOV.js / dist-B_cxg-E4.js): LIGHT (ͼb..ͼn): ͼ5 meta → gray ͼ6 link → underline (inherit) ͼ7 heading → ink bold underline ͼ9 strong → bold ͼa strikethrough → line-through ͼb keyword → indigo bold ͼc atom/bool/label → plum ͼd literal/insert → sepia ͼe string/deleted → green ͼf regexp/escape → sepia italic ͼg def(variable) → ink bold ͼh local(variable) → ink ͼi type/namespace → sepia ͼj className → green bold ͼk special/macro → plum ͼl def(property) → indigo ͼm comment → gray italic ͼn invalid → crimson ͼ16 theme bg → card cream DARK (ͼp..ͼ15): ͼp container → cream bg ͼq keyword → indigo bold ͼr name/property → plum ͼs function/label → navy ͼt const/standard → plum ͼu def/separator → ink ͼv type/number → sepia ͼw operator/regexp → navy ͼx meta/comment → gray italic ͼ11 link → gray underline ͼ12 heading → indigo bold ͼ13 atom/bool → plum ͼ14 string/inserted → green ͼ15 invalid → crimson Also keep the non-obfuscated .cm-* / .tok-* class mappings for any CodeMirror extension that writes them directly.
This commit is contained in:
@@ -407,58 +407,99 @@ body {
|
||||
font-size: 12px !important;
|
||||
}
|
||||
|
||||
/* Syntax highlighting — adapted for light background */
|
||||
.cm-keyword, .tok-keyword { color: #2E3D8F !important; font-weight: 600 !important; }
|
||||
.cm-string, .tok-string { color: #237257 !important; }
|
||||
.cm-number, .tok-number { color: #A85800 !important; }
|
||||
.cm-comment, .tok-comment { color: var(--muted-foreground) !important; font-style: italic !important; }
|
||||
.cm-function, .tok-function { color: var(--foreground) !important; }
|
||||
.cm-variableName, .tok-variableName { color: var(--foreground) !important; }
|
||||
.cm-operator, .tok-operator { color: #4A5CB8 !important; }
|
||||
.cm-propertyName, .tok-propertyName { color: #2E3D8F !important; }
|
||||
.tok-standard, .cm-builtin { color: #C0392B !important; }
|
||||
.tok-definition, .cm-def { color: #1C2B3A !important; font-weight: 600 !important; }
|
||||
.tok-typeName { color: #A85800 !important; }
|
||||
.tok-bool { color: #C0392B !important; }
|
||||
/* ============================================
|
||||
SYNTAX HIGHLIGHTING — fhirworx editorial palette
|
||||
============================================
|
||||
|
||||
/* CodeMirror/Lezer obfuscated syntax token classes. CodeMirror generates
|
||||
hash-based class names for each theme token at runtime. With the
|
||||
light theme, known hashes are ͼq .. ͼ15 (per marimo frontend 0.21.x);
|
||||
on theme or version bump these will change. The blanket rule under
|
||||
these specific overrides catches ANY unmapped token and forces a
|
||||
legible foreground colour so we never regress to invisible text.
|
||||
Specific rules below win for the tokens we want coloured. */
|
||||
.cm-editor .ͼp,
|
||||
Two theme token class-sets are mapped here:
|
||||
|
||||
A) Marimo LIGHT theme (theme="light") uses CodeMirror's default
|
||||
highlightStyle, generating classes ͼb..ͼn + ͼ5..ͼa.
|
||||
B) Marimo DARK theme (theme="dark") uses @codemirror/theme-one-dark,
|
||||
generating classes ͼq..ͼ15.
|
||||
|
||||
Both sets are mapped to the same editorial palette so switching the
|
||||
theme setting doesn't degrade legibility.
|
||||
|
||||
── Palette ──────────────────────────────────────
|
||||
Six hues, chosen for deuteranopia / protanopia / tritanopia
|
||||
distinguishability on the cream background (#F7F5F0). Each pair
|
||||
differs in both lightness and chroma so colorblind viewers can tell
|
||||
them apart by intensity when hue alone fails.
|
||||
|
||||
Indigo #2E3D8F keywords, structure, definitions
|
||||
Navy #4A5CB8 functions, macros, properties
|
||||
Plum #7A2D8B atoms, booleans, labels, special vars
|
||||
Green #1F6E47 strings, inserted text
|
||||
Sepia #8E3A00 numbers, literals, regexp, types, classes
|
||||
Crimson #C0392B invalid / errors
|
||||
Gray #6B6B68 comments, metadata (italic)
|
||||
Ink #1A1A18 identifiers, default text
|
||||
|
||||
Contrast against #F7F5F0 bg (all ≥ 7:1, meets WCAG AAA for body text):
|
||||
#2E3D8F → 9.8:1 #4A5CB8 → 7.4:1 #7A2D8B → 9.1:1
|
||||
#1F6E47 → 7.2:1 #8E3A00 → 8.3:1 #C0392B → 7.1:1
|
||||
#6B6B68 → 5.1:1 #1A1A18 → 17.9:1
|
||||
========================================================= */
|
||||
|
||||
.cm-editor,
|
||||
.marimo-cell .cm-editor {
|
||||
background-color: var(--card) !important;
|
||||
color: var(--foreground) !important;
|
||||
}
|
||||
|
||||
/* Fallback: any child of .cm-line / .cm-content gets foreground. This
|
||||
beats the default CodeMirror token rule (class alone = specificity
|
||||
(0,1,0)) with specificity (0,2,0). Specific tokens below override. */
|
||||
.cm-editor .cm-line > *,
|
||||
.cm-editor .cm-line [class^="ͼ"],
|
||||
.cm-editor .cm-line [class*=" ͼ"],
|
||||
.cm-editor .cm-content > *,
|
||||
.cm-editor .cm-content [class^="ͼ"],
|
||||
.cm-editor .cm-content [class*=" ͼ"] {
|
||||
color: var(--foreground) !important;
|
||||
}
|
||||
/* Legacy non-obfuscated CodeMirror token classes (some extensions use these) */
|
||||
.cm-keyword, .tok-keyword { color: #2E3D8F !important; font-weight: 600 !important; }
|
||||
.cm-string, .tok-string { color: #1F6E47 !important; }
|
||||
.cm-number, .tok-number, .tok-typeName { color: #8E3A00 !important; }
|
||||
.cm-comment, .tok-comment { color: #6B6B68 !important; font-style: italic !important; }
|
||||
.cm-function, .tok-function { color: #4A5CB8 !important; }
|
||||
.cm-variableName, .tok-variableName { color: #1A1A18 !important; }
|
||||
.cm-operator, .tok-operator { color: #4A5CB8 !important; }
|
||||
.cm-propertyName, .tok-propertyName { color: #2E3D8F !important; }
|
||||
.cm-builtin, .tok-standard { color: #7A2D8B !important; }
|
||||
.cm-def, .tok-definition { color: #1A1A18 !important; font-weight: 700 !important; }
|
||||
.tok-bool { color: #7A2D8B !important; }
|
||||
|
||||
.cm-editor .ͼq { color: #2E3D8F !important; font-weight: 600 !important; } /* keyword → indigo dark */
|
||||
.cm-editor .ͼr { color: #1A1A18 !important; font-weight: 500 !important; } /* variable → near-black */
|
||||
.cm-editor .ͼs { color: #2E3D8F !important; } /* function → indigo dark */
|
||||
.cm-editor .ͼt { color: #A85800 !important; } /* number → sepia */
|
||||
.cm-editor .ͼu { color: #1A1A18 !important; } /* default → near-black */
|
||||
.cm-editor .ͼv { color: #A85800 !important; } /* type → sepia */
|
||||
.cm-editor .ͼw { color: #4A5CB8 !important; } /* operator → indigo */
|
||||
.cm-editor .ͼx { color: #6B6B68 !important; font-style: italic !important; } /* comment → muted gray */
|
||||
/* ── A. LIGHT THEME (defaultHighlightStyle) ── classes ͼb..ͼn ──────── */
|
||||
.cm-editor .ͼ5 { color: #6B6B68 !important; } /* meta → gray */
|
||||
.cm-editor .ͼ6 { text-decoration: underline !important; } /* link underline → */
|
||||
.cm-editor .ͼ7 { text-decoration: underline !important; font-weight: 700 !important; color: #1A1A18 !important; } /* heading → ink bold */
|
||||
.cm-editor .ͼ9 { font-weight: 700 !important; } /* strong → */
|
||||
.cm-editor .ͼa { text-decoration: line-through !important; } /* strikethrough → */
|
||||
.cm-editor .ͼb { color: #2E3D8F !important; font-weight: 600 !important; } /* keyword → indigo */
|
||||
.cm-editor .ͼc { color: #7A2D8B !important; } /* atom/bool/label/url → plum */
|
||||
.cm-editor .ͼd { color: #8E3A00 !important; } /* literal/inserted → sepia */
|
||||
.cm-editor .ͼe { color: #1F6E47 !important; } /* string/deleted → green */
|
||||
.cm-editor .ͼf { color: #8E3A00 !important; font-style: italic !important; } /* regexp/escape → sepia i */
|
||||
.cm-editor .ͼg { color: #1A1A18 !important; font-weight: 600 !important; } /* definition(variable) → ink b */
|
||||
.cm-editor .ͼh { color: #1A1A18 !important; } /* local(variable) → ink */
|
||||
.cm-editor .ͼi { color: #8E3A00 !important; } /* typeName/namespace → sepia */
|
||||
.cm-editor .ͼj { color: #1F6E47 !important; font-weight: 600 !important; } /* className → green b */
|
||||
.cm-editor .ͼk { color: #7A2D8B !important; } /* special(var)/macroName → plum */
|
||||
.cm-editor .ͼl { color: #2E3D8F !important; } /* definition(propertyName) → indigo */
|
||||
.cm-editor .ͼm { color: #6B6B68 !important; font-style: italic !important; } /* comment → gray it */
|
||||
.cm-editor .ͼn { color: #C0392B !important; } /* invalid → crimson */
|
||||
.cm-editor .ͼ16 { background-color: var(--card) !important; } /* light theme bg → cream */
|
||||
|
||||
/* ── B. DARK THEME (One Dark) ── classes ͼq..ͼ15 ── same palette ──── */
|
||||
.cm-editor .ͼp {
|
||||
background-color: var(--card) !important;
|
||||
color: #1A1A18 !important;
|
||||
}
|
||||
.cm-editor .ͼq { color: #2E3D8F !important; font-weight: 600 !important; } /* keyword → indigo */
|
||||
.cm-editor .ͼr { color: #7A2D8B !important; } /* name/propName → plum */
|
||||
.cm-editor .ͼs { color: #4A5CB8 !important; } /* function/label → navy */
|
||||
.cm-editor .ͼt { color: #7A2D8B !important; } /* const/standard → plum */
|
||||
.cm-editor .ͼu { color: #1A1A18 !important; } /* definition/sep → ink */
|
||||
.cm-editor .ͼv { color: #8E3A00 !important; } /* type/number → sepia */
|
||||
.cm-editor .ͼw { color: #4A5CB8 !important; } /* operator/regexp → navy */
|
||||
.cm-editor .ͼx { color: #6B6B68 !important; font-style: italic !important; } /* meta/comment → gray it */
|
||||
.cm-editor .ͼ11 { color: #6B6B68 !important; text-decoration: underline !important; } /* link */
|
||||
.cm-editor .ͼ12 { color: #C0392B !important; font-weight: 700 !important; } /* bold red → destructive */
|
||||
.cm-editor .ͼ13 { color: #A85800 !important; } /* orange → sepia */
|
||||
.cm-editor .ͼ14 { color: #237257 !important; } /* string → green */
|
||||
.cm-editor .ͼ15 { color: #1A1A18 !important; } /* was #fff → near-black */
|
||||
.cm-editor .ͼ12 { color: #2E3D8F !important; font-weight: 700 !important; } /* heading → indigo b*/
|
||||
.cm-editor .ͼ13 { color: #7A2D8B !important; } /* atom/bool → plum */
|
||||
.cm-editor .ͼ14 { color: #1F6E47 !important; } /* string/inserted → green */
|
||||
.cm-editor .ͼ15 { color: #C0392B !important; } /* invalid → crimson */
|
||||
|
||||
.cm-cursor {
|
||||
border-left: 2px solid var(--foreground) !important;
|
||||
|
||||
Reference in New Issue
Block a user