aboutsummaryrefslogtreecommitdiffstats
path: root/language-web/src/main/js/editor/EditorParent.ts
diff options
context:
space:
mode:
Diffstat (limited to 'language-web/src/main/js/editor/EditorParent.ts')
-rw-r--r--language-web/src/main/js/editor/EditorParent.ts200
1 files changed, 200 insertions, 0 deletions
diff --git a/language-web/src/main/js/editor/EditorParent.ts b/language-web/src/main/js/editor/EditorParent.ts
new file mode 100644
index 00000000..ee1323f6
--- /dev/null
+++ b/language-web/src/main/js/editor/EditorParent.ts
@@ -0,0 +1,200 @@
1import { styled } from '@mui/material/styles';
2
3/**
4 * Returns a squiggly underline background image encoded as a CSS `url()` data URI with Base64.
5 *
6 * Based on
7 * https://github.com/codemirror/lint/blob/f524b4a53b0183bb343ac1e32b228d28030d17af/src/lint.ts#L501
8 *
9 * @param color the color of the underline
10 * @returns the CSS `url()`
11 */
12function underline(color: string) {
13 const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="6" height="3">
14 <path d="m0 3 l2 -2 l1 0 l2 2 l1 0" stroke="${color}" fill="none" stroke-width=".7"/>
15 </svg>`;
16 const svgBase64 = window.btoa(svg);
17 return `url('data:image/svg+xml;base64,${svgBase64}')`;
18}
19
20export const EditorParent = styled('div')(({ theme }) => {
21 const codeMirrorLintStyle: Record<string, unknown> = {};
22 (['error', 'warning', 'info'] as const).forEach((severity) => {
23 const color = theme.palette[severity].main;
24 codeMirrorLintStyle[`.cm-diagnostic-${severity}`] = {
25 borderLeftColor: color,
26 };
27 codeMirrorLintStyle[`.cm-lintRange-${severity}`] = {
28 backgroundImage: underline(color),
29 };
30 });
31
32 return {
33 background: theme.palette.background.default,
34 '&, .cm-editor': {
35 height: '100%',
36 },
37 '.cm-scroller, .cm-tooltip-autocomplete, .cm-completionLabel, .cm-completionDetail': {
38 fontSize: 16,
39 fontFamily: '"JetBrains MonoVariable", "JetBrains Mono", monospace',
40 fontFeatureSettings: '"liga", "calt"',
41 fontWeight: 400,
42 letterSpacing: 0,
43 textRendering: 'optimizeLegibility',
44 },
45 '.cm-scroller': {
46 color: theme.palette.text.secondary,
47 },
48 '.cm-gutters': {
49 background: theme.palette.background.default,
50 color: theme.palette.text.disabled,
51 border: 'none',
52 },
53 '.cm-specialChar': {
54 color: theme.palette.secondary.main,
55 },
56 '.cm-activeLine': {
57 background: 'rgba(0, 0, 0, 0.3)',
58 },
59 '.cm-activeLineGutter': {
60 background: 'rgba(0, 0, 0, 0.3)',
61 color: theme.palette.text.primary,
62 },
63 '.cm-cursor, .cm-cursor-primary': {
64 borderColor: theme.palette.primary.main,
65 background: theme.palette.common.black,
66 },
67 '.cm-selectionBackground': {
68 background: '#3e4453',
69 },
70 '.cm-focused': {
71 outline: 'none',
72 '.cm-selectionBackground': {
73 background: '#3e4453',
74 },
75 },
76 '.cm-panels-top': {
77 color: theme.palette.text.secondary,
78 },
79 '.cm-panel': {
80 '&, & button, & input': {
81 fontFamily: '"Roboto","Helvetica","Arial",sans-serif',
82 },
83 background: theme.palette.background.paper,
84 borderTop: `1px solid ${theme.palette.divider}`,
85 'button[name="close"]': {
86 background: 'transparent',
87 color: theme.palette.text.secondary,
88 cursor: 'pointer',
89 },
90 },
91 '.cm-panel.cm-panel-lint': {
92 'button[name="close"]': {
93 // Close button interferes with scrollbar, so we better hide it.
94 // The panel can still be closed from the toolbar.
95 display: 'none',
96 },
97 ul: {
98 li: {
99 borderBottom: `1px solid ${theme.palette.divider}`,
100 cursor: 'pointer',
101 },
102 '[aria-selected]': {
103 background: '#3e4453',
104 color: theme.palette.text.primary,
105 },
106 '&:focus [aria-selected]': {
107 background: theme.palette.primary.main,
108 color: theme.palette.primary.contrastText,
109 },
110 },
111 },
112 '.cm-foldPlaceholder': {
113 background: theme.palette.background.paper,
114 borderColor: theme.palette.text.disabled,
115 color: theme.palette.text.secondary,
116 },
117 '.cmt-comment': {
118 fontStyle: 'italic',
119 color: theme.palette.text.disabled,
120 },
121 '.cmt-number': {
122 color: '#6188a6',
123 },
124 '.cmt-string': {
125 color: theme.palette.secondary.dark,
126 },
127 '.cmt-keyword': {
128 color: theme.palette.primary.main,
129 },
130 '.cmt-typeName, .cmt-macroName, .cmt-atom': {
131 color: theme.palette.text.primary,
132 },
133 '.cmt-variableName': {
134 color: '#c8ae9d',
135 },
136 '.cmt-problem-node': {
137 '&, & .cmt-variableName': {
138 color: theme.palette.text.secondary,
139 },
140 },
141 '.cmt-problem-unique': {
142 '&, & .cmt-variableName': {
143 color: theme.palette.text.primary,
144 },
145 },
146 '.cmt-problem-abstract, .cmt-problem-new': {
147 fontStyle: 'italic',
148 },
149 '.cmt-problem-containment': {
150 fontWeight: 700,
151 },
152 '.cmt-problem-error': {
153 '&, & .cmt-typeName': {
154 color: theme.palette.error.main,
155 },
156 },
157 '.cmt-problem-builtin': {
158 '&, & .cmt-typeName, & .cmt-atom, & .cmt-variableName': {
159 color: theme.palette.primary.main,
160 fontWeight: 400,
161 fontStyle: 'normal',
162 },
163 },
164 '.cm-tooltip-autocomplete': {
165 background: theme.palette.background.paper,
166 boxShadow: `0px 2px 4px -1px rgb(0 0 0 / 20%),
167 0px 4px 5px 0px rgb(0 0 0 / 14%),
168 0px 1px 10px 0px rgb(0 0 0 / 12%)`,
169 '.cm-completionIcon': {
170 color: theme.palette.text.secondary,
171 },
172 '.cm-completionLabel': {
173 color: theme.palette.text.primary,
174 },
175 '.cm-completionDetail': {
176 color: theme.palette.text.secondary,
177 fontStyle: 'normal',
178 },
179 '[aria-selected]': {
180 background: `${theme.palette.primary.main} !important`,
181 '.cm-completionIcon, .cm-completionLabel, .cm-completionDetail': {
182 color: theme.palette.primary.contrastText,
183 },
184 },
185 },
186 '.cm-completionIcon': {
187 width: 16,
188 padding: 0,
189 marginRight: '0.5em',
190 textAlign: 'center',
191 },
192 ...codeMirrorLintStyle,
193 '.cm-problem-write': {
194 background: 'rgba(255, 255, 128, 0.3)',
195 },
196 '.cm-problem-read': {
197 background: 'rgba(255, 255, 255, 0.15)',
198 },
199 };
200});