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.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}