syntax.ts

  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}