diff options
-rw-r--r-- | editors/code/src/config.ts | 2 | ||||
-rw-r--r-- | editors/code/src/ctx.ts | 2 | ||||
-rw-r--r-- | editors/code/src/highlighting.ts | 215 | ||||
-rw-r--r-- | editors/code/src/scopes.ts | 182 | ||||
-rw-r--r-- | editors/code/tsconfig.json | 2 |
5 files changed, 182 insertions, 221 deletions
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index e323110a4..f63d1ddce 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts | |||
@@ -1,5 +1,4 @@ | |||
1 | import * as vscode from 'vscode'; | 1 | import * as vscode from 'vscode'; |
2 | import * as scopes from './scopes'; | ||
3 | import * as scopesMapper from './scopes_mapper'; | 2 | import * as scopesMapper from './scopes_mapper'; |
4 | 3 | ||
5 | const RA_LSP_DEBUG = process.env.__RA_LSP_SERVER_DEBUG; | 4 | const RA_LSP_DEBUG = process.env.__RA_LSP_SERVER_DEBUG; |
@@ -60,7 +59,6 @@ export class Config { | |||
60 | if (config.has('highlightingOn')) { | 59 | if (config.has('highlightingOn')) { |
61 | this.highlightingOn = config.get('highlightingOn') as boolean; | 60 | this.highlightingOn = config.get('highlightingOn') as boolean; |
62 | if (this.highlightingOn) { | 61 | if (this.highlightingOn) { |
63 | scopes.load(); | ||
64 | scopesMapper.load(); | 62 | scopesMapper.load(); |
65 | } | 63 | } |
66 | } | 64 | } |
diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index 39eddfcbd..30dd9811c 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts | |||
@@ -65,7 +65,7 @@ export class Ctx { | |||
65 | async sendRequestWithRetry<R>( | 65 | async sendRequestWithRetry<R>( |
66 | method: string, | 66 | method: string, |
67 | param: any, | 67 | param: any, |
68 | token: vscode.CancellationToken, | 68 | token?: vscode.CancellationToken, |
69 | ): Promise<R> { | 69 | ): Promise<R> { |
70 | await this.client.onReady(); | 70 | await this.client.onReady(); |
71 | for (const delay of [2, 4, 6, 8, 10, null]) { | 71 | for (const delay of [2, 4, 6, 8, 10, null]) { |
diff --git a/editors/code/src/highlighting.ts b/editors/code/src/highlighting.ts index 247673b5c..5e9cbe0de 100644 --- a/editors/code/src/highlighting.ts +++ b/editors/code/src/highlighting.ts | |||
@@ -3,7 +3,7 @@ import * as lc from 'vscode-languageclient'; | |||
3 | import * as seedrandom_ from 'seedrandom'; | 3 | import * as seedrandom_ from 'seedrandom'; |
4 | const seedrandom = seedrandom_; // https://github.com/jvandemo/generator-angular2-library/issues/221#issuecomment-355945207 | 4 | const seedrandom = seedrandom_; // https://github.com/jvandemo/generator-angular2-library/issues/221#issuecomment-355945207 |
5 | 5 | ||
6 | import * as scopes from './scopes'; | 6 | import { loadThemeColors, TextMateRuleSettings } from './scopes'; |
7 | import * as scopesMapper from './scopes_mapper'; | 7 | import * as scopesMapper from './scopes_mapper'; |
8 | 8 | ||
9 | import { Ctx } from './ctx'; | 9 | import { Ctx } from './ctx'; |
@@ -47,7 +47,7 @@ export function activateHighlighting(ctx: Ctx) { | |||
47 | const params: lc.TextDocumentIdentifier = { | 47 | const params: lc.TextDocumentIdentifier = { |
48 | uri: editor.document.uri.toString(), | 48 | uri: editor.document.uri.toString(), |
49 | }; | 49 | }; |
50 | const decorations = await ctx.client.sendRequest<Decoration[]>( | 50 | const decorations = await ctx.sendRequestWithRetry<Decoration[]>( |
51 | 'rust-analyzer/decorationsRequest', | 51 | 'rust-analyzer/decorationsRequest', |
52 | params, | 52 | params, |
53 | ); | 53 | ); |
@@ -62,7 +62,7 @@ interface PublishDecorationsParams { | |||
62 | decorations: Decoration[]; | 62 | decorations: Decoration[]; |
63 | } | 63 | } |
64 | 64 | ||
65 | export interface Decoration { | 65 | interface Decoration { |
66 | range: lc.Range; | 66 | range: lc.Range; |
67 | tag: string; | 67 | tag: string; |
68 | bindingHash?: string; | 68 | bindingHash?: string; |
@@ -81,116 +81,17 @@ function fancify(seed: string, shade: 'light' | 'dark') { | |||
81 | return `hsl(${h},${s}%,${l}%)`; | 81 | return `hsl(${h},${s}%,${l}%)`; |
82 | } | 82 | } |
83 | 83 | ||
84 | function createDecorationFromTextmate( | ||
85 | themeStyle: scopes.TextMateRuleSettings, | ||
86 | ): vscode.TextEditorDecorationType { | ||
87 | const decorationOptions: vscode.DecorationRenderOptions = {}; | ||
88 | decorationOptions.rangeBehavior = vscode.DecorationRangeBehavior.OpenOpen; | ||
89 | |||
90 | if (themeStyle.foreground) { | ||
91 | decorationOptions.color = themeStyle.foreground; | ||
92 | } | ||
93 | |||
94 | if (themeStyle.background) { | ||
95 | decorationOptions.backgroundColor = themeStyle.background; | ||
96 | } | ||
97 | |||
98 | if (themeStyle.fontStyle) { | ||
99 | const parts: string[] = themeStyle.fontStyle.split(' '); | ||
100 | parts.forEach(part => { | ||
101 | switch (part) { | ||
102 | case 'italic': | ||
103 | decorationOptions.fontStyle = 'italic'; | ||
104 | break; | ||
105 | case 'bold': | ||
106 | decorationOptions.fontWeight = 'bold'; | ||
107 | break; | ||
108 | case 'underline': | ||
109 | decorationOptions.textDecoration = 'underline'; | ||
110 | break; | ||
111 | default: | ||
112 | break; | ||
113 | } | ||
114 | }); | ||
115 | } | ||
116 | return vscode.window.createTextEditorDecorationType(decorationOptions); | ||
117 | } | ||
118 | |||
119 | class Highlighter { | 84 | class Highlighter { |
120 | private ctx: Ctx; | 85 | private ctx: Ctx; |
121 | |||
122 | constructor(ctx: Ctx) { | ||
123 | this.ctx = ctx; | ||
124 | } | ||
125 | |||
126 | private static initDecorations(): Map< | ||
127 | string, | ||
128 | vscode.TextEditorDecorationType | ||
129 | > { | ||
130 | const decoration = ( | ||
131 | tag: string, | ||
132 | textDecoration?: string, | ||
133 | ): [string, vscode.TextEditorDecorationType] => { | ||
134 | const rule = scopesMapper.toRule(tag, scopes.find); | ||
135 | |||
136 | if (rule) { | ||
137 | const decor = createDecorationFromTextmate(rule); | ||
138 | return [tag, decor]; | ||
139 | } else { | ||
140 | const fallBackTag = 'ralsp.' + tag; | ||
141 | // console.log(' '); | ||
142 | // console.log('Missing theme for: <"' + tag + '"> for following mapped scopes:'); | ||
143 | // console.log(scopesMapper.find(tag)); | ||
144 | // console.log('Falling back to values defined in: ' + fallBackTag); | ||
145 | // console.log(' '); | ||
146 | const color = new vscode.ThemeColor(fallBackTag); | ||
147 | const decor = vscode.window.createTextEditorDecorationType({ | ||
148 | color, | ||
149 | textDecoration, | ||
150 | }); | ||
151 | return [tag, decor]; | ||
152 | } | ||
153 | }; | ||
154 | |||
155 | const decorations: Iterable<[ | ||
156 | string, | ||
157 | vscode.TextEditorDecorationType, | ||
158 | ]> = [ | ||
159 | decoration('comment'), | ||
160 | decoration('string'), | ||
161 | decoration('keyword'), | ||
162 | decoration('keyword.control'), | ||
163 | decoration('keyword.unsafe'), | ||
164 | decoration('function'), | ||
165 | decoration('parameter'), | ||
166 | decoration('constant'), | ||
167 | decoration('type.builtin'), | ||
168 | decoration('type.generic'), | ||
169 | decoration('type.lifetime'), | ||
170 | decoration('type.param'), | ||
171 | decoration('type.self'), | ||
172 | decoration('type'), | ||
173 | decoration('text'), | ||
174 | decoration('attribute'), | ||
175 | decoration('literal'), | ||
176 | decoration('literal.numeric'), | ||
177 | decoration('literal.char'), | ||
178 | decoration('literal.byte'), | ||
179 | decoration('macro'), | ||
180 | decoration('variable'), | ||
181 | decoration('variable.mut', 'underline'), | ||
182 | decoration('field'), | ||
183 | decoration('module'), | ||
184 | ]; | ||
185 | |||
186 | return new Map<string, vscode.TextEditorDecorationType>(decorations); | ||
187 | } | ||
188 | |||
189 | private decorations: Map< | 86 | private decorations: Map< |
190 | string, | 87 | string, |
191 | vscode.TextEditorDecorationType | 88 | vscode.TextEditorDecorationType |
192 | > | null = null; | 89 | > | null = null; |
193 | 90 | ||
91 | constructor(ctx: Ctx) { | ||
92 | this.ctx = ctx; | ||
93 | } | ||
94 | |||
194 | public removeHighlights() { | 95 | public removeHighlights() { |
195 | if (this.decorations == null) { | 96 | if (this.decorations == null) { |
196 | return; | 97 | return; |
@@ -210,7 +111,7 @@ class Highlighter { | |||
210 | // Note: decoration objects need to be kept around so we can dispose them | 111 | // Note: decoration objects need to be kept around so we can dispose them |
211 | // if the user disables syntax highlighting | 112 | // if the user disables syntax highlighting |
212 | if (this.decorations == null) { | 113 | if (this.decorations == null) { |
213 | this.decorations = Highlighter.initDecorations(); | 114 | this.decorations = initDecorations(); |
214 | } | 115 | } |
215 | 116 | ||
216 | const byTag: Map<string, vscode.Range[]> = new Map(); | 117 | const byTag: Map<string, vscode.Range[]> = new Map(); |
@@ -266,3 +167,103 @@ class Highlighter { | |||
266 | } | 167 | } |
267 | } | 168 | } |
268 | } | 169 | } |
170 | |||
171 | function initDecorations(): Map< | ||
172 | string, | ||
173 | vscode.TextEditorDecorationType | ||
174 | > { | ||
175 | const themeColors = loadThemeColors(); | ||
176 | |||
177 | const decoration = ( | ||
178 | tag: string, | ||
179 | textDecoration?: string, | ||
180 | ): [string, vscode.TextEditorDecorationType] => { | ||
181 | const rule = scopesMapper.toRule(tag, it => themeColors.get(it)); | ||
182 | |||
183 | if (rule) { | ||
184 | const decor = createDecorationFromTextmate(rule); | ||
185 | return [tag, decor]; | ||
186 | } else { | ||
187 | const fallBackTag = 'ralsp.' + tag; | ||
188 | // console.log(' '); | ||
189 | // console.log('Missing theme for: <"' + tag + '"> for following mapped scopes:'); | ||
190 | // console.log(scopesMapper.find(tag)); | ||
191 | // console.log('Falling back to values defined in: ' + fallBackTag); | ||
192 | // console.log(' '); | ||
193 | const color = new vscode.ThemeColor(fallBackTag); | ||
194 | const decor = vscode.window.createTextEditorDecorationType({ | ||
195 | color, | ||
196 | textDecoration, | ||
197 | }); | ||
198 | return [tag, decor]; | ||
199 | } | ||
200 | }; | ||
201 | |||
202 | const decorations: Iterable<[ | ||
203 | string, | ||
204 | vscode.TextEditorDecorationType, | ||
205 | ]> = [ | ||
206 | decoration('comment'), | ||
207 | decoration('string'), | ||
208 | decoration('keyword'), | ||
209 | decoration('keyword.control'), | ||
210 | decoration('keyword.unsafe'), | ||
211 | decoration('function'), | ||
212 | decoration('parameter'), | ||
213 | decoration('constant'), | ||
214 | decoration('type.builtin'), | ||
215 | decoration('type.generic'), | ||
216 | decoration('type.lifetime'), | ||
217 | decoration('type.param'), | ||
218 | decoration('type.self'), | ||
219 | decoration('type'), | ||
220 | decoration('text'), | ||
221 | decoration('attribute'), | ||
222 | decoration('literal'), | ||
223 | decoration('literal.numeric'), | ||
224 | decoration('literal.char'), | ||
225 | decoration('literal.byte'), | ||
226 | decoration('macro'), | ||
227 | decoration('variable'), | ||
228 | decoration('variable.mut', 'underline'), | ||
229 | decoration('field'), | ||
230 | decoration('module'), | ||
231 | ]; | ||
232 | |||
233 | return new Map<string, vscode.TextEditorDecorationType>(decorations); | ||
234 | } | ||
235 | |||
236 | function createDecorationFromTextmate( | ||
237 | themeStyle: TextMateRuleSettings, | ||
238 | ): vscode.TextEditorDecorationType { | ||
239 | const decorationOptions: vscode.DecorationRenderOptions = {}; | ||
240 | decorationOptions.rangeBehavior = vscode.DecorationRangeBehavior.OpenOpen; | ||
241 | |||
242 | if (themeStyle.foreground) { | ||
243 | decorationOptions.color = themeStyle.foreground; | ||
244 | } | ||
245 | |||
246 | if (themeStyle.background) { | ||
247 | decorationOptions.backgroundColor = themeStyle.background; | ||
248 | } | ||
249 | |||
250 | if (themeStyle.fontStyle) { | ||
251 | const parts: string[] = themeStyle.fontStyle.split(' '); | ||
252 | parts.forEach(part => { | ||
253 | switch (part) { | ||
254 | case 'italic': | ||
255 | decorationOptions.fontStyle = 'italic'; | ||
256 | break; | ||
257 | case 'bold': | ||
258 | decorationOptions.fontWeight = 'bold'; | ||
259 | break; | ||
260 | case 'underline': | ||
261 | decorationOptions.textDecoration = 'underline'; | ||
262 | break; | ||
263 | default: | ||
264 | break; | ||
265 | } | ||
266 | }); | ||
267 | } | ||
268 | return vscode.window.createTextEditorDecorationType(decorationOptions); | ||
269 | } | ||
diff --git a/editors/code/src/scopes.ts b/editors/code/src/scopes.ts index cb250b853..73fabbf54 100644 --- a/editors/code/src/scopes.ts +++ b/editors/code/src/scopes.ts | |||
@@ -3,28 +3,14 @@ import * as jsonc from 'jsonc-parser'; | |||
3 | import * as path from 'path'; | 3 | import * as path from 'path'; |
4 | import * as vscode from 'vscode'; | 4 | import * as vscode from 'vscode'; |
5 | 5 | ||
6 | export interface TextMateRule { | ||
7 | scope: string | string[]; | ||
8 | settings: TextMateRuleSettings; | ||
9 | } | ||
10 | |||
11 | export interface TextMateRuleSettings { | 6 | export interface TextMateRuleSettings { |
12 | foreground: string | undefined; | 7 | foreground?: string; |
13 | background: string | undefined; | 8 | background?: string; |
14 | fontStyle: string | undefined; | 9 | fontStyle?: string; |
15 | } | ||
16 | |||
17 | // Current theme colors | ||
18 | const rules = new Map<string, TextMateRuleSettings>(); | ||
19 | |||
20 | export function find(scope: string): TextMateRuleSettings | undefined { | ||
21 | return rules.get(scope); | ||
22 | } | 10 | } |
23 | 11 | ||
24 | // Load all textmate scopes in the currently active theme | 12 | // Load all textmate scopes in the currently active theme |
25 | export function load() { | 13 | export function loadThemeColors(): Map<string, TextMateRuleSettings> { |
26 | // Remove any previous theme | ||
27 | rules.clear(); | ||
28 | // Find out current color theme | 14 | // Find out current color theme |
29 | const themeName = vscode.workspace | 15 | const themeName = vscode.workspace |
30 | .getConfiguration('workbench') | 16 | .getConfiguration('workbench') |
@@ -32,115 +18,91 @@ export function load() { | |||
32 | 18 | ||
33 | if (typeof themeName !== 'string') { | 19 | if (typeof themeName !== 'string') { |
34 | // console.warn('workbench.colorTheme is', themeName) | 20 | // console.warn('workbench.colorTheme is', themeName) |
35 | return; | 21 | return new Map(); |
36 | } | ||
37 | // Try to load colors from that theme | ||
38 | try { | ||
39 | loadThemeNamed(themeName); | ||
40 | } catch (e) { | ||
41 | // console.warn('failed to load theme', themeName, e) | ||
42 | } | 22 | } |
23 | return loadThemeNamed(themeName); | ||
43 | } | 24 | } |
44 | 25 | ||
45 | function filterThemeExtensions(extension: vscode.Extension<any>): boolean { | 26 | function loadThemeNamed(themeName: string): Map<string, TextMateRuleSettings> { |
46 | return ( | 27 | function isTheme(extension: vscode.Extension<any>): boolean { |
47 | extension.extensionKind === vscode.ExtensionKind.UI && | 28 | return ( |
48 | extension.packageJSON.contributes && | 29 | extension.extensionKind === vscode.ExtensionKind.UI && |
49 | extension.packageJSON.contributes.themes | 30 | extension.packageJSON.contributes && |
50 | ); | 31 | extension.packageJSON.contributes.themes |
51 | } | 32 | ); |
52 | 33 | } | |
53 | // Find current theme on disk | ||
54 | function loadThemeNamed(themeName: string) { | ||
55 | const themePaths = vscode.extensions.all | ||
56 | .filter(filterThemeExtensions) | ||
57 | .reduce((list, extension) => { | ||
58 | return extension.packageJSON.contributes.themes | ||
59 | .filter( | ||
60 | (element: any) => | ||
61 | (element.id || element.label) === themeName, | ||
62 | ) | ||
63 | .map((element: any) => | ||
64 | path.join(extension.extensionPath, element.path), | ||
65 | ) | ||
66 | .concat(list); | ||
67 | }, Array<string>()); | ||
68 | |||
69 | themePaths.forEach(loadThemeFile); | ||
70 | |||
71 | const tokenColorCustomizations: [any] = [ | ||
72 | vscode.workspace | ||
73 | .getConfiguration('editor') | ||
74 | .get('tokenColorCustomizations'), | ||
75 | ]; | ||
76 | |||
77 | tokenColorCustomizations | ||
78 | .filter(custom => custom && custom.textMateRules) | ||
79 | .map(custom => custom.textMateRules) | ||
80 | .forEach(loadColors); | ||
81 | } | ||
82 | 34 | ||
83 | function loadThemeFile(themePath: string) { | 35 | let themePaths = vscode.extensions.all |
84 | const themeContent = [themePath] | 36 | .filter(isTheme) |
85 | .filter(isFile) | 37 | .flatMap(ext => { |
86 | .map(readFileText) | 38 | return ext.packageJSON.contributes.themes |
87 | .map(parseJSON) | 39 | .filter((it: any) => (it.id || it.label) === themeName) |
88 | .filter(theme => theme); | 40 | .map((it: any) => path.join(ext.extensionPath, it.path)); |
41 | }) | ||
42 | |||
43 | const res = new Map(); | ||
44 | for (const themePath of themePaths) { | ||
45 | mergeInto(res, loadThemeFile(themePath)) | ||
46 | } | ||
89 | 47 | ||
90 | themeContent | 48 | const customizations: any = vscode.workspace.getConfiguration('editor').get('tokenColorCustomizations'); |
91 | .filter(theme => theme.tokenColors) | 49 | mergeInto(res, loadColors(customizations?.textMateRules ?? [])) |
92 | .map(theme => theme.tokenColors) | ||
93 | .forEach(loadColors); | ||
94 | 50 | ||
95 | themeContent | 51 | return res; |
96 | .filter(theme => theme.include) | ||
97 | .map(theme => path.join(path.dirname(themePath), theme.include)) | ||
98 | .forEach(loadThemeFile); | ||
99 | } | 52 | } |
100 | 53 | ||
101 | function mergeRuleSettings( | 54 | function loadThemeFile(themePath: string): Map<string, TextMateRuleSettings> { |
102 | defaultSetting: TextMateRuleSettings | undefined, | 55 | let text; |
103 | override: TextMateRuleSettings, | 56 | try { |
104 | ): TextMateRuleSettings { | 57 | text = fs.readFileSync(themePath, 'utf8') |
105 | if (defaultSetting === undefined) { | 58 | } catch { |
106 | return override; | 59 | return new Map(); |
60 | } | ||
61 | const obj = jsonc.parse(text); | ||
62 | const tokenColors = obj?.tokenColors ?? []; | ||
63 | const res = loadColors(tokenColors); | ||
64 | |||
65 | for (const include in obj?.include ?? []) { | ||
66 | const includePath = path.join(path.dirname(themePath), include); | ||
67 | const tmp = loadThemeFile(includePath); | ||
68 | mergeInto(res, tmp); | ||
107 | } | 69 | } |
108 | const mergedRule = defaultSetting; | ||
109 | |||
110 | mergedRule.background = override.background || defaultSetting.background; | ||
111 | mergedRule.foreground = override.foreground || defaultSetting.foreground; | ||
112 | mergedRule.fontStyle = override.fontStyle || defaultSetting.foreground; | ||
113 | 70 | ||
114 | return mergedRule; | 71 | return res; |
115 | } | 72 | } |
116 | 73 | ||
117 | function updateRules( | 74 | interface TextMateRule { |
118 | scope: string, | 75 | scope: string | string[]; |
119 | updatedSettings: TextMateRuleSettings, | 76 | settings: TextMateRuleSettings; |
120 | ): void { | ||
121 | [rules.get(scope)] | ||
122 | .map(settings => mergeRuleSettings(settings, updatedSettings)) | ||
123 | .forEach(settings => rules.set(scope, settings)); | ||
124 | } | 77 | } |
125 | 78 | ||
126 | function loadColors(textMateRules: TextMateRule[]): void { | 79 | function loadColors(textMateRules: TextMateRule[]): Map<string, TextMateRuleSettings> { |
127 | textMateRules.forEach(rule => { | 80 | const res = new Map(); |
128 | if (typeof rule.scope === 'string') { | 81 | for (const rule of textMateRules) { |
129 | updateRules(rule.scope, rule.settings); | 82 | const scopes = typeof rule.scope === 'string' |
130 | } else if (rule.scope instanceof Array) { | 83 | ? [rule.scope] |
131 | rule.scope.forEach(scope => updateRules(scope, rule.settings)); | 84 | : rule.scope; |
85 | for (const scope of scopes) { | ||
86 | res.set(scope, rule.settings) | ||
132 | } | 87 | } |
133 | }); | 88 | } |
134 | } | 89 | return res |
135 | |||
136 | function isFile(filePath: string): boolean { | ||
137 | return [filePath].map(fs.statSync).every(stat => stat.isFile()); | ||
138 | } | 90 | } |
139 | 91 | ||
140 | function readFileText(filePath: string): string { | 92 | function mergeRuleSettings( |
141 | return fs.readFileSync(filePath, 'utf8'); | 93 | defaultSetting: TextMateRuleSettings | undefined, |
94 | override: TextMateRuleSettings, | ||
95 | ): TextMateRuleSettings { | ||
96 | return { | ||
97 | foreground: defaultSetting?.foreground ?? override.foreground, | ||
98 | background: defaultSetting?.background ?? override.background, | ||
99 | fontStyle: defaultSetting?.fontStyle ?? override.fontStyle, | ||
100 | } | ||
142 | } | 101 | } |
143 | 102 | ||
144 | function parseJSON(content: string): any { | 103 | function mergeInto(dst: Map<string, TextMateRuleSettings>, addition: Map<string, TextMateRuleSettings>) { |
145 | return jsonc.parse(content); | 104 | addition.forEach((value, key) => { |
105 | const merged = mergeRuleSettings(dst.get(key), value) | ||
106 | dst.set(key, merged) | ||
107 | }) | ||
146 | } | 108 | } |
diff --git a/editors/code/tsconfig.json b/editors/code/tsconfig.json index fe3b40f34..e60eb8e5e 100644 --- a/editors/code/tsconfig.json +++ b/editors/code/tsconfig.json | |||
@@ -4,7 +4,7 @@ | |||
4 | "target": "es2018", | 4 | "target": "es2018", |
5 | "outDir": "out", | 5 | "outDir": "out", |
6 | "lib": [ | 6 | "lib": [ |
7 | "es2018" | 7 | "es2019" |
8 | ], | 8 | ], |
9 | "sourceMap": true, | 9 | "sourceMap": true, |
10 | "rootDir": "src", | 10 | "rootDir": "src", |