@motionscript/code 0.1.0-alpha.3 → 0.1.0-alpha.5
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.
- package/CHANGELOG.md +45 -0
- package/LICENSE +201 -201
- package/NOTICE +48 -0
- package/README.md +161 -108
- package/dist/browser/THIRD_PARTY_LICENSES.txt +431 -0
- package/dist/browser/index.js +7 -6
- package/dist/browser/index.js.map +3 -3
- package/dist/browser/manifest.json +84 -2
- package/dist/code-range.d.ts +6 -0
- package/dist/code-range.d.ts.map +1 -1
- package/dist/code-range.js +8 -0
- package/dist/code-range.js.map +1 -1
- package/dist/diff.d.ts +14 -0
- package/dist/diff.d.ts.map +1 -1
- package/dist/diff.js +134 -2
- package/dist/diff.js.map +1 -1
- package/dist/engine.d.ts +1 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +1 -1
- package/dist/engine.js.map +1 -1
- package/dist/highlight.d.ts +10 -2
- package/dist/highlight.d.ts.map +1 -1
- package/dist/highlight.js +40 -6
- package/dist/highlight.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/layout.js.map +1 -1
- package/dist/node.d.ts +42 -7
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +174 -47
- package/dist/node.js.map +1 -1
- package/dist/nodes.js.map +1 -1
- package/dist/render.d.ts +6 -1
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +59 -0
- package/dist/render.js.map +1 -1
- package/dist/style.d.ts +3 -3
- package/dist/style.d.ts.map +1 -1
- package/dist/style.js +10 -6
- package/dist/style.js.map +1 -1
- package/dist/tokens.d.ts.map +1 -1
- package/dist/tokens.js +5 -1
- package/dist/tokens.js.map +1 -1
- package/dist/transitions.d.ts +19 -1
- package/dist/transitions.d.ts.map +1 -1
- package/dist/transitions.js.map +1 -1
- package/package.json +7 -5
- package/registry.json +6 -6
- package/src/code-range.ts +165 -156
- package/src/diff.ts +351 -216
- package/src/engine.ts +21 -21
- package/src/highlight.ts +340 -291
- package/src/index.ts +3 -3
- package/src/layout.ts +157 -157
- package/src/node.ts +1038 -904
- package/src/nodes.ts +18 -18
- package/src/render.ts +312 -247
- package/src/style.ts +255 -251
- package/src/tokens.ts +79 -75
- package/src/transitions.ts +204 -184
package/src/style.ts
CHANGED
|
@@ -1,251 +1,255 @@
|
|
|
1
|
-
import { Highlighter, Tag, tagHighlighter, tags as t } from "@lezer/highlight";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* A single style rule: map one or more Lezer highlight {@link Tag}s to a color.
|
|
5
|
-
* This mirrors a `@codemirror/language` HighlightStyle entry, but instead of
|
|
6
|
-
* emitting CSS class names it carries the color directly — we render to a canvas,
|
|
7
|
-
* not the DOM, so there is no stylesheet to resolve against.
|
|
8
|
-
*/
|
|
9
|
-
export interface CodeStyleRule {
|
|
10
|
-
tag: Tag | readonly Tag[];
|
|
11
|
-
color: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* A code theme: an ordered list of tag→color rules plus a fallback color for any
|
|
16
|
-
* text the parser produces no highlight tag for (operators, punctuation, plain
|
|
17
|
-
* identifiers in some grammars, etc.). Pass a custom one via the Code node's
|
|
18
|
-
* `theme` prop to recolor highlighting without touching the highlighter wiring.
|
|
19
|
-
*
|
|
20
|
-
* @remarks
|
|
21
|
-
* Later rules win when several match the same tag, matching how
|
|
22
|
-
* `@lezer/highlight`'s {@link tagHighlighter} resolves precedence.
|
|
23
|
-
*/
|
|
24
|
-
export interface CodeHighlightStyle {
|
|
25
|
-
/** Stable name, used
|
|
26
|
-
name: string;
|
|
27
|
-
/** Color applied to text with no matching tag. */
|
|
28
|
-
defaultColor: string;
|
|
29
|
-
rules: CodeStyleRule[];
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Motion Canvas's default highlight palette (a Nord-derived theme), ported from
|
|
34
|
-
* `@motion-canvas/2d`'s DefaultHighlightStyle so highlighting matches Motion
|
|
35
|
-
* Canvas token-for-token. Colors and tag groupings are kept identical; only the
|
|
36
|
-
* shape changes (color strings in place of CSS rules).
|
|
37
|
-
*/
|
|
38
|
-
export const DefaultHighlightStyle: CodeHighlightStyle = {
|
|
39
|
-
name: "motion-canvas-default",
|
|
40
|
-
defaultColor: "#d8dee9",
|
|
41
|
-
rules: [
|
|
42
|
-
{ tag: t.keyword, color: "#5e81ac" },
|
|
43
|
-
{ tag: [t.name, t.deleted, t.character, t.propertyName, t.macroName], color: "#88c0d0" },
|
|
44
|
-
{ tag: [t.variableName], color: "#8fbcbb" },
|
|
45
|
-
{ tag: [t.function(t.variableName)], color: "#8fbcbb" },
|
|
46
|
-
{ tag: [t.labelName], color: "#81a1c1" },
|
|
47
|
-
{ tag: [t.color, t.constant(t.name), t.standard(t.name)], color: "#5e81ac" },
|
|
48
|
-
{ tag: [t.definition(t.name), t.separator], color: "#a3be8c" },
|
|
49
|
-
{ tag: [t.brace], color: "#8fbcbb" },
|
|
50
|
-
{ tag: [t.annotation], color: "#d30102" },
|
|
51
|
-
{ tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace], color: "#b48ead" },
|
|
52
|
-
{ tag: [t.typeName, t.className], color: "#ECEFF4" },
|
|
53
|
-
{ tag: [t.operator, t.operatorKeyword], color: "#a3be8c" },
|
|
54
|
-
{ tag: [t.tagName], color: "#b48ead" },
|
|
55
|
-
{ tag: [t.squareBracket], color: "#ECEFF4" },
|
|
56
|
-
{ tag: [t.angleBracket], color: "#ECEFF4" },
|
|
57
|
-
{ tag: [t.attributeName], color: "#eceff4" },
|
|
58
|
-
{ tag: [t.regexp], color: "#5e81ac" },
|
|
59
|
-
{ tag: [t.quote], color: "#b48ead" },
|
|
60
|
-
{ tag: [t.string], color: "#a3be8c" },
|
|
61
|
-
{ tag: t.link, color: "#a3be8c" },
|
|
62
|
-
{ tag: [t.url, t.escape, t.special(t.string)], color: "#8fbcbb" },
|
|
63
|
-
{ tag: [t.meta], color: "#88c0d0" },
|
|
64
|
-
{ tag: [t.monospace], color: "#d8dee9" },
|
|
65
|
-
{ tag: [t.comment], color: "#4c566a" },
|
|
66
|
-
{ tag: t.strong, color: "#5e81ac" },
|
|
67
|
-
{ tag: t.emphasis, color: "#5e81ac" },
|
|
68
|
-
{ tag: t.heading, color: "#5e81ac" },
|
|
69
|
-
{ tag: t.special(t.heading1), color: "#5e81ac" },
|
|
70
|
-
{ tag: t.heading1, color: "#5e81ac" },
|
|
71
|
-
{ tag: [t.heading2, t.heading3, t.heading4], color: "#5e81ac" },
|
|
72
|
-
{ tag: [t.heading5, t.heading6], color: "#5e81ac" },
|
|
73
|
-
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: "#d08770" },
|
|
74
|
-
{ tag: [t.processingInstruction, t.inserted], color: "#8fbcbb" },
|
|
75
|
-
{ tag: [t.contentSeparator], color: "#ebcb8b" },
|
|
76
|
-
{ tag: t.invalid, color: "#434c5e" },
|
|
77
|
-
],
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* GitHub Dark highlight palette, adapted from `@uiw/codemirror-theme-github`.
|
|
82
|
-
* `defaultColor` is GitHub's editor foreground (`#c9d1d9`), used for any text the
|
|
83
|
-
* parser tags don't cover. DOM-only style props (backgroundColor, textDecoration,
|
|
84
|
-
* fontWeight, fontStyle) are dropped — we only color tokens on the canvas.
|
|
85
|
-
*/
|
|
86
|
-
export const GithubDarkStyle: CodeHighlightStyle = {
|
|
87
|
-
name: "github-dark",
|
|
88
|
-
defaultColor: "#c9d1d9",
|
|
89
|
-
rules: [
|
|
90
|
-
{ tag: [t.standard(t.tagName), t.tagName], color: "#7ee787" },
|
|
91
|
-
{ tag: [t.comment, t.bracket], color: "#8b949e" },
|
|
92
|
-
{ tag: [t.className, t.propertyName], color: "#d2a8ff" },
|
|
93
|
-
{ tag: [t.variableName, t.attributeName, t.number, t.operator], color: "#79c0ff" },
|
|
94
|
-
{ tag: [t.keyword, t.typeName, t.typeOperator], color: "#ff7b72" },
|
|
95
|
-
{ tag: [t.string, t.meta, t.regexp], color: "#a5d6ff" },
|
|
96
|
-
{ tag: [t.name, t.quote], color: "#7ee787" },
|
|
97
|
-
{ tag: [t.heading, t.strong], color: "#d2a8ff" },
|
|
98
|
-
{ tag: [t.emphasis], color: "#d2a8ff" },
|
|
99
|
-
{ tag: [t.deleted], color: "#ffdcd7" },
|
|
100
|
-
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: "#ffab70" },
|
|
101
|
-
{ tag: t.invalid, color: "#f97583" },
|
|
102
|
-
],
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* GitHub Light highlight palette, adapted from `@uiw/codemirror-theme-github`.
|
|
107
|
-
* `defaultColor` is GitHub's editor foreground (`#24292e`). See {@link GithubDarkStyle}
|
|
108
|
-
* for the note on dropped DOM-only style props.
|
|
109
|
-
*/
|
|
110
|
-
export const GithubLightStyle: CodeHighlightStyle = {
|
|
111
|
-
name: "github-light",
|
|
112
|
-
defaultColor: "#24292e",
|
|
113
|
-
rules: [
|
|
114
|
-
{ tag: [t.standard(t.tagName), t.tagName], color: "#116329" },
|
|
115
|
-
{ tag: [t.comment, t.bracket], color: "#6a737d" },
|
|
116
|
-
{ tag: [t.className, t.propertyName], color: "#6f42c1" },
|
|
117
|
-
{ tag: [t.variableName, t.attributeName, t.number, t.operator], color: "#005cc5" },
|
|
118
|
-
{ tag: [t.keyword, t.typeName, t.typeOperator], color: "#d73a49" },
|
|
119
|
-
{ tag: [t.string, t.meta, t.regexp], color: "#032f62" },
|
|
120
|
-
{ tag: [t.name, t.quote], color: "#22863a" },
|
|
121
|
-
{ tag: [t.heading, t.strong], color: "#24292e" },
|
|
122
|
-
{ tag: [t.emphasis], color: "#24292e" },
|
|
123
|
-
{ tag: [t.deleted], color: "#b31d28" },
|
|
124
|
-
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: "#e36209" },
|
|
125
|
-
{ tag: [t.url, t.escape, t.regexp, t.link], color: "#032f62" },
|
|
126
|
-
{ tag: t.invalid, color: "#cb2431" },
|
|
127
|
-
],
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* VS Code Dark+ highlight palette, adapted from the `@uiw/codemirror-theme-vscode`
|
|
132
|
-
* snippet. `defaultColor` is VS Code's editor foreground (`#9cdcfe`). DOM-only
|
|
133
|
-
* style props are dropped; later rules win, matching {@link tagHighlighter}.
|
|
134
|
-
*/
|
|
135
|
-
export const VscodeDarkStyle: CodeHighlightStyle = {
|
|
136
|
-
name: "vscode-dark",
|
|
137
|
-
defaultColor: "#9cdcfe",
|
|
138
|
-
rules: [
|
|
139
|
-
{
|
|
140
|
-
tag: [
|
|
141
|
-
t.keyword, t.operatorKeyword, t.modifier, t.color,
|
|
142
|
-
t.constant(t.name), t.standard(t.name), t.standard(t.tagName),
|
|
143
|
-
t.special(t.brace), t.atom, t.bool, t.special(t.variableName),
|
|
144
|
-
],
|
|
145
|
-
color: "#569cd6",
|
|
146
|
-
},
|
|
147
|
-
{ tag: [t.controlKeyword, t.moduleKeyword], color: "#c586c0" },
|
|
148
|
-
{
|
|
149
|
-
tag: [
|
|
150
|
-
t.name, t.deleted, t.character, t.macroName, t.propertyName,
|
|
151
|
-
t.variableName, t.labelName, t.definition(t.name),
|
|
152
|
-
],
|
|
153
|
-
color: "#9cdcfe",
|
|
154
|
-
},
|
|
155
|
-
{ tag: t.heading, color: "#9cdcfe" },
|
|
156
|
-
{ tag: [t.typeName, t.className, t.tagName, t.changed, t.annotation, t.self, t.namespace], color: "#4ec9b0" },
|
|
157
|
-
{ tag: [t.function(t.variableName), t.function(t.propertyName)], color: "#dcdcaa" },
|
|
158
|
-
{ tag: [t.number], color: "#b5cea8" },
|
|
159
|
-
{ tag: [t.operator, t.punctuation, t.separator, t.url, t.escape], color: "#d4d4d4" },
|
|
160
|
-
{ tag: [t.regexp], color: "#d16969" },
|
|
161
|
-
{ tag: [t.special(t.string), t.processingInstruction, t.string, t.inserted], color: "#ce9178" },
|
|
162
|
-
{ tag: [t.angleBracket], color: "#808080" },
|
|
163
|
-
{ tag: [t.meta, t.comment], color: "#6a9955" },
|
|
164
|
-
{ tag: t.link, color: "#6a9955" },
|
|
165
|
-
{ tag: t.invalid, color: "#ff0000" },
|
|
166
|
-
],
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* VS Code Light+ highlight palette, adapted from the `@uiw/codemirror-theme-vscode`
|
|
171
|
-
* snippet. `defaultColor` is VS Code's editor foreground (`#383a42`). See
|
|
172
|
-
* {@link VscodeDarkStyle} for the note on dropped DOM-only style props.
|
|
173
|
-
*/
|
|
174
|
-
export const VscodeLightStyle: CodeHighlightStyle = {
|
|
175
|
-
name: "vscode-light",
|
|
176
|
-
defaultColor: "#383a42",
|
|
177
|
-
rules: [
|
|
178
|
-
{
|
|
179
|
-
tag: [
|
|
180
|
-
t.keyword, t.operatorKeyword, t.modifier, t.color,
|
|
181
|
-
t.constant(t.name), t.standard(t.name), t.standard(t.tagName),
|
|
182
|
-
t.special(t.brace), t.atom, t.bool, t.special(t.variableName),
|
|
183
|
-
],
|
|
184
|
-
color: "#0000ff",
|
|
185
|
-
},
|
|
186
|
-
{ tag: [t.moduleKeyword, t.controlKeyword], color: "#af00db" },
|
|
187
|
-
{
|
|
188
|
-
tag: [
|
|
189
|
-
t.name, t.deleted, t.character, t.macroName, t.propertyName,
|
|
190
|
-
t.variableName, t.labelName, t.definition(t.name),
|
|
191
|
-
],
|
|
192
|
-
color: "#0070c1",
|
|
193
|
-
},
|
|
194
|
-
{ tag: t.heading, color: "#0070c1" },
|
|
195
|
-
{ tag: [t.typeName, t.className, t.tagName, t.changed, t.annotation, t.self, t.namespace], color: "#267f99" },
|
|
196
|
-
{ tag: [t.function(t.variableName), t.function(t.propertyName)], color: "#795e26" },
|
|
197
|
-
{ tag: [t.number], color: "#098658" },
|
|
198
|
-
{ tag: [t.operator, t.punctuation, t.separator, t.url, t.escape], color: "#383a42" },
|
|
199
|
-
{ tag: [t.regexp], color: "#af00db" },
|
|
200
|
-
{ tag: [t.special(t.string), t.processingInstruction, t.string, t.inserted], color: "#a31515" },
|
|
201
|
-
{ tag: [t.angleBracket], color: "#383a42" },
|
|
202
|
-
{ tag: [t.meta, t.comment], color: "#008000" },
|
|
203
|
-
{ tag: t.link, color: "#4078f2" },
|
|
204
|
-
{ tag: t.invalid, color: "#e45649" },
|
|
205
|
-
],
|
|
206
|
-
};
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* The built-in themes, keyed by their string name. {@link CodeThemeName} is the
|
|
210
|
-
* union of these keys — pass one of those strings (or any {@link CodeHighlightStyle}
|
|
211
|
-
* object) to a Code node's `theme` prop.
|
|
212
|
-
*/
|
|
213
|
-
export const BUILTIN_THEMES = {
|
|
214
|
-
// Literal keys (not computed from `.name`) so `keyof` yields a string-literal
|
|
215
|
-
// union for CodeThemeName; these must stay in sync with each style's `name`.
|
|
216
|
-
"motion-canvas-default": DefaultHighlightStyle,
|
|
217
|
-
"github-dark": GithubDarkStyle,
|
|
218
|
-
"github-light": GithubLightStyle,
|
|
219
|
-
"vscode-dark": VscodeDarkStyle,
|
|
220
|
-
"vscode-light": VscodeLightStyle,
|
|
221
|
-
} satisfies Record<string, CodeHighlightStyle>;
|
|
222
|
-
|
|
223
|
-
/** Names of the built-in themes, e.g. `'github-dark' | 'github-light'`. */
|
|
224
|
-
export type CodeThemeName = keyof typeof BUILTIN_THEMES;
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* What a Code node's `theme` prop accepts: a built-in theme name (with
|
|
228
|
-
* autocomplete), any other registered theme name, or a {@link CodeHighlightStyle}
|
|
229
|
-
* object passed inline. The `string & {}` keeps the literal-name suggestions while
|
|
230
|
-
* still allowing arbitrary registered names.
|
|
231
|
-
*/
|
|
232
|
-
export type CodeTheme = CodeThemeName | (string & {}) | CodeHighlightStyle;
|
|
233
|
-
|
|
234
|
-
// Cache one compiled Highlighter per style
|
|
235
|
-
// matcher; the parsed result is pure data so it's safe to share across Code nodes.
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
);
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
}
|
|
1
|
+
import { Highlighter, Tag, tagHighlighter, tags as t } from "@lezer/highlight";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A single style rule: map one or more Lezer highlight {@link Tag}s to a color.
|
|
5
|
+
* This mirrors a `@codemirror/language` HighlightStyle entry, but instead of
|
|
6
|
+
* emitting CSS class names it carries the color directly — we render to a canvas,
|
|
7
|
+
* not the DOM, so there is no stylesheet to resolve against.
|
|
8
|
+
*/
|
|
9
|
+
export interface CodeStyleRule {
|
|
10
|
+
tag: Tag | readonly Tag[];
|
|
11
|
+
color: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A code theme: an ordered list of tag→color rules plus a fallback color for any
|
|
16
|
+
* text the parser produces no highlight tag for (operators, punctuation, plain
|
|
17
|
+
* identifiers in some grammars, etc.). Pass a custom one via the Code node's
|
|
18
|
+
* `theme` prop to recolor highlighting without touching the highlighter wiring.
|
|
19
|
+
*
|
|
20
|
+
* @remarks
|
|
21
|
+
* Later rules win when several match the same tag, matching how
|
|
22
|
+
* `@lezer/highlight`'s {@link tagHighlighter} resolves precedence.
|
|
23
|
+
*/
|
|
24
|
+
export interface CodeHighlightStyle {
|
|
25
|
+
/** Stable name, used to register the style and to refer to it from a `theme` prop. */
|
|
26
|
+
name: string;
|
|
27
|
+
/** Color applied to text with no matching tag. */
|
|
28
|
+
defaultColor: string;
|
|
29
|
+
rules: CodeStyleRule[];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Motion Canvas's default highlight palette (a Nord-derived theme), ported from
|
|
34
|
+
* `@motion-canvas/2d`'s DefaultHighlightStyle so highlighting matches Motion
|
|
35
|
+
* Canvas token-for-token. Colors and tag groupings are kept identical; only the
|
|
36
|
+
* shape changes (color strings in place of CSS rules).
|
|
37
|
+
*/
|
|
38
|
+
export const DefaultHighlightStyle: CodeHighlightStyle = {
|
|
39
|
+
name: "motion-canvas-default",
|
|
40
|
+
defaultColor: "#d8dee9",
|
|
41
|
+
rules: [
|
|
42
|
+
{ tag: t.keyword, color: "#5e81ac" },
|
|
43
|
+
{ tag: [t.name, t.deleted, t.character, t.propertyName, t.macroName], color: "#88c0d0" },
|
|
44
|
+
{ tag: [t.variableName], color: "#8fbcbb" },
|
|
45
|
+
{ tag: [t.function(t.variableName)], color: "#8fbcbb" },
|
|
46
|
+
{ tag: [t.labelName], color: "#81a1c1" },
|
|
47
|
+
{ tag: [t.color, t.constant(t.name), t.standard(t.name)], color: "#5e81ac" },
|
|
48
|
+
{ tag: [t.definition(t.name), t.separator], color: "#a3be8c" },
|
|
49
|
+
{ tag: [t.brace], color: "#8fbcbb" },
|
|
50
|
+
{ tag: [t.annotation], color: "#d30102" },
|
|
51
|
+
{ tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace], color: "#b48ead" },
|
|
52
|
+
{ tag: [t.typeName, t.className], color: "#ECEFF4" },
|
|
53
|
+
{ tag: [t.operator, t.operatorKeyword], color: "#a3be8c" },
|
|
54
|
+
{ tag: [t.tagName], color: "#b48ead" },
|
|
55
|
+
{ tag: [t.squareBracket], color: "#ECEFF4" },
|
|
56
|
+
{ tag: [t.angleBracket], color: "#ECEFF4" },
|
|
57
|
+
{ tag: [t.attributeName], color: "#eceff4" },
|
|
58
|
+
{ tag: [t.regexp], color: "#5e81ac" },
|
|
59
|
+
{ tag: [t.quote], color: "#b48ead" },
|
|
60
|
+
{ tag: [t.string], color: "#a3be8c" },
|
|
61
|
+
{ tag: t.link, color: "#a3be8c" },
|
|
62
|
+
{ tag: [t.url, t.escape, t.special(t.string)], color: "#8fbcbb" },
|
|
63
|
+
{ tag: [t.meta], color: "#88c0d0" },
|
|
64
|
+
{ tag: [t.monospace], color: "#d8dee9" },
|
|
65
|
+
{ tag: [t.comment], color: "#4c566a" },
|
|
66
|
+
{ tag: t.strong, color: "#5e81ac" },
|
|
67
|
+
{ tag: t.emphasis, color: "#5e81ac" },
|
|
68
|
+
{ tag: t.heading, color: "#5e81ac" },
|
|
69
|
+
{ tag: t.special(t.heading1), color: "#5e81ac" },
|
|
70
|
+
{ tag: t.heading1, color: "#5e81ac" },
|
|
71
|
+
{ tag: [t.heading2, t.heading3, t.heading4], color: "#5e81ac" },
|
|
72
|
+
{ tag: [t.heading5, t.heading6], color: "#5e81ac" },
|
|
73
|
+
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: "#d08770" },
|
|
74
|
+
{ tag: [t.processingInstruction, t.inserted], color: "#8fbcbb" },
|
|
75
|
+
{ tag: [t.contentSeparator], color: "#ebcb8b" },
|
|
76
|
+
{ tag: t.invalid, color: "#434c5e" },
|
|
77
|
+
],
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* GitHub Dark highlight palette, adapted from `@uiw/codemirror-theme-github`.
|
|
82
|
+
* `defaultColor` is GitHub's editor foreground (`#c9d1d9`), used for any text the
|
|
83
|
+
* parser tags don't cover. DOM-only style props (backgroundColor, textDecoration,
|
|
84
|
+
* fontWeight, fontStyle) are dropped — we only color tokens on the canvas.
|
|
85
|
+
*/
|
|
86
|
+
export const GithubDarkStyle: CodeHighlightStyle = {
|
|
87
|
+
name: "github-dark",
|
|
88
|
+
defaultColor: "#c9d1d9",
|
|
89
|
+
rules: [
|
|
90
|
+
{ tag: [t.standard(t.tagName), t.tagName], color: "#7ee787" },
|
|
91
|
+
{ tag: [t.comment, t.bracket], color: "#8b949e" },
|
|
92
|
+
{ tag: [t.className, t.propertyName], color: "#d2a8ff" },
|
|
93
|
+
{ tag: [t.variableName, t.attributeName, t.number, t.operator], color: "#79c0ff" },
|
|
94
|
+
{ tag: [t.keyword, t.typeName, t.typeOperator], color: "#ff7b72" },
|
|
95
|
+
{ tag: [t.string, t.meta, t.regexp], color: "#a5d6ff" },
|
|
96
|
+
{ tag: [t.name, t.quote], color: "#7ee787" },
|
|
97
|
+
{ tag: [t.heading, t.strong], color: "#d2a8ff" },
|
|
98
|
+
{ tag: [t.emphasis], color: "#d2a8ff" },
|
|
99
|
+
{ tag: [t.deleted], color: "#ffdcd7" },
|
|
100
|
+
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: "#ffab70" },
|
|
101
|
+
{ tag: t.invalid, color: "#f97583" },
|
|
102
|
+
],
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* GitHub Light highlight palette, adapted from `@uiw/codemirror-theme-github`.
|
|
107
|
+
* `defaultColor` is GitHub's editor foreground (`#24292e`). See {@link GithubDarkStyle}
|
|
108
|
+
* for the note on dropped DOM-only style props.
|
|
109
|
+
*/
|
|
110
|
+
export const GithubLightStyle: CodeHighlightStyle = {
|
|
111
|
+
name: "github-light",
|
|
112
|
+
defaultColor: "#24292e",
|
|
113
|
+
rules: [
|
|
114
|
+
{ tag: [t.standard(t.tagName), t.tagName], color: "#116329" },
|
|
115
|
+
{ tag: [t.comment, t.bracket], color: "#6a737d" },
|
|
116
|
+
{ tag: [t.className, t.propertyName], color: "#6f42c1" },
|
|
117
|
+
{ tag: [t.variableName, t.attributeName, t.number, t.operator], color: "#005cc5" },
|
|
118
|
+
{ tag: [t.keyword, t.typeName, t.typeOperator], color: "#d73a49" },
|
|
119
|
+
{ tag: [t.string, t.meta, t.regexp], color: "#032f62" },
|
|
120
|
+
{ tag: [t.name, t.quote], color: "#22863a" },
|
|
121
|
+
{ tag: [t.heading, t.strong], color: "#24292e" },
|
|
122
|
+
{ tag: [t.emphasis], color: "#24292e" },
|
|
123
|
+
{ tag: [t.deleted], color: "#b31d28" },
|
|
124
|
+
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: "#e36209" },
|
|
125
|
+
{ tag: [t.url, t.escape, t.regexp, t.link], color: "#032f62" },
|
|
126
|
+
{ tag: t.invalid, color: "#cb2431" },
|
|
127
|
+
],
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* VS Code Dark+ highlight palette, adapted from the `@uiw/codemirror-theme-vscode`
|
|
132
|
+
* snippet. `defaultColor` is VS Code's editor foreground (`#9cdcfe`). DOM-only
|
|
133
|
+
* style props are dropped; later rules win, matching {@link tagHighlighter}.
|
|
134
|
+
*/
|
|
135
|
+
export const VscodeDarkStyle: CodeHighlightStyle = {
|
|
136
|
+
name: "vscode-dark",
|
|
137
|
+
defaultColor: "#9cdcfe",
|
|
138
|
+
rules: [
|
|
139
|
+
{
|
|
140
|
+
tag: [
|
|
141
|
+
t.keyword, t.operatorKeyword, t.modifier, t.color,
|
|
142
|
+
t.constant(t.name), t.standard(t.name), t.standard(t.tagName),
|
|
143
|
+
t.special(t.brace), t.atom, t.bool, t.special(t.variableName),
|
|
144
|
+
],
|
|
145
|
+
color: "#569cd6",
|
|
146
|
+
},
|
|
147
|
+
{ tag: [t.controlKeyword, t.moduleKeyword], color: "#c586c0" },
|
|
148
|
+
{
|
|
149
|
+
tag: [
|
|
150
|
+
t.name, t.deleted, t.character, t.macroName, t.propertyName,
|
|
151
|
+
t.variableName, t.labelName, t.definition(t.name),
|
|
152
|
+
],
|
|
153
|
+
color: "#9cdcfe",
|
|
154
|
+
},
|
|
155
|
+
{ tag: t.heading, color: "#9cdcfe" },
|
|
156
|
+
{ tag: [t.typeName, t.className, t.tagName, t.changed, t.annotation, t.self, t.namespace], color: "#4ec9b0" },
|
|
157
|
+
{ tag: [t.function(t.variableName), t.function(t.propertyName)], color: "#dcdcaa" },
|
|
158
|
+
{ tag: [t.number], color: "#b5cea8" },
|
|
159
|
+
{ tag: [t.operator, t.punctuation, t.separator, t.url, t.escape], color: "#d4d4d4" },
|
|
160
|
+
{ tag: [t.regexp], color: "#d16969" },
|
|
161
|
+
{ tag: [t.special(t.string), t.processingInstruction, t.string, t.inserted], color: "#ce9178" },
|
|
162
|
+
{ tag: [t.angleBracket], color: "#808080" },
|
|
163
|
+
{ tag: [t.meta, t.comment], color: "#6a9955" },
|
|
164
|
+
{ tag: t.link, color: "#6a9955" },
|
|
165
|
+
{ tag: t.invalid, color: "#ff0000" },
|
|
166
|
+
],
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* VS Code Light+ highlight palette, adapted from the `@uiw/codemirror-theme-vscode`
|
|
171
|
+
* snippet. `defaultColor` is VS Code's editor foreground (`#383a42`). See
|
|
172
|
+
* {@link VscodeDarkStyle} for the note on dropped DOM-only style props.
|
|
173
|
+
*/
|
|
174
|
+
export const VscodeLightStyle: CodeHighlightStyle = {
|
|
175
|
+
name: "vscode-light",
|
|
176
|
+
defaultColor: "#383a42",
|
|
177
|
+
rules: [
|
|
178
|
+
{
|
|
179
|
+
tag: [
|
|
180
|
+
t.keyword, t.operatorKeyword, t.modifier, t.color,
|
|
181
|
+
t.constant(t.name), t.standard(t.name), t.standard(t.tagName),
|
|
182
|
+
t.special(t.brace), t.atom, t.bool, t.special(t.variableName),
|
|
183
|
+
],
|
|
184
|
+
color: "#0000ff",
|
|
185
|
+
},
|
|
186
|
+
{ tag: [t.moduleKeyword, t.controlKeyword], color: "#af00db" },
|
|
187
|
+
{
|
|
188
|
+
tag: [
|
|
189
|
+
t.name, t.deleted, t.character, t.macroName, t.propertyName,
|
|
190
|
+
t.variableName, t.labelName, t.definition(t.name),
|
|
191
|
+
],
|
|
192
|
+
color: "#0070c1",
|
|
193
|
+
},
|
|
194
|
+
{ tag: t.heading, color: "#0070c1" },
|
|
195
|
+
{ tag: [t.typeName, t.className, t.tagName, t.changed, t.annotation, t.self, t.namespace], color: "#267f99" },
|
|
196
|
+
{ tag: [t.function(t.variableName), t.function(t.propertyName)], color: "#795e26" },
|
|
197
|
+
{ tag: [t.number], color: "#098658" },
|
|
198
|
+
{ tag: [t.operator, t.punctuation, t.separator, t.url, t.escape], color: "#383a42" },
|
|
199
|
+
{ tag: [t.regexp], color: "#af00db" },
|
|
200
|
+
{ tag: [t.special(t.string), t.processingInstruction, t.string, t.inserted], color: "#a31515" },
|
|
201
|
+
{ tag: [t.angleBracket], color: "#383a42" },
|
|
202
|
+
{ tag: [t.meta, t.comment], color: "#008000" },
|
|
203
|
+
{ tag: t.link, color: "#4078f2" },
|
|
204
|
+
{ tag: t.invalid, color: "#e45649" },
|
|
205
|
+
],
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* The built-in themes, keyed by their string name. {@link CodeThemeName} is the
|
|
210
|
+
* union of these keys — pass one of those strings (or any {@link CodeHighlightStyle}
|
|
211
|
+
* object) to a Code node's `theme` prop.
|
|
212
|
+
*/
|
|
213
|
+
export const BUILTIN_THEMES = {
|
|
214
|
+
// Literal keys (not computed from `.name`) so `keyof` yields a string-literal
|
|
215
|
+
// union for CodeThemeName; these must stay in sync with each style's `name`.
|
|
216
|
+
"motion-canvas-default": DefaultHighlightStyle,
|
|
217
|
+
"github-dark": GithubDarkStyle,
|
|
218
|
+
"github-light": GithubLightStyle,
|
|
219
|
+
"vscode-dark": VscodeDarkStyle,
|
|
220
|
+
"vscode-light": VscodeLightStyle,
|
|
221
|
+
} satisfies Record<string, CodeHighlightStyle>;
|
|
222
|
+
|
|
223
|
+
/** Names of the built-in themes, e.g. `'github-dark' | 'github-light'`. */
|
|
224
|
+
export type CodeThemeName = keyof typeof BUILTIN_THEMES;
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* What a Code node's `theme` prop accepts: a built-in theme name (with
|
|
228
|
+
* autocomplete), any other registered theme name, or a {@link CodeHighlightStyle}
|
|
229
|
+
* object passed inline. The `string & {}` keeps the literal-name suggestions while
|
|
230
|
+
* still allowing arbitrary registered names.
|
|
231
|
+
*/
|
|
232
|
+
export type CodeTheme = CodeThemeName | (string & {}) | CodeHighlightStyle;
|
|
233
|
+
|
|
234
|
+
// Cache one compiled Highlighter per style *object*. Compiling builds a tag-rule
|
|
235
|
+
// matcher; the parsed result is pure data so it's safe to share across Code nodes.
|
|
236
|
+
// Keyed by the object rather than its `name`: two styles may share a name (an
|
|
237
|
+
// inline theme, or one re-registered under the same name with new colours), and
|
|
238
|
+
// the second must not colour with the first one's rules. A WeakMap, so a style
|
|
239
|
+
// nothing refers to any more takes its matcher with it.
|
|
240
|
+
const compiledByStyle = new WeakMap<CodeHighlightStyle, Highlighter>();
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Compile a {@link CodeHighlightStyle} into a `@lezer/highlight` {@link Highlighter}
|
|
244
|
+
* whose "class" output is the literal color string for each tag. Cached per style
|
|
245
|
+
* object so repeated lookups (every tokenize) don't rebuild the matcher.
|
|
246
|
+
*/
|
|
247
|
+
export function compileStyle(style: CodeHighlightStyle): Highlighter {
|
|
248
|
+
const cached = compiledByStyle.get(style);
|
|
249
|
+
if (cached) return cached;
|
|
250
|
+
const highlighter = tagHighlighter(
|
|
251
|
+
style.rules.map(rule => ({ tag: rule.tag, class: rule.color })),
|
|
252
|
+
);
|
|
253
|
+
compiledByStyle.set(style, highlighter);
|
|
254
|
+
return highlighter;
|
|
255
|
+
}
|