material-icon-theme 4.23.1 → 4.24.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.
- package/.eslintrc.json +51 -51
- package/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +7 -0
- package/.github/workflows/build.yml +45 -45
- package/.github/workflows/color-check.yml +22 -22
- package/.github/workflows/release.yml +73 -73
- package/.vscodeignore +21 -21
- package/CHANGELOG.md +1305 -1292
- package/CONTRIBUTING.md +199 -29
- package/README.md +199 -199
- package/icons/craco.svg +45 -45
- package/icons/folder-changesets-open.svg +5 -5
- package/icons/folder-changesets.svg +2 -2
- package/icons/folder-decorators-open.svg +2 -2
- package/icons/folder-decorators.svg +5 -5
- package/icons/folder-supabase-open.svg +5 -5
- package/icons/folder-supabase.svg +2 -2
- package/icons/sonarcloud.svg +4 -4
- package/icons/stylable.svg +10 -10
- package/icons/supabase.svg +4 -4
- package/icons/vitest.svg +6 -6
- package/images/contributors.png +0 -0
- package/images/how-tos/folder-icon-parts.png +0 -0
- package/images/how-tos/pick-folder-colors.png +0 -0
- package/images/how-tos/pick-folder-colors.svg +301 -0
- package/images/how-tos/svg-folder-icon-with-correct-colors.png +0 -0
- package/images/how-tos/svg-folder-icon-with-wrong-colors.png +0 -0
- package/images/how-tos/svg-with-light-color.png +0 -0
- package/images/how-tos/svg-with-spacing.png +0 -0
- package/images/how-tos/svg-with-too-dark-color.png +0 -0
- package/images/how-tos/svg-with-wrong-color.png +0 -0
- package/images/how-tos/svg-without-spacing.png +0 -0
- package/package.json +252 -252
- package/package.nls.de.json +32 -32
- package/package.nls.es.json +29 -29
- package/package.nls.fr.json +29 -29
- package/package.nls.ja.json +32 -32
- package/package.nls.json +32 -32
- package/package.nls.nl.json +32 -32
- package/package.nls.pl.json +32 -32
- package/package.nls.pt-BR.json +29 -29
- package/package.nls.pt-PT.json +29 -29
- package/package.nls.ru.json +29 -29
- package/package.nls.zh-CN.json +29 -29
- package/package.nls.zh-TW.json +29 -29
- package/src/commands/activate.ts +28 -28
- package/src/commands/explorerArrows.ts +55 -55
- package/src/commands/folderColor.ts +96 -96
- package/src/commands/folders.ts +55 -55
- package/src/commands/grayscale.ts +55 -55
- package/src/commands/iconPacks.ts +64 -64
- package/src/commands/index.ts +30 -30
- package/src/commands/opacity.ts +46 -46
- package/src/commands/saturation.ts +46 -46
- package/src/extension.ts +37 -37
- package/src/helpers/customIcons.ts +8 -8
- package/src/helpers/index.ts +88 -88
- package/src/i18n/index.ts +78 -78
- package/src/i18n/lang-de.ts +43 -43
- package/src/i18n/lang-en.ts +43 -43
- package/src/i18n/lang-es.ts +43 -43
- package/src/i18n/lang-fr.ts +43 -43
- package/src/i18n/lang-ja.ts +43 -43
- package/src/i18n/lang-nl.ts +43 -43
- package/src/i18n/lang-pl.ts +43 -43
- package/src/i18n/lang-pt-br.ts +43 -43
- package/src/i18n/lang-pt-pt.ts +43 -43
- package/src/i18n/lang-ru.ts +43 -43
- package/src/i18n/lang-uk.ts +43 -43
- package/src/i18n/lang-zh-cn.ts +43 -43
- package/src/i18n/lang-zh-tw.ts +43 -43
- package/src/icons/fileIcons.ts +2206 -2197
- package/src/icons/folderIcons.ts +818 -806
- package/src/icons/generator/folderGenerator.ts +340 -340
- package/src/icons/generator/iconOpacity.ts +111 -111
- package/src/icons/generator/iconSaturation.ts +140 -140
- package/src/icons/generator/jsonGenerator.ts +191 -191
- package/src/icons/languageIcons.ts +141 -141
- package/src/models/i18n/translation.ts +41 -41
- package/src/models/iconConfiguration.ts +37 -37
- package/src/models/icons/iconJsonOptions.ts +21 -21
- package/src/models/index.ts +3 -3
- package/src/scripts/contributors/index.ts +138 -138
- package/src/scripts/helpers/screenshots.ts +32 -32
- package/src/scripts/icons/checks/checkIconAvailability.ts +215 -215
- package/src/scripts/icons/checks/checkIconConflicts.ts +152 -152
- package/src/scripts/icons/checks/checkIconUsage.ts +137 -137
- package/src/scripts/icons/checks/index.ts +7 -7
- package/src/scripts/preview/index.ts +40 -40
- package/src/scripts/preview/preview.ts +163 -163
- package/src/test/runTest.ts +26 -26
- package/src/test/spec/i18n/i18n.spec.ts +54 -54
- package/src/test/spec/icons/fileIcons.spec.ts +250 -250
- package/src/test/spec/icons/folderIcons.spec.ts +418 -418
- package/src/test/spec/icons/languageIcons.spec.ts +184 -184
|
@@ -1,340 +1,340 @@
|
|
|
1
|
-
import { writeFileSync } from 'fs';
|
|
2
|
-
import merge from 'lodash.merge';
|
|
3
|
-
import { basename, join } from 'path';
|
|
4
|
-
import { getFileConfigHash } from '../../helpers/fileConfig';
|
|
5
|
-
import {
|
|
6
|
-
DefaultIcon,
|
|
7
|
-
FolderIcon,
|
|
8
|
-
FolderTheme,
|
|
9
|
-
IconAssociations,
|
|
10
|
-
IconConfiguration,
|
|
11
|
-
IconJsonOptions,
|
|
12
|
-
} from '../../models/index';
|
|
13
|
-
import {
|
|
14
|
-
highContrastColorFileEnding,
|
|
15
|
-
iconFolderPath,
|
|
16
|
-
lightColorFileEnding,
|
|
17
|
-
openedFolder,
|
|
18
|
-
} from './constants';
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Get the folder icon definitions as object.
|
|
22
|
-
*/
|
|
23
|
-
export const loadFolderIconDefinitions = (
|
|
24
|
-
folderThemes: FolderTheme[],
|
|
25
|
-
config: IconConfiguration,
|
|
26
|
-
options: IconJsonOptions
|
|
27
|
-
): IconConfiguration => {
|
|
28
|
-
config = merge({}, config);
|
|
29
|
-
config.hidesExplorerArrows = options.hidesExplorerArrows;
|
|
30
|
-
const activeTheme = getEnabledFolderTheme(
|
|
31
|
-
folderThemes,
|
|
32
|
-
options.folders?.theme
|
|
33
|
-
);
|
|
34
|
-
if (!activeTheme) {
|
|
35
|
-
return {};
|
|
36
|
-
}
|
|
37
|
-
const enabledIcons = disableIconsByPack(activeTheme, options.activeIconPack);
|
|
38
|
-
const customIcons = getCustomIcons(options.folders?.associations);
|
|
39
|
-
const allIcons = [...enabledIcons, ...customIcons];
|
|
40
|
-
|
|
41
|
-
if (options.folders?.theme === 'none') {
|
|
42
|
-
return config;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
allIcons.forEach((icon) => {
|
|
46
|
-
if (icon.disabled) return;
|
|
47
|
-
config = setIconDefinitions(config, icon);
|
|
48
|
-
config = merge({}, config, setFolderNames(icon.name, icon.folderNames));
|
|
49
|
-
config.light = icon.light
|
|
50
|
-
? merge(
|
|
51
|
-
{},
|
|
52
|
-
config.light,
|
|
53
|
-
setFolderNames(icon.name, icon.folderNames, lightColorFileEnding)
|
|
54
|
-
)
|
|
55
|
-
: config.light;
|
|
56
|
-
config.highContrast = icon.highContrast
|
|
57
|
-
? merge(
|
|
58
|
-
{},
|
|
59
|
-
config.highContrast,
|
|
60
|
-
setFolderNames(
|
|
61
|
-
icon.name,
|
|
62
|
-
icon.folderNames,
|
|
63
|
-
highContrastColorFileEnding
|
|
64
|
-
)
|
|
65
|
-
)
|
|
66
|
-
: config.highContrast;
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
config = setDefaultFolderIcons(activeTheme, config);
|
|
70
|
-
return config;
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Set the default folder icons for the theme.
|
|
75
|
-
*/
|
|
76
|
-
const setDefaultFolderIcons = (
|
|
77
|
-
theme: FolderTheme,
|
|
78
|
-
config: IconConfiguration
|
|
79
|
-
): IconConfiguration => {
|
|
80
|
-
config = merge({}, config);
|
|
81
|
-
const hasFolderIcons =
|
|
82
|
-
!!theme.defaultIcon.name && theme.defaultIcon.name.length > 0;
|
|
83
|
-
if (hasFolderIcons) {
|
|
84
|
-
config = setIconDefinitions(config, theme.defaultIcon);
|
|
85
|
-
}
|
|
86
|
-
config = merge(
|
|
87
|
-
{},
|
|
88
|
-
config,
|
|
89
|
-
createDefaultIconConfigObject(hasFolderIcons, theme, '')
|
|
90
|
-
);
|
|
91
|
-
config.light = theme.defaultIcon.light
|
|
92
|
-
? merge(
|
|
93
|
-
{},
|
|
94
|
-
config.light,
|
|
95
|
-
createDefaultIconConfigObject(
|
|
96
|
-
hasFolderIcons,
|
|
97
|
-
theme,
|
|
98
|
-
lightColorFileEnding
|
|
99
|
-
)
|
|
100
|
-
)
|
|
101
|
-
: config.light;
|
|
102
|
-
config.highContrast = theme.defaultIcon.highContrast
|
|
103
|
-
? merge(
|
|
104
|
-
{},
|
|
105
|
-
config.highContrast,
|
|
106
|
-
createDefaultIconConfigObject(
|
|
107
|
-
hasFolderIcons,
|
|
108
|
-
theme,
|
|
109
|
-
highContrastColorFileEnding
|
|
110
|
-
)
|
|
111
|
-
)
|
|
112
|
-
: config.highContrast;
|
|
113
|
-
|
|
114
|
-
config = merge(
|
|
115
|
-
{},
|
|
116
|
-
config,
|
|
117
|
-
createRootIconConfigObject(hasFolderIcons, theme, '')
|
|
118
|
-
);
|
|
119
|
-
if (theme.rootFolder) {
|
|
120
|
-
config = setIconDefinitions(config, theme.rootFolder);
|
|
121
|
-
config.light = theme.rootFolder.light
|
|
122
|
-
? merge(
|
|
123
|
-
{},
|
|
124
|
-
config.light,
|
|
125
|
-
createRootIconConfigObject(
|
|
126
|
-
hasFolderIcons,
|
|
127
|
-
theme,
|
|
128
|
-
lightColorFileEnding
|
|
129
|
-
)
|
|
130
|
-
)
|
|
131
|
-
: config.light;
|
|
132
|
-
config.highContrast = theme.rootFolder.highContrast
|
|
133
|
-
? merge(
|
|
134
|
-
{},
|
|
135
|
-
config.highContrast,
|
|
136
|
-
createRootIconConfigObject(
|
|
137
|
-
hasFolderIcons,
|
|
138
|
-
theme,
|
|
139
|
-
highContrastColorFileEnding
|
|
140
|
-
)
|
|
141
|
-
)
|
|
142
|
-
: config.highContrast;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return config;
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Get the object of the current enabled theme.
|
|
150
|
-
*/
|
|
151
|
-
const getEnabledFolderTheme = (
|
|
152
|
-
themes: FolderTheme[],
|
|
153
|
-
enabledTheme: string | undefined
|
|
154
|
-
): FolderTheme | undefined => {
|
|
155
|
-
return themes.find((theme) => theme.name === enabledTheme);
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Disable all file icons that are in a pack which is disabled.
|
|
160
|
-
*/
|
|
161
|
-
const disableIconsByPack = (
|
|
162
|
-
folderIcons: FolderTheme | undefined,
|
|
163
|
-
activatedIconPack: string | undefined
|
|
164
|
-
): FolderIcon[] => {
|
|
165
|
-
if (!folderIcons?.icons || folderIcons.icons.length === 0) {
|
|
166
|
-
return [];
|
|
167
|
-
}
|
|
168
|
-
return folderIcons.icons.filter((icon) => {
|
|
169
|
-
return !icon.enabledFor
|
|
170
|
-
? true
|
|
171
|
-
: icon.enabledFor.some((p) => p === activatedIconPack);
|
|
172
|
-
});
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
const setIconDefinitions = (
|
|
176
|
-
config: IconConfiguration,
|
|
177
|
-
icon: FolderIcon | DefaultIcon
|
|
178
|
-
) => {
|
|
179
|
-
config = merge({}, config);
|
|
180
|
-
config = createIconDefinitions(config, icon.name);
|
|
181
|
-
if (icon.light) {
|
|
182
|
-
config = merge(
|
|
183
|
-
{},
|
|
184
|
-
config,
|
|
185
|
-
createIconDefinitions(config, icon.name, lightColorFileEnding)
|
|
186
|
-
);
|
|
187
|
-
}
|
|
188
|
-
if (icon.highContrast) {
|
|
189
|
-
config = merge(
|
|
190
|
-
{},
|
|
191
|
-
config,
|
|
192
|
-
createIconDefinitions(config, icon.name, highContrastColorFileEnding)
|
|
193
|
-
);
|
|
194
|
-
}
|
|
195
|
-
return config;
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
const createIconDefinitions = (
|
|
199
|
-
config: IconConfiguration,
|
|
200
|
-
iconName: string,
|
|
201
|
-
appendix: string = ''
|
|
202
|
-
) => {
|
|
203
|
-
config = merge({}, config);
|
|
204
|
-
const fileConfigHash = getFileConfigHash(config.options ?? {});
|
|
205
|
-
const configIconDefinitions = config.iconDefinitions;
|
|
206
|
-
if (configIconDefinitions) {
|
|
207
|
-
configIconDefinitions[iconName + appendix] = {
|
|
208
|
-
iconPath: `${iconFolderPath}${iconName}${appendix}${fileConfigHash}.svg`,
|
|
209
|
-
};
|
|
210
|
-
configIconDefinitions[`${iconName}${openedFolder}${appendix}`] = {
|
|
211
|
-
iconPath: `${iconFolderPath}${iconName}${openedFolder}${appendix}${fileConfigHash}.svg`,
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
return config;
|
|
215
|
-
};
|
|
216
|
-
|
|
217
|
-
const setFolderNames = (
|
|
218
|
-
iconName: string,
|
|
219
|
-
folderNames: string[],
|
|
220
|
-
appendix: string = ''
|
|
221
|
-
) => {
|
|
222
|
-
const obj: Partial<IconConfiguration> = {
|
|
223
|
-
folderNames: {},
|
|
224
|
-
folderNamesExpanded: {},
|
|
225
|
-
};
|
|
226
|
-
folderNames.forEach((name) => {
|
|
227
|
-
if (obj.folderNames) {
|
|
228
|
-
obj.folderNames[name as keyof IconConfiguration] = iconName + appendix;
|
|
229
|
-
}
|
|
230
|
-
if (obj.folderNamesExpanded) {
|
|
231
|
-
obj.folderNamesExpanded[
|
|
232
|
-
name as keyof IconConfiguration
|
|
233
|
-
] = `${iconName}${openedFolder}${appendix}`;
|
|
234
|
-
}
|
|
235
|
-
});
|
|
236
|
-
return obj;
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
const createDefaultIconConfigObject = (
|
|
240
|
-
hasFolderIcons: boolean,
|
|
241
|
-
theme: FolderTheme,
|
|
242
|
-
appendix: string = ''
|
|
243
|
-
) => {
|
|
244
|
-
const obj = {
|
|
245
|
-
folder: '',
|
|
246
|
-
folderExpanded: '',
|
|
247
|
-
};
|
|
248
|
-
obj.folder = hasFolderIcons ? theme.defaultIcon.name + appendix : '';
|
|
249
|
-
obj.folderExpanded = hasFolderIcons
|
|
250
|
-
? `${theme.defaultIcon.name}${openedFolder}${appendix}`
|
|
251
|
-
: '';
|
|
252
|
-
return obj;
|
|
253
|
-
};
|
|
254
|
-
|
|
255
|
-
const createRootIconConfigObject = (
|
|
256
|
-
hasFolderIcons: boolean,
|
|
257
|
-
theme: FolderTheme,
|
|
258
|
-
appendix: string = ''
|
|
259
|
-
) => {
|
|
260
|
-
const obj = {
|
|
261
|
-
rootFolder: '',
|
|
262
|
-
rootFolderExpanded: '',
|
|
263
|
-
};
|
|
264
|
-
obj.rootFolder = hasFolderIcons
|
|
265
|
-
? theme.rootFolder
|
|
266
|
-
? theme.rootFolder.name + appendix
|
|
267
|
-
: theme.defaultIcon.name + appendix
|
|
268
|
-
: '';
|
|
269
|
-
obj.rootFolderExpanded = hasFolderIcons
|
|
270
|
-
? theme.rootFolder
|
|
271
|
-
? `${theme.rootFolder.name}${openedFolder}${appendix}`
|
|
272
|
-
: `${theme.defaultIcon.name}${openedFolder}${appendix}`
|
|
273
|
-
: '';
|
|
274
|
-
return obj;
|
|
275
|
-
};
|
|
276
|
-
|
|
277
|
-
const getCustomIcons = (folderAssociations: IconAssociations | undefined) => {
|
|
278
|
-
if (!folderAssociations) return [];
|
|
279
|
-
|
|
280
|
-
const icons: FolderIcon[] = Object.keys(folderAssociations).map((fa) => ({
|
|
281
|
-
// use default folder if icon name is empty
|
|
282
|
-
name:
|
|
283
|
-
folderAssociations[fa].length > 0
|
|
284
|
-
? 'folder-' + folderAssociations[fa].toLowerCase()
|
|
285
|
-
: 'folder',
|
|
286
|
-
folderNames: [fa.toLowerCase()],
|
|
287
|
-
}));
|
|
288
|
-
|
|
289
|
-
return icons;
|
|
290
|
-
};
|
|
291
|
-
|
|
292
|
-
export const generateFolderIcons = (color: string | undefined) => {
|
|
293
|
-
if (!color || !validateHEXColorCode(color)) {
|
|
294
|
-
return console.error('Invalid color code for folder icons');
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
const folderIcon =
|
|
298
|
-
'M10 4H4c-1.11 0-2 .89-2 2v12a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8c0-1.11-.9-2-2-2h-8l-2-2z';
|
|
299
|
-
const folderIconOpen =
|
|
300
|
-
'M19 20H4c-1.11 0-2-.9-2-2V6c0-1.11.89-2 2-2h6l2 2h7a2 2 0 0 1 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z';
|
|
301
|
-
const rootFolderIcon =
|
|
302
|
-
'M12 20a8 8 0 0 1-8-8 8 8 0 0 1 8-8 8 8 0 0 1 8 8 8 8 0 0 1-8 8m0-18A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10A10 10 0 0 0 12 2m0 5a5 5 0 0 0-5 5 5 5 0 0 0 5 5 5 5 0 0 0 5-5 5 5 0 0 0-5-5z';
|
|
303
|
-
const rootFolderIconOpen =
|
|
304
|
-
'M12 20a8 8 0 0 1-8-8 8 8 0 0 1 8-8 8 8 0 0 1 8 8 8 8 0 0 1-8 8m0-18A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10A10 10 0 0 0 12 2z';
|
|
305
|
-
|
|
306
|
-
writeSVGFiles('folder', getSVG(getPath(folderIcon, color)));
|
|
307
|
-
writeSVGFiles('folder-open', getSVG(getPath(folderIconOpen, color)));
|
|
308
|
-
writeSVGFiles('folder-root', getSVG(getPath(rootFolderIcon, color)));
|
|
309
|
-
writeSVGFiles('folder-root-open', getSVG(getPath(rootFolderIconOpen, color)));
|
|
310
|
-
};
|
|
311
|
-
|
|
312
|
-
const getPath = (d: string, color: string) =>
|
|
313
|
-
`<path d="${d}" fill="${color}" />`;
|
|
314
|
-
const getSVG = (path: string) =>
|
|
315
|
-
`<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">${path}</svg>`;
|
|
316
|
-
|
|
317
|
-
const writeSVGFiles = (iconName: string, svg: string) => {
|
|
318
|
-
let iconsPath;
|
|
319
|
-
if (basename(__dirname) === 'dist') {
|
|
320
|
-
iconsPath = join(__dirname, '..', 'icons');
|
|
321
|
-
} else {
|
|
322
|
-
// executed via script
|
|
323
|
-
iconsPath = join(__dirname, '..', '..', '..', 'icons');
|
|
324
|
-
}
|
|
325
|
-
const iconsFolderPath = join(iconsPath, `${iconName}.svg`);
|
|
326
|
-
try {
|
|
327
|
-
writeFileSync(iconsFolderPath, svg);
|
|
328
|
-
} catch (error) {
|
|
329
|
-
console.error(error);
|
|
330
|
-
}
|
|
331
|
-
};
|
|
332
|
-
|
|
333
|
-
/**
|
|
334
|
-
* Validate the HEX color code
|
|
335
|
-
* @param color HEX code
|
|
336
|
-
*/
|
|
337
|
-
export const validateHEXColorCode = (color: string = '') => {
|
|
338
|
-
const hexPattern = new RegExp(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/);
|
|
339
|
-
return color.length > 0 && hexPattern.test(color);
|
|
340
|
-
};
|
|
1
|
+
import { writeFileSync } from 'fs';
|
|
2
|
+
import merge from 'lodash.merge';
|
|
3
|
+
import { basename, join } from 'path';
|
|
4
|
+
import { getFileConfigHash } from '../../helpers/fileConfig';
|
|
5
|
+
import {
|
|
6
|
+
DefaultIcon,
|
|
7
|
+
FolderIcon,
|
|
8
|
+
FolderTheme,
|
|
9
|
+
IconAssociations,
|
|
10
|
+
IconConfiguration,
|
|
11
|
+
IconJsonOptions,
|
|
12
|
+
} from '../../models/index';
|
|
13
|
+
import {
|
|
14
|
+
highContrastColorFileEnding,
|
|
15
|
+
iconFolderPath,
|
|
16
|
+
lightColorFileEnding,
|
|
17
|
+
openedFolder,
|
|
18
|
+
} from './constants';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Get the folder icon definitions as object.
|
|
22
|
+
*/
|
|
23
|
+
export const loadFolderIconDefinitions = (
|
|
24
|
+
folderThemes: FolderTheme[],
|
|
25
|
+
config: IconConfiguration,
|
|
26
|
+
options: IconJsonOptions
|
|
27
|
+
): IconConfiguration => {
|
|
28
|
+
config = merge({}, config);
|
|
29
|
+
config.hidesExplorerArrows = options.hidesExplorerArrows;
|
|
30
|
+
const activeTheme = getEnabledFolderTheme(
|
|
31
|
+
folderThemes,
|
|
32
|
+
options.folders?.theme
|
|
33
|
+
);
|
|
34
|
+
if (!activeTheme) {
|
|
35
|
+
return {};
|
|
36
|
+
}
|
|
37
|
+
const enabledIcons = disableIconsByPack(activeTheme, options.activeIconPack);
|
|
38
|
+
const customIcons = getCustomIcons(options.folders?.associations);
|
|
39
|
+
const allIcons = [...enabledIcons, ...customIcons];
|
|
40
|
+
|
|
41
|
+
if (options.folders?.theme === 'none') {
|
|
42
|
+
return config;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
allIcons.forEach((icon) => {
|
|
46
|
+
if (icon.disabled) return;
|
|
47
|
+
config = setIconDefinitions(config, icon);
|
|
48
|
+
config = merge({}, config, setFolderNames(icon.name, icon.folderNames));
|
|
49
|
+
config.light = icon.light
|
|
50
|
+
? merge(
|
|
51
|
+
{},
|
|
52
|
+
config.light,
|
|
53
|
+
setFolderNames(icon.name, icon.folderNames, lightColorFileEnding)
|
|
54
|
+
)
|
|
55
|
+
: config.light;
|
|
56
|
+
config.highContrast = icon.highContrast
|
|
57
|
+
? merge(
|
|
58
|
+
{},
|
|
59
|
+
config.highContrast,
|
|
60
|
+
setFolderNames(
|
|
61
|
+
icon.name,
|
|
62
|
+
icon.folderNames,
|
|
63
|
+
highContrastColorFileEnding
|
|
64
|
+
)
|
|
65
|
+
)
|
|
66
|
+
: config.highContrast;
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
config = setDefaultFolderIcons(activeTheme, config);
|
|
70
|
+
return config;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Set the default folder icons for the theme.
|
|
75
|
+
*/
|
|
76
|
+
const setDefaultFolderIcons = (
|
|
77
|
+
theme: FolderTheme,
|
|
78
|
+
config: IconConfiguration
|
|
79
|
+
): IconConfiguration => {
|
|
80
|
+
config = merge({}, config);
|
|
81
|
+
const hasFolderIcons =
|
|
82
|
+
!!theme.defaultIcon.name && theme.defaultIcon.name.length > 0;
|
|
83
|
+
if (hasFolderIcons) {
|
|
84
|
+
config = setIconDefinitions(config, theme.defaultIcon);
|
|
85
|
+
}
|
|
86
|
+
config = merge(
|
|
87
|
+
{},
|
|
88
|
+
config,
|
|
89
|
+
createDefaultIconConfigObject(hasFolderIcons, theme, '')
|
|
90
|
+
);
|
|
91
|
+
config.light = theme.defaultIcon.light
|
|
92
|
+
? merge(
|
|
93
|
+
{},
|
|
94
|
+
config.light,
|
|
95
|
+
createDefaultIconConfigObject(
|
|
96
|
+
hasFolderIcons,
|
|
97
|
+
theme,
|
|
98
|
+
lightColorFileEnding
|
|
99
|
+
)
|
|
100
|
+
)
|
|
101
|
+
: config.light;
|
|
102
|
+
config.highContrast = theme.defaultIcon.highContrast
|
|
103
|
+
? merge(
|
|
104
|
+
{},
|
|
105
|
+
config.highContrast,
|
|
106
|
+
createDefaultIconConfigObject(
|
|
107
|
+
hasFolderIcons,
|
|
108
|
+
theme,
|
|
109
|
+
highContrastColorFileEnding
|
|
110
|
+
)
|
|
111
|
+
)
|
|
112
|
+
: config.highContrast;
|
|
113
|
+
|
|
114
|
+
config = merge(
|
|
115
|
+
{},
|
|
116
|
+
config,
|
|
117
|
+
createRootIconConfigObject(hasFolderIcons, theme, '')
|
|
118
|
+
);
|
|
119
|
+
if (theme.rootFolder) {
|
|
120
|
+
config = setIconDefinitions(config, theme.rootFolder);
|
|
121
|
+
config.light = theme.rootFolder.light
|
|
122
|
+
? merge(
|
|
123
|
+
{},
|
|
124
|
+
config.light,
|
|
125
|
+
createRootIconConfigObject(
|
|
126
|
+
hasFolderIcons,
|
|
127
|
+
theme,
|
|
128
|
+
lightColorFileEnding
|
|
129
|
+
)
|
|
130
|
+
)
|
|
131
|
+
: config.light;
|
|
132
|
+
config.highContrast = theme.rootFolder.highContrast
|
|
133
|
+
? merge(
|
|
134
|
+
{},
|
|
135
|
+
config.highContrast,
|
|
136
|
+
createRootIconConfigObject(
|
|
137
|
+
hasFolderIcons,
|
|
138
|
+
theme,
|
|
139
|
+
highContrastColorFileEnding
|
|
140
|
+
)
|
|
141
|
+
)
|
|
142
|
+
: config.highContrast;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return config;
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Get the object of the current enabled theme.
|
|
150
|
+
*/
|
|
151
|
+
const getEnabledFolderTheme = (
|
|
152
|
+
themes: FolderTheme[],
|
|
153
|
+
enabledTheme: string | undefined
|
|
154
|
+
): FolderTheme | undefined => {
|
|
155
|
+
return themes.find((theme) => theme.name === enabledTheme);
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Disable all file icons that are in a pack which is disabled.
|
|
160
|
+
*/
|
|
161
|
+
const disableIconsByPack = (
|
|
162
|
+
folderIcons: FolderTheme | undefined,
|
|
163
|
+
activatedIconPack: string | undefined
|
|
164
|
+
): FolderIcon[] => {
|
|
165
|
+
if (!folderIcons?.icons || folderIcons.icons.length === 0) {
|
|
166
|
+
return [];
|
|
167
|
+
}
|
|
168
|
+
return folderIcons.icons.filter((icon) => {
|
|
169
|
+
return !icon.enabledFor
|
|
170
|
+
? true
|
|
171
|
+
: icon.enabledFor.some((p) => p === activatedIconPack);
|
|
172
|
+
});
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
const setIconDefinitions = (
|
|
176
|
+
config: IconConfiguration,
|
|
177
|
+
icon: FolderIcon | DefaultIcon
|
|
178
|
+
) => {
|
|
179
|
+
config = merge({}, config);
|
|
180
|
+
config = createIconDefinitions(config, icon.name);
|
|
181
|
+
if (icon.light) {
|
|
182
|
+
config = merge(
|
|
183
|
+
{},
|
|
184
|
+
config,
|
|
185
|
+
createIconDefinitions(config, icon.name, lightColorFileEnding)
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
if (icon.highContrast) {
|
|
189
|
+
config = merge(
|
|
190
|
+
{},
|
|
191
|
+
config,
|
|
192
|
+
createIconDefinitions(config, icon.name, highContrastColorFileEnding)
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
return config;
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
const createIconDefinitions = (
|
|
199
|
+
config: IconConfiguration,
|
|
200
|
+
iconName: string,
|
|
201
|
+
appendix: string = ''
|
|
202
|
+
) => {
|
|
203
|
+
config = merge({}, config);
|
|
204
|
+
const fileConfigHash = getFileConfigHash(config.options ?? {});
|
|
205
|
+
const configIconDefinitions = config.iconDefinitions;
|
|
206
|
+
if (configIconDefinitions) {
|
|
207
|
+
configIconDefinitions[iconName + appendix] = {
|
|
208
|
+
iconPath: `${iconFolderPath}${iconName}${appendix}${fileConfigHash}.svg`,
|
|
209
|
+
};
|
|
210
|
+
configIconDefinitions[`${iconName}${openedFolder}${appendix}`] = {
|
|
211
|
+
iconPath: `${iconFolderPath}${iconName}${openedFolder}${appendix}${fileConfigHash}.svg`,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
return config;
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
const setFolderNames = (
|
|
218
|
+
iconName: string,
|
|
219
|
+
folderNames: string[],
|
|
220
|
+
appendix: string = ''
|
|
221
|
+
) => {
|
|
222
|
+
const obj: Partial<IconConfiguration> = {
|
|
223
|
+
folderNames: {},
|
|
224
|
+
folderNamesExpanded: {},
|
|
225
|
+
};
|
|
226
|
+
folderNames.forEach((name) => {
|
|
227
|
+
if (obj.folderNames) {
|
|
228
|
+
obj.folderNames[name as keyof IconConfiguration] = iconName + appendix;
|
|
229
|
+
}
|
|
230
|
+
if (obj.folderNamesExpanded) {
|
|
231
|
+
obj.folderNamesExpanded[
|
|
232
|
+
name as keyof IconConfiguration
|
|
233
|
+
] = `${iconName}${openedFolder}${appendix}`;
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
return obj;
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
const createDefaultIconConfigObject = (
|
|
240
|
+
hasFolderIcons: boolean,
|
|
241
|
+
theme: FolderTheme,
|
|
242
|
+
appendix: string = ''
|
|
243
|
+
) => {
|
|
244
|
+
const obj = {
|
|
245
|
+
folder: '',
|
|
246
|
+
folderExpanded: '',
|
|
247
|
+
};
|
|
248
|
+
obj.folder = hasFolderIcons ? theme.defaultIcon.name + appendix : '';
|
|
249
|
+
obj.folderExpanded = hasFolderIcons
|
|
250
|
+
? `${theme.defaultIcon.name}${openedFolder}${appendix}`
|
|
251
|
+
: '';
|
|
252
|
+
return obj;
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
const createRootIconConfigObject = (
|
|
256
|
+
hasFolderIcons: boolean,
|
|
257
|
+
theme: FolderTheme,
|
|
258
|
+
appendix: string = ''
|
|
259
|
+
) => {
|
|
260
|
+
const obj = {
|
|
261
|
+
rootFolder: '',
|
|
262
|
+
rootFolderExpanded: '',
|
|
263
|
+
};
|
|
264
|
+
obj.rootFolder = hasFolderIcons
|
|
265
|
+
? theme.rootFolder
|
|
266
|
+
? theme.rootFolder.name + appendix
|
|
267
|
+
: theme.defaultIcon.name + appendix
|
|
268
|
+
: '';
|
|
269
|
+
obj.rootFolderExpanded = hasFolderIcons
|
|
270
|
+
? theme.rootFolder
|
|
271
|
+
? `${theme.rootFolder.name}${openedFolder}${appendix}`
|
|
272
|
+
: `${theme.defaultIcon.name}${openedFolder}${appendix}`
|
|
273
|
+
: '';
|
|
274
|
+
return obj;
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
const getCustomIcons = (folderAssociations: IconAssociations | undefined) => {
|
|
278
|
+
if (!folderAssociations) return [];
|
|
279
|
+
|
|
280
|
+
const icons: FolderIcon[] = Object.keys(folderAssociations).map((fa) => ({
|
|
281
|
+
// use default folder if icon name is empty
|
|
282
|
+
name:
|
|
283
|
+
folderAssociations[fa].length > 0
|
|
284
|
+
? 'folder-' + folderAssociations[fa].toLowerCase()
|
|
285
|
+
: 'folder',
|
|
286
|
+
folderNames: [fa.toLowerCase()],
|
|
287
|
+
}));
|
|
288
|
+
|
|
289
|
+
return icons;
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
export const generateFolderIcons = (color: string | undefined) => {
|
|
293
|
+
if (!color || !validateHEXColorCode(color)) {
|
|
294
|
+
return console.error('Invalid color code for folder icons');
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const folderIcon =
|
|
298
|
+
'M10 4H4c-1.11 0-2 .89-2 2v12a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8c0-1.11-.9-2-2-2h-8l-2-2z';
|
|
299
|
+
const folderIconOpen =
|
|
300
|
+
'M19 20H4c-1.11 0-2-.9-2-2V6c0-1.11.89-2 2-2h6l2 2h7a2 2 0 0 1 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z';
|
|
301
|
+
const rootFolderIcon =
|
|
302
|
+
'M12 20a8 8 0 0 1-8-8 8 8 0 0 1 8-8 8 8 0 0 1 8 8 8 8 0 0 1-8 8m0-18A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10A10 10 0 0 0 12 2m0 5a5 5 0 0 0-5 5 5 5 0 0 0 5 5 5 5 0 0 0 5-5 5 5 0 0 0-5-5z';
|
|
303
|
+
const rootFolderIconOpen =
|
|
304
|
+
'M12 20a8 8 0 0 1-8-8 8 8 0 0 1 8-8 8 8 0 0 1 8 8 8 8 0 0 1-8 8m0-18A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10A10 10 0 0 0 12 2z';
|
|
305
|
+
|
|
306
|
+
writeSVGFiles('folder', getSVG(getPath(folderIcon, color)));
|
|
307
|
+
writeSVGFiles('folder-open', getSVG(getPath(folderIconOpen, color)));
|
|
308
|
+
writeSVGFiles('folder-root', getSVG(getPath(rootFolderIcon, color)));
|
|
309
|
+
writeSVGFiles('folder-root-open', getSVG(getPath(rootFolderIconOpen, color)));
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
const getPath = (d: string, color: string) =>
|
|
313
|
+
`<path d="${d}" fill="${color}" />`;
|
|
314
|
+
const getSVG = (path: string) =>
|
|
315
|
+
`<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">${path}</svg>`;
|
|
316
|
+
|
|
317
|
+
const writeSVGFiles = (iconName: string, svg: string) => {
|
|
318
|
+
let iconsPath;
|
|
319
|
+
if (basename(__dirname) === 'dist') {
|
|
320
|
+
iconsPath = join(__dirname, '..', 'icons');
|
|
321
|
+
} else {
|
|
322
|
+
// executed via script
|
|
323
|
+
iconsPath = join(__dirname, '..', '..', '..', 'icons');
|
|
324
|
+
}
|
|
325
|
+
const iconsFolderPath = join(iconsPath, `${iconName}.svg`);
|
|
326
|
+
try {
|
|
327
|
+
writeFileSync(iconsFolderPath, svg);
|
|
328
|
+
} catch (error) {
|
|
329
|
+
console.error(error);
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Validate the HEX color code
|
|
335
|
+
* @param color HEX code
|
|
336
|
+
*/
|
|
337
|
+
export const validateHEXColorCode = (color: string = '') => {
|
|
338
|
+
const hexPattern = new RegExp(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/);
|
|
339
|
+
return color.length > 0 && hexPattern.test(color);
|
|
340
|
+
};
|