@codingame/monaco-vscode-theme-service-override 1.82.4 → 1.82.5-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,292 @@
1
+ import * as nls from 'monaco-editor/esm/vs/nls.js';
2
+ import * as path from 'monaco-editor/esm/vs/base/common/path.js';
3
+ import * as resources from 'monaco-editor/esm/vs/base/common/resources.js';
4
+ import * as json from 'monaco-editor/esm/vs/base/common/json.js';
5
+ import { ThemeSettingDefaults, ExtensionData } from 'vscode/vscode/vs/workbench/services/themes/common/workbenchThemeService';
6
+ import { getParseErrorMessage } from 'vscode/vscode/vs/base/common/jsonErrorMessages';
7
+ import { fontIdRegex, fontWeightRegex, fontStyleRegex, fontFormatRegex } from '../common/productIconThemeSchema.js';
8
+ import { isObject, isString } from 'monaco-editor/esm/vs/base/common/types.js';
9
+ import { IconFontDefinition, getIconRegistry } from 'monaco-editor/esm/vs/platform/theme/common/iconRegistry.js';
10
+ import { ThemeIcon } from 'monaco-editor/esm/vs/base/common/themables.js';
11
+
12
+ const DEFAULT_PRODUCT_ICON_THEME_ID = '';
13
+ class ProductIconThemeData {
14
+ static { this.STORAGE_KEY = 'productIconThemeData'; }
15
+ constructor(id, label, settingsId) {
16
+ this.iconThemeDocument = { iconDefinitions: ( new Map()) };
17
+ this.id = id;
18
+ this.label = label;
19
+ this.settingsId = settingsId;
20
+ this.isLoaded = false;
21
+ }
22
+ getIcon(iconContribution) {
23
+ return _resolveIconDefinition(iconContribution, this.iconThemeDocument);
24
+ }
25
+ ensureLoaded(fileService, logService) {
26
+ return !this.isLoaded ? this.load(fileService, logService) : Promise.resolve(this.styleSheetContent);
27
+ }
28
+ reload(fileService, logService) {
29
+ return this.load(fileService, logService);
30
+ }
31
+ async load(fileService, logService) {
32
+ const location = this.location;
33
+ if (!location) {
34
+ return Promise.resolve(this.styleSheetContent);
35
+ }
36
+ const warnings = [];
37
+ this.iconThemeDocument = await _loadProductIconThemeDocument(fileService, location, warnings);
38
+ this.isLoaded = true;
39
+ if (warnings.length) {
40
+ logService.error(( nls.localize(
41
+ 'error.parseicondefs',
42
+ "Problems processing product icons definitions in {0}:\n{1}",
43
+ ( location.toString()),
44
+ warnings.join('\n')
45
+ )));
46
+ }
47
+ return this.styleSheetContent;
48
+ }
49
+ static fromExtensionTheme(iconTheme, iconThemeLocation, extensionData) {
50
+ const id = extensionData.extensionId + '-' + iconTheme.id;
51
+ const label = iconTheme.label || path.basename(iconTheme.path);
52
+ const settingsId = iconTheme.id;
53
+ const themeData = ( new ProductIconThemeData(id, label, settingsId));
54
+ themeData.description = iconTheme.description;
55
+ themeData.location = iconThemeLocation;
56
+ themeData.extensionData = extensionData;
57
+ themeData.watch = iconTheme._watch;
58
+ themeData.isLoaded = false;
59
+ return themeData;
60
+ }
61
+ static createUnloadedTheme(id) {
62
+ const themeData = ( new ProductIconThemeData(id, '', '__' + id));
63
+ themeData.isLoaded = false;
64
+ themeData.extensionData = undefined;
65
+ themeData.watch = false;
66
+ return themeData;
67
+ }
68
+ static { this._defaultProductIconTheme = null; }
69
+ static get defaultTheme() {
70
+ let themeData = ProductIconThemeData._defaultProductIconTheme;
71
+ if (!themeData) {
72
+ themeData = ProductIconThemeData._defaultProductIconTheme = ( new ProductIconThemeData(DEFAULT_PRODUCT_ICON_THEME_ID, ( nls.localize('defaultTheme', 'Default')), ThemeSettingDefaults.PRODUCT_ICON_THEME));
73
+ themeData.isLoaded = true;
74
+ themeData.extensionData = undefined;
75
+ themeData.watch = false;
76
+ }
77
+ return themeData;
78
+ }
79
+ static fromStorageData(storageService) {
80
+ const input = storageService.get(ProductIconThemeData.STORAGE_KEY, 0 );
81
+ if (!input) {
82
+ return undefined;
83
+ }
84
+ try {
85
+ const data = JSON.parse(input);
86
+ const theme = ( new ProductIconThemeData('', '', ''));
87
+ for (const key in data) {
88
+ switch (key) {
89
+ case 'id':
90
+ case 'label':
91
+ case 'description':
92
+ case 'settingsId':
93
+ case 'styleSheetContent':
94
+ case 'watch':
95
+ theme[key] = data[key];
96
+ break;
97
+ case 'location':
98
+ break;
99
+ case 'extensionData':
100
+ theme.extensionData = ExtensionData.fromJSONObject(data.extensionData);
101
+ break;
102
+ }
103
+ }
104
+ const { iconDefinitions, iconFontDefinitions } = data;
105
+ if (Array.isArray(iconDefinitions) && isObject(iconFontDefinitions)) {
106
+ const restoredIconDefinitions = ( new Map());
107
+ for (const entry of iconDefinitions) {
108
+ const { id, fontCharacter, fontId } = entry;
109
+ if (isString(id) && isString(fontCharacter)) {
110
+ if (isString(fontId)) {
111
+ const iconFontDefinition = IconFontDefinition.fromJSONObject(iconFontDefinitions[fontId]);
112
+ if (iconFontDefinition) {
113
+ restoredIconDefinitions.set(id, { fontCharacter, font: { id: fontId, definition: iconFontDefinition } });
114
+ }
115
+ }
116
+ else {
117
+ restoredIconDefinitions.set(id, { fontCharacter });
118
+ }
119
+ }
120
+ }
121
+ theme.iconThemeDocument = { iconDefinitions: restoredIconDefinitions };
122
+ }
123
+ return theme;
124
+ }
125
+ catch (e) {
126
+ return undefined;
127
+ }
128
+ }
129
+ toStorage(storageService) {
130
+ const iconDefinitions = [];
131
+ const iconFontDefinitions = {};
132
+ for (const entry of this.iconThemeDocument.iconDefinitions.entries()) {
133
+ const font = entry[1].font;
134
+ iconDefinitions.push({ id: entry[0], fontCharacter: entry[1].fontCharacter, fontId: font?.id });
135
+ if (font && iconFontDefinitions[font.id] === undefined) {
136
+ iconFontDefinitions[font.id] = IconFontDefinition.toJSONObject(font.definition);
137
+ }
138
+ }
139
+ const data = JSON.stringify({
140
+ id: this.id,
141
+ label: this.label,
142
+ description: this.description,
143
+ settingsId: this.settingsId,
144
+ styleSheetContent: this.styleSheetContent,
145
+ watch: this.watch,
146
+ extensionData: ExtensionData.toJSONObject(this.extensionData),
147
+ iconDefinitions,
148
+ iconFontDefinitions
149
+ });
150
+ storageService.store(ProductIconThemeData.STORAGE_KEY, data, 0 , 1 );
151
+ }
152
+ }
153
+ function _loadProductIconThemeDocument(fileService, location, warnings) {
154
+ return fileService.readExtensionResource(location).then((content) => {
155
+ const parseErrors = [];
156
+ const contentValue = json.parse(content, parseErrors);
157
+ if (parseErrors.length > 0) {
158
+ return Promise.reject(( new Error(( nls.localize(
159
+ 'error.cannotparseicontheme',
160
+ "Problems parsing product icons file: {0}",
161
+ ( parseErrors.map(e => getParseErrorMessage(e.error))).join(', ')
162
+ )))));
163
+ }
164
+ else if (json.getNodeType(contentValue) !== 'object') {
165
+ return Promise.reject(( new Error(( nls.localize(
166
+ 'error.invalidformat',
167
+ "Invalid format for product icons theme file: Object expected."
168
+ )))));
169
+ }
170
+ else if (!contentValue.iconDefinitions || !Array.isArray(contentValue.fonts) || !contentValue.fonts.length) {
171
+ return Promise.reject(( new Error(( nls.localize(
172
+ 'error.missingProperties',
173
+ "Invalid format for product icons theme file: Must contain iconDefinitions and fonts."
174
+ )))));
175
+ }
176
+ const iconThemeDocumentLocationDirname = resources.dirname(location);
177
+ const sanitizedFonts = ( new Map());
178
+ for (const font of contentValue.fonts) {
179
+ if (isString(font.id) && font.id.match(fontIdRegex)) {
180
+ const fontId = font.id;
181
+ let fontWeight = undefined;
182
+ if (isString(font.weight) && font.weight.match(fontWeightRegex)) {
183
+ fontWeight = font.weight;
184
+ }
185
+ else {
186
+ warnings.push(( nls.localize(
187
+ 'error.fontWeight',
188
+ 'Invalid font weight in font \'{0}\'. Ignoring setting.',
189
+ font.id
190
+ )));
191
+ }
192
+ let fontStyle = undefined;
193
+ if (isString(font.style) && font.style.match(fontStyleRegex)) {
194
+ fontStyle = font.style;
195
+ }
196
+ else {
197
+ warnings.push(( nls.localize(
198
+ 'error.fontStyle',
199
+ 'Invalid font style in font \'{0}\'. Ignoring setting.',
200
+ font.id
201
+ )));
202
+ }
203
+ const sanitizedSrc = [];
204
+ if (Array.isArray(font.src)) {
205
+ for (const s of font.src) {
206
+ if (isString(s.path) && isString(s.format) && s.format.match(fontFormatRegex)) {
207
+ const iconFontLocation = resources.joinPath(iconThemeDocumentLocationDirname, s.path);
208
+ sanitizedSrc.push({ location: iconFontLocation, format: s.format });
209
+ }
210
+ else {
211
+ warnings.push(( nls.localize(
212
+ 'error.fontSrc',
213
+ 'Invalid font source in font \'{0}\'. Ignoring source.',
214
+ font.id
215
+ )));
216
+ }
217
+ }
218
+ }
219
+ if (sanitizedSrc.length) {
220
+ sanitizedFonts.set(fontId, { weight: fontWeight, style: fontStyle, src: sanitizedSrc });
221
+ }
222
+ else {
223
+ warnings.push(( nls.localize(
224
+ 'error.noFontSrc',
225
+ 'No valid font source in font \'{0}\'. Ignoring font definition.',
226
+ font.id
227
+ )));
228
+ }
229
+ }
230
+ else {
231
+ warnings.push(( nls.localize(
232
+ 'error.fontId',
233
+ 'Missing or invalid font id \'{0}\'. Skipping font definition.',
234
+ font.id
235
+ )));
236
+ }
237
+ }
238
+ const iconDefinitions = ( new Map());
239
+ const primaryFontId = contentValue.fonts[0].id;
240
+ for (const iconId in contentValue.iconDefinitions) {
241
+ const definition = contentValue.iconDefinitions[iconId];
242
+ if (isString(definition.fontCharacter)) {
243
+ const fontId = definition.fontId ?? primaryFontId;
244
+ const fontDefinition = sanitizedFonts.get(fontId);
245
+ if (fontDefinition) {
246
+ const font = { id: `pi-${fontId}`, definition: fontDefinition };
247
+ iconDefinitions.set(iconId, { fontCharacter: definition.fontCharacter, font });
248
+ }
249
+ else {
250
+ warnings.push(( nls.localize(
251
+ 'error.icon.font',
252
+ 'Skipping icon definition \'{0}\'. Unknown font.',
253
+ iconId
254
+ )));
255
+ }
256
+ }
257
+ else {
258
+ warnings.push(( nls.localize(
259
+ 'error.icon.fontCharacter',
260
+ 'Skipping icon definition \'{0}\'. Unknown fontCharacter.',
261
+ iconId
262
+ )));
263
+ }
264
+ }
265
+ return { iconDefinitions };
266
+ });
267
+ }
268
+ const iconRegistry = getIconRegistry();
269
+ function _resolveIconDefinition(iconContribution, iconThemeDocument) {
270
+ const iconDefinitions = iconThemeDocument.iconDefinitions;
271
+ let definition = iconDefinitions.get(iconContribution.id);
272
+ let defaults = iconContribution.defaults;
273
+ while (!definition && ThemeIcon.isThemeIcon(defaults)) {
274
+ const ic = iconRegistry.getIcon(defaults.id);
275
+ if (ic) {
276
+ definition = iconDefinitions.get(ic.id);
277
+ defaults = ic.defaults;
278
+ }
279
+ else {
280
+ return undefined;
281
+ }
282
+ }
283
+ if (definition) {
284
+ return definition;
285
+ }
286
+ if (!ThemeIcon.isThemeIcon(defaults)) {
287
+ return defaults;
288
+ }
289
+ return undefined;
290
+ }
291
+
292
+ export { DEFAULT_PRODUCT_ICON_THEME_ID, ProductIconThemeData };