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.escape": {
106 color: color.comment,
107 },
108 "string.regex": {
109 color: color.string,
110 },
111 constructor: {
112 color: colorScheme.ramps.blue(0.5).hex(),
113 },
114 variant: {
115 color: colorScheme.ramps.blue(0.5).hex(),
116 },
117 type: {
118 color: color.type,
119 },
120 "type.builtin": {
121 color: color.type,
122 },
123 "variable.builtin": {
124 color: colorScheme.ramps.blue(0.5).hex(),
125 },
126 "variable.special": {
127 color: colorScheme.ramps.blue(0.7).hex(),
128 },
129 label: {
130 color: colorScheme.ramps.blue(0.5).hex(),
131 },
132 tag: {
133 color: colorScheme.ramps.blue(0.5).hex(),
134 },
135 attribute: {
136 color: colorScheme.ramps.blue(0.5).hex(),
137 },
138 property: {
139 color: colorScheme.ramps.blue(0.5).hex(),
140 },
141 constant: {
142 color: color.constant,
143 },
144 keyword: {
145 color: color.keyword,
146 },
147 enum: {
148 color: color.enum,
149 },
150 operator: {
151 color: color.operator,
152 },
153 number: {
154 color: color.number,
155 },
156 boolean: {
157 color: color.boolean,
158 },
159 "constant.builtin": {
160 color: color.constant,
161 },
162 function: {
163 color: color.function,
164 },
165 "function.builtin": {
166 color: color.function,
167 },
168 "function.call": {
169 color: color.function,
170 },
171 "function.definition": {
172 color: color.function,
173 },
174 "function.special.definition": {
175 color: color.function,
176 },
177 "function.method": {
178 color: color.function,
179 },
180 "function.method.builtin": {
181 color: color.function,
182 },
183 preproc: {
184 color: color.primary,
185 },
186 embedded: {
187 color: color.primary,
188 },
189 }
190
191 console.log(JSON.stringify(defaultSyntax, null, 2))
192
193 return defaultSyntax
194}
195
196function mergeSyntax(defaultSyntax: Syntax, colorScheme: ColorScheme): Syntax {
197 if (!colorScheme.syntax) {
198 return defaultSyntax
199 }
200
201 return deepmerge<Syntax, Partial<ThemeSyntax>>(
202 defaultSyntax,
203 colorScheme.syntax,
204 {
205 arrayMerge: (destinationArray, sourceArray) => [
206 ...destinationArray,
207 ...sourceArray,
208 ],
209 }
210 )
211}
212
213import {
214 ColorScheme,
215 Syntax,
216 SyntaxHighlightStyle,
217 ThemeSyntax,
218} from "./colorScheme"
219
220export function buildSyntax(colorScheme: ColorScheme): Syntax {
221 const defaultSyntax: Syntax = buildDefaultSyntax(colorScheme)
222
223 const syntax = mergeSyntax(defaultSyntax, colorScheme)
224
225 return syntax
226}