material-icon-theme 4.18.0 → 4.18.1

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.
Files changed (202) hide show
  1. package/.eslintrc.json +51 -51
  2. package/.github/FUNDING.yml +3 -3
  3. package/.github/ISSUE_TEMPLATE/bug_report.md +34 -34
  4. package/.github/ISSUE_TEMPLATE/icon_request.md +27 -27
  5. package/.github/workflows/build.yml +45 -45
  6. package/.github/workflows/color-check.yml +22 -22
  7. package/.github/workflows/release.yml +73 -73
  8. package/.prettierrc +7 -7
  9. package/.vscode/extensions.json +3 -3
  10. package/.vscode/launch.json +43 -43
  11. package/.vscode/settings.json +14 -14
  12. package/.vscode/tasks.json +32 -32
  13. package/.vscodeignore +20 -20
  14. package/CHANGELOG.md +1179 -1171
  15. package/CONTRIBUTING.md +62 -62
  16. package/LICENSE.md +8 -8
  17. package/README.md +208 -208
  18. package/build/web-extension.webpack.config.js +62 -62
  19. package/build/webpack.config.js +39 -39
  20. package/changelog.config.json +4 -4
  21. package/icons/architecture.svg +4 -4
  22. package/icons/astyle.svg +4 -4
  23. package/icons/auto.svg +10 -0
  24. package/icons/auto_light.svg +10 -0
  25. package/icons/azure.svg +9 -9
  26. package/icons/blitz.svg +4 -4
  27. package/icons/buildkite.svg +8 -8
  28. package/icons/cypress.svg +4 -4
  29. package/icons/dart_generated.svg +9 -9
  30. package/icons/dependabot.svg +4 -4
  31. package/icons/dinophp.svg +16 -16
  32. package/icons/figma.svg +10 -10
  33. package/icons/folder-angular-open.svg +2 -2
  34. package/icons/folder-angular.svg +2 -2
  35. package/icons/folder-buildkite-open.svg +8 -8
  36. package/icons/folder-buildkite.svg +7 -7
  37. package/icons/folder-cypress-open.svg +5 -5
  38. package/icons/folder-cypress.svg +5 -5
  39. package/icons/folder-java-open.svg +2 -2
  40. package/icons/folder-java.svg +2 -2
  41. package/icons/folder-next-open.svg +2 -2
  42. package/icons/folder-next.svg +2 -2
  43. package/icons/folder-nuxt-open.svg +2 -2
  44. package/icons/folder-nuxt.svg +2 -2
  45. package/icons/folder-queue-open.svg +2 -2
  46. package/icons/folder-queue.svg +2 -2
  47. package/icons/folder-resolver-open.svg +2 -2
  48. package/icons/folder-resolver.svg +2 -2
  49. package/icons/folder-serverless-open.svg +5 -5
  50. package/icons/folder-serverless.svg +5 -5
  51. package/icons/folder-shader-open.svg +7 -7
  52. package/icons/folder-shader.svg +6 -6
  53. package/icons/folder-target-open.svg +2 -2
  54. package/icons/folder-target.svg +2 -2
  55. package/icons/folder-unity-open.svg +2 -2
  56. package/icons/folder-unity.svg +2 -2
  57. package/icons/folder-vercel-open.svg +4 -4
  58. package/icons/folder-vercel.svg +4 -4
  59. package/icons/folder-verdaccio-open.svg +8 -8
  60. package/icons/folder-verdaccio.svg +8 -8
  61. package/icons/gleam.svg +4 -4
  62. package/icons/gridsome.svg +4 -4
  63. package/icons/hardhat.svg +3 -3
  64. package/icons/lighthouse.svg +2 -2
  65. package/icons/ndst.svg +7 -7
  66. package/icons/next.svg +3 -3
  67. package/icons/next_light.svg +2 -2
  68. package/icons/nuxt.svg +5 -5
  69. package/icons/odin.svg +6 -6
  70. package/icons/otne.svg +16 -16
  71. package/icons/parcel.svg +4 -4
  72. package/icons/playwright.svg +7 -7
  73. package/icons/plop.svg +4 -4
  74. package/icons/pnpm.svg +9 -9
  75. package/icons/pnpm_light.svg +7 -7
  76. package/icons/poetry.svg +1 -1
  77. package/icons/processing.svg +10 -10
  78. package/icons/remix.svg +4 -4
  79. package/icons/remix_light.svg +4 -4
  80. package/icons/rescript-interface.svg +5 -5
  81. package/icons/rome.svg +5 -5
  82. package/icons/serverless.svg +4 -4
  83. package/icons/shader.svg +4 -4
  84. package/icons/siyuan.svg +9 -9
  85. package/icons/steadybit.svg +1 -1
  86. package/icons/svgr.svg +4 -4
  87. package/icons/tauri.svg +9 -9
  88. package/icons/template.svg +4 -4
  89. package/icons/tobi.svg +4 -4
  90. package/icons/tobimake.svg +14 -14
  91. package/icons/turborepo.svg +12 -12
  92. package/icons/turborepo_light.svg +12 -12
  93. package/icons/verdaccio.svg +5 -5
  94. package/images/contributors.png +0 -0
  95. package/images/fileIcons.png +0 -0
  96. package/logo.svg +21 -21
  97. package/material-colors.yml +257 -257
  98. package/package.json +267 -264
  99. package/package.nls.de.json +35 -35
  100. package/package.nls.es.json +32 -32
  101. package/package.nls.fr.json +32 -32
  102. package/package.nls.ja.json +35 -35
  103. package/package.nls.json +35 -35
  104. package/package.nls.nl.json +35 -35
  105. package/package.nls.pl.json +35 -35
  106. package/package.nls.pt-BR.json +32 -32
  107. package/package.nls.pt-PT.json +32 -32
  108. package/package.nls.ru.json +32 -32
  109. package/package.nls.zh-CN.json +32 -32
  110. package/package.nls.zh-TW.json +32 -32
  111. package/src/commands/activate.ts +26 -26
  112. package/src/commands/explorerArrows.ts +55 -55
  113. package/src/commands/folderColor.ts +96 -96
  114. package/src/commands/folders.ts +55 -55
  115. package/src/commands/grayscale.ts +55 -55
  116. package/src/commands/iconPacks.ts +68 -68
  117. package/src/commands/index.ts +30 -30
  118. package/src/commands/opacity.ts +46 -46
  119. package/src/commands/restoreConfig.ts +14 -14
  120. package/src/commands/saturation.ts +46 -46
  121. package/src/extension.ts +42 -42
  122. package/src/helpers/changeDetection.ts +105 -73
  123. package/src/helpers/customIcons.ts +8 -8
  124. package/src/helpers/fileConfig.ts +37 -37
  125. package/src/helpers/index.ts +100 -100
  126. package/src/helpers/objects.ts +58 -58
  127. package/src/helpers/types.ts +7 -7
  128. package/src/helpers/versioning.ts +73 -73
  129. package/src/i18n/index.ts +78 -78
  130. package/src/i18n/lang-de.ts +54 -54
  131. package/src/i18n/lang-en.ts +53 -53
  132. package/src/i18n/lang-es.ts +53 -53
  133. package/src/i18n/lang-fr.ts +53 -53
  134. package/src/i18n/lang-ja.ts +54 -54
  135. package/src/i18n/lang-nl.ts +54 -54
  136. package/src/i18n/lang-pl.ts +52 -52
  137. package/src/i18n/lang-pt-br.ts +53 -53
  138. package/src/i18n/lang-pt-pt.ts +53 -53
  139. package/src/i18n/lang-ru.ts +52 -52
  140. package/src/i18n/lang-uk.ts +54 -54
  141. package/src/i18n/lang-zh-cn.ts +52 -52
  142. package/src/i18n/lang-zh-tw.ts +52 -52
  143. package/src/icons/fileIcons.ts +2060 -2046
  144. package/src/icons/folderIcons.ts +773 -773
  145. package/src/icons/generator/constants.ts +29 -29
  146. package/src/icons/generator/fileGenerator.ts +216 -216
  147. package/src/icons/generator/folderGenerator.ts +340 -340
  148. package/src/icons/generator/iconOpacity.ts +111 -111
  149. package/src/icons/generator/iconSaturation.ts +140 -140
  150. package/src/icons/generator/index.ts +7 -7
  151. package/src/icons/generator/jsonGenerator.ts +187 -187
  152. package/src/icons/generator/languageGenerator.ts +127 -127
  153. package/src/icons/index.ts +4 -4
  154. package/src/icons/languageIcons.ts +136 -136
  155. package/src/messages/outdated.ts +33 -33
  156. package/src/messages/reload.ts +32 -32
  157. package/src/messages/start.ts +12 -12
  158. package/src/messages/update.ts +48 -48
  159. package/src/messages/welcome.ts +47 -47
  160. package/src/models/helpers/index.ts +1 -1
  161. package/src/models/helpers/themeStatus.ts +5 -5
  162. package/src/models/i18n/index.ts +1 -1
  163. package/src/models/i18n/translation.ts +50 -50
  164. package/src/models/iconConfiguration.ts +37 -37
  165. package/src/models/icons/defaultIcon.ts +16 -16
  166. package/src/models/icons/files/fileIcon.ts +49 -49
  167. package/src/models/icons/files/fileTypes.ts +14 -14
  168. package/src/models/icons/files/index.ts +2 -2
  169. package/src/models/icons/folders/folderIcon.ts +34 -34
  170. package/src/models/icons/folders/folderTheme.ts +23 -23
  171. package/src/models/icons/folders/index.ts +2 -2
  172. package/src/models/icons/iconJsonOptions.ts +23 -23
  173. package/src/models/icons/iconPack.ts +12 -12
  174. package/src/models/icons/index.ts +6 -6
  175. package/src/models/icons/languages/index.ts +1 -1
  176. package/src/models/icons/languages/languageIdentifier.ts +26 -26
  177. package/src/models/index.ts +4 -4
  178. package/src/models/scripts/contributors/contributor.ts +22 -22
  179. package/src/models/scripts/contributors/contributorsConfig.ts +10 -10
  180. package/src/scripts/contributors/contributors.css +24 -24
  181. package/src/scripts/contributors/index.ts +138 -138
  182. package/src/scripts/helpers/painter.ts +5 -5
  183. package/src/scripts/helpers/screenshots.ts +32 -32
  184. package/src/scripts/helpers/similarity.ts +47 -47
  185. package/src/scripts/helpers/titleCase.ts +7 -7
  186. package/src/scripts/icons/checks/checkIconAvailability.ts +215 -215
  187. package/src/scripts/icons/checks/checkIconConflicts.ts +154 -154
  188. package/src/scripts/icons/checks/checkIconUsage.ts +141 -141
  189. package/src/scripts/icons/checks/index.ts +7 -7
  190. package/src/scripts/icons/generateJson.ts +11 -11
  191. package/src/scripts/preview/index.ts +40 -40
  192. package/src/scripts/preview/preview.ts +165 -165
  193. package/src/scripts/preview/style.css +48 -48
  194. package/src/test/runTest.ts +26 -26
  195. package/src/test/spec/i18n/i18n.spec.ts +61 -61
  196. package/src/test/spec/icons/fileIcons.spec.ts +250 -250
  197. package/src/test/spec/icons/folderIcons.spec.ts +418 -418
  198. package/src/test/spec/icons/languageIcons.spec.ts +184 -184
  199. package/src/test/spec/index.ts +36 -36
  200. package/src/web/extension.ts +10 -10
  201. package/svgo.config.js +11 -11
  202. package/tsconfig.json +23 -23
@@ -1,340 +1,340 @@
1
- import * as fs from 'fs';
2
- import merge from 'lodash.merge';
3
- import * as path 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 (path.basename(__dirname) === 'dist') {
320
- iconsPath = path.join(__dirname, '..', 'icons');
321
- } else {
322
- // executed via script
323
- iconsPath = path.join(__dirname, '..', '..', '..', 'icons');
324
- }
325
- const iconsFolderPath = path.join(iconsPath, `${iconName}.svg`);
326
- try {
327
- fs.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 * as fs from 'fs';
2
+ import merge from 'lodash.merge';
3
+ import * as path 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 (path.basename(__dirname) === 'dist') {
320
+ iconsPath = path.join(__dirname, '..', 'icons');
321
+ } else {
322
+ // executed via script
323
+ iconsPath = path.join(__dirname, '..', '..', '..', 'icons');
324
+ }
325
+ const iconsFolderPath = path.join(iconsPath, `${iconName}.svg`);
326
+ try {
327
+ fs.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
+ };