1import deepmerge from "deepmerge"
2import { fontWeights } from "../../common"
3
4const defaultSyntaxHighlightStyle: Omit<SyntaxHighlightStyle, "color"> = {
5 weight: fontWeights.normal,
6 underline: false,
7 italic: false,
8}
9
10function buildDefaultSyntax(colorScheme: ColorScheme): Syntax {
11 // Make a temporary object that is allowed to be missing
12 // the "color" property for each style
13 const syntax: {
14 [key: string]: Omit<SyntaxHighlightStyle, "color">
15 } = {}
16
17 // then spread the default to each style
18 for (const key of Object.keys({} as Syntax)) {
19 syntax[key as keyof Syntax] = {
20 ...defaultSyntaxHighlightStyle,
21 }
22 }
23
24 const color = {
25 primary: colorScheme.ramps.neutral(1).hex(),
26 comment: colorScheme.ramps.neutral(0.71).hex(),
27 punctuation: colorScheme.ramps.neutral(0.86).hex(),
28 predictive: colorScheme.ramps.neutral(0.57).hex(),
29 emphasis: colorScheme.ramps.blue(0.5).hex(),
30 string: colorScheme.ramps.orange(0.5).hex(),
31 function: colorScheme.ramps.yellow(0.5).hex(),
32 type: colorScheme.ramps.cyan(0.5).hex(),
33 constructor: colorScheme.ramps.blue(0.5).hex(),
34 variant: colorScheme.ramps.blue(0.5).hex(),
35 property: colorScheme.ramps.blue(0.5).hex(),
36 enum: colorScheme.ramps.orange(0.5).hex(),
37 operator: colorScheme.ramps.orange(0.5).hex(),
38 number: colorScheme.ramps.green(0.5).hex(),
39 boolean: colorScheme.ramps.green(0.5).hex(),
40 constant: colorScheme.ramps.green(0.5).hex(),
41 keyword: colorScheme.ramps.blue(0.5).hex(),
42 }
43
44 // Then assign colors and use Syntax to enforce each style getting it's own color
45 const defaultSyntax: Syntax = {
46 ...syntax,
47 comment: {
48 color: color.comment,
49 },
50 "comment.doc": {
51 color: color.comment,
52 },
53 primary: {
54 color: color.primary,
55 },
56 predictive: {
57 color: color.predictive,
58 },
59 emphasis: {
60 color: color.emphasis,
61 },
62 "emphasis.strong": {
63 color: color.emphasis,
64 weight: fontWeights.bold,
65 },
66 title: {
67 color: color.primary,
68 weight: fontWeights.bold,
69 },
70 linkUri: {
71 color: colorScheme.ramps.green(0.5).hex(),
72 underline: true,
73 },
74 linkText: {
75 color: colorScheme.ramps.orange(0.5).hex(),
76 italic: true,
77 },
78 "text.literal": {
79 color: color.string,
80 },
81 punctuation: {
82 color: color.punctuation,
83 },
84 "punctuation.bracket": {
85 color: color.punctuation,
86 },
87 "punctuation.delimiter": {
88 color: color.punctuation,
89 },
90 "punctuation.special": {
91 color: colorScheme.ramps.neutral(0.86).hex(),
92 },
93 "punctuation.list_marker": {
94 color: color.punctuation,
95 },
96 string: {
97 color: color.string,
98 },
99 "string.special": {
100 color: color.string,
101 },
102 "string.special.symbol": {
103 color: color.string,
104 },
105 "string.special.regex": {
106 color: color.string,
107 },
108 "string.escape": {
109 color: color.comment,
110 },
111 "string.regex": {
112 color: color.string,
113 },
114 constructor: {
115 color: colorScheme.ramps.blue(0.5).hex(),
116 },
117 variant: {
118 color: colorScheme.ramps.blue(0.5).hex(),
119 },
120 type: {
121 color: color.type,
122 },
123 "type.builtin": {
124 color: color.type,
125 },
126 "variable.builtin": {
127 color: colorScheme.ramps.blue(0.5).hex(),
128 },
129 "variable.special": {
130 color: colorScheme.ramps.blue(0.7).hex(),
131 },
132 label: {
133 color: colorScheme.ramps.blue(0.5).hex(),
134 },
135 tag: {
136 color: colorScheme.ramps.blue(0.5).hex(),
137 },
138 attribute: {
139 color: colorScheme.ramps.blue(0.5).hex(),
140 },
141 property: {
142 color: colorScheme.ramps.blue(0.5).hex(),
143 },
144 constant: {
145 color: color.constant,
146 },
147 keyword: {
148 color: color.keyword,
149 },
150 enum: {
151 color: color.enum,
152 },
153 operator: {
154 color: color.operator,
155 },
156 number: {
157 color: color.number,
158 },
159 boolean: {
160 color: color.boolean,
161 },
162 "constant.builtin": {
163 color: color.constant,
164 },
165 function: {
166 color: color.function,
167 },
168 "function.builtin": {
169 color: color.function,
170 },
171 "function.call": {
172 color: color.function,
173 },
174 "function.definition": {
175 color: color.function,
176 },
177 "function.special.definition": {
178 color: color.function,
179 },
180 "function.method": {
181 color: color.function,
182 },
183 "function.method.builtin": {
184 color: color.function,
185 },
186 preproc: {
187 color: color.primary,
188 },
189 embedded: {
190 color: color.primary,
191 },
192 }
193
194 console.log(JSON.stringify(defaultSyntax, null, 2))
195
196 return defaultSyntax
197}
198
199function mergeSyntax(defaultSyntax: Syntax, colorScheme: ColorScheme): Syntax {
200 if (!colorScheme.syntax) {
201 return defaultSyntax
202 }
203
204 return deepmerge<Syntax, Partial<ThemeSyntax>>(
205 defaultSyntax,
206 colorScheme.syntax,
207 {
208 arrayMerge: (destinationArray, sourceArray) => [
209 ...destinationArray,
210 ...sourceArray,
211 ],
212 }
213 )
214}
215
216import {
217 ColorScheme,
218 Syntax,
219 SyntaxHighlightStyle,
220 ThemeSyntax,
221} from "./colorScheme"
222
223export function buildSyntax(colorScheme: ColorScheme): Syntax {
224 const defaultSyntax: Syntax = buildDefaultSyntax(colorScheme)
225
226 const syntax = mergeSyntax(defaultSyntax, colorScheme)
227
228 return syntax
229}