vueless 0.0.5 → 0.0.6
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.js +7 -0
- package/package.json +3 -2
- package/postcss.config.js +1 -1
- package/src/service.tailwind/index.js +1 -1
- package/src/service.ui/index.js +1 -1
- package/src/ui.button/index.vue +2 -3
- package/src/ui.button-link/index.vue +2 -2
- package/src/ui.button-toggle/index.vue +2 -2
- package/src/ui.button-toggle-item/index.vue +1 -1
- package/src/ui.container-modal/index.vue +1 -0
- package/src/ui.container-page/index.vue +4 -0
- package/src/ui.data-list/index.vue +1 -0
- package/src/ui.data-table/index.vue +5 -0
- package/src/ui.dropdown-badge/index.vue +1 -0
- package/src/ui.dropdown-button/index.vue +3 -3
- package/src/ui.dropdown-link/index.vue +1 -0
- package/src/ui.dropdown-list/index.vue +6 -4
- package/src/ui.form-calendar/index.vue +6 -1
- package/src/ui.form-checkbox/index.vue +3 -2
- package/src/ui.form-checkbox-group/index.vue +2 -0
- package/src/ui.form-checkbox-multi-state/index.vue +1 -0
- package/src/ui.form-color-picker/index.vue +3 -0
- package/src/ui.form-date-picker/index.vue +7 -4
- package/src/ui.form-date-picker-range/index.vue +19 -11
- package/src/ui.form-input/index.vue +3 -0
- package/src/ui.form-input-file/index.vue +2 -0
- package/src/ui.form-input-money/index.vue +3 -4
- package/src/ui.form-input-number/index.vue +3 -0
- package/src/ui.form-input-rating/index.vue +1 -0
- package/src/ui.form-input-search/index.vue +3 -0
- package/src/ui.form-radio/index.vue +2 -1
- package/src/ui.form-radio-card/index.vue +1 -0
- package/src/ui.form-select/index.vue +3 -0
- package/src/ui.form-switch/index.vue +1 -0
- package/src/ui.form-textarea/index.vue +2 -2
- package/src/ui.navigation-pagination/index.vue +2 -1
- package/src/ui.navigation-stepper/index.vue +1 -3
- package/src/ui.navigation-tabs/index.vue +1 -1
- package/src/ui.text-alert/index.vue +2 -1
- package/src/ui.text-empty/index.vue +1 -0
- package/src/ui.text-files/index.vue +1 -1
- package/vite.config.mjs +5 -4
- package/web-types.json +1 -1
- package/.web-types-gen/package.json +0 -3
- package/src/library.web-types-gen/index.js +0 -17
- package/src/library.web-types-gen/lib/build.js +0 -252
- package/src/library.web-types-gen/lib/config.js +0 -32
- package/src/library.web-types-gen/package.json +0 -3
- package/src/plugin.vite/index.js +0 -59
- package/src/plugin.vite/services/iconResolver.service.js +0 -291
- package/src/plugin.vite/services/svgLoader.service.js +0 -76
- package/src/plugin.vite/services/tailwindSafelist.service.js +0 -195
- package/src/plugin.vite/services/unpluginComponentsResolver.js +0 -172
|
@@ -1,291 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
This scrypt find icon names from the UIcon props and objects across the project
|
|
3
|
-
and copy SVG icons from the default icons library (@material-symbols or other from config)
|
|
4
|
-
to the ".../.generated" folder.
|
|
5
|
-
|
|
6
|
-
Those icons will be used only in the build stage.
|
|
7
|
-
The script is needed to avoid all @material-symbols icons set in the project bundle.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
/* eslint-disable no-console */
|
|
11
|
-
import fs from "fs";
|
|
12
|
-
import path from "path";
|
|
13
|
-
import { createRequire } from "node:module";
|
|
14
|
-
import { merge } from "lodash-es";
|
|
15
|
-
|
|
16
|
-
import vuelessConfig from "../../../vueless.config.js";
|
|
17
|
-
|
|
18
|
-
const DESTINATION_DIR = "./src/assets/images/.generated";
|
|
19
|
-
const DEFAULT_CONFIG_PATH = ".vueless/ui.image-icon/configs/default.config.js";
|
|
20
|
-
const STORYBOOK_STORY_EXTENSION = ".stories.js";
|
|
21
|
-
const U_ICON = "UIcon";
|
|
22
|
-
|
|
23
|
-
const defaultVariants = getMergedConfig();
|
|
24
|
-
const args = parseArgs();
|
|
25
|
-
|
|
26
|
-
let isDebug = false;
|
|
27
|
-
|
|
28
|
-
// run method manually
|
|
29
|
-
if (args.run) {
|
|
30
|
-
copyIcons(args.mode);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// perform icons copy magick... ✨
|
|
34
|
-
export function copyIcons(mode = "src", debug) {
|
|
35
|
-
isDebug = debug || false;
|
|
36
|
-
|
|
37
|
-
removeIcons();
|
|
38
|
-
|
|
39
|
-
const vuelessVueFiles = getFiles(".vueless", ".vue");
|
|
40
|
-
const vuelessJsFiles = getFiles(".vueless", ".js");
|
|
41
|
-
const vuelessLayoutsVueFiles = getFiles(".vueless-layouts", ".vue");
|
|
42
|
-
const vuelessLayoutsJsFiles = getFiles(".vueless-layouts", ".js");
|
|
43
|
-
const vuelessServicesJsFiles = getFiles(".vueless-services", ".js");
|
|
44
|
-
|
|
45
|
-
findAndCopyIcons([
|
|
46
|
-
...vuelessVueFiles,
|
|
47
|
-
...vuelessJsFiles,
|
|
48
|
-
...vuelessLayoutsVueFiles,
|
|
49
|
-
...vuelessLayoutsJsFiles,
|
|
50
|
-
...vuelessServicesJsFiles,
|
|
51
|
-
"vueless.config.js",
|
|
52
|
-
"vueless.config.ts",
|
|
53
|
-
]);
|
|
54
|
-
|
|
55
|
-
if (mode === "src" || mode === "all") {
|
|
56
|
-
const srcVueFiles = getFiles("src", ".vue");
|
|
57
|
-
const srcJsFiles = getFiles("src", ".js");
|
|
58
|
-
const srcTsFiles = getFiles("src", ".ts");
|
|
59
|
-
|
|
60
|
-
findAndCopyIcons([...srcVueFiles, ...srcJsFiles, ...srcTsFiles]);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (mode === "storybook" || mode === "all") {
|
|
64
|
-
const vuelessStoriesJsFiles = getFiles(".vueless", STORYBOOK_STORY_EXTENSION);
|
|
65
|
-
|
|
66
|
-
findAndCopyIcons(vuelessStoriesJsFiles);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export function removeIcons() {
|
|
71
|
-
if (fs.existsSync(DESTINATION_DIR)) {
|
|
72
|
-
fs.rmSync(DESTINATION_DIR, { recursive: true, force: true });
|
|
73
|
-
|
|
74
|
-
if (isDebug) {
|
|
75
|
-
console.log("Dynamically copied icons was successfully removed.");
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function findAndCopyIcons(files) {
|
|
81
|
-
const safelistIcons = getSafelistIcons();
|
|
82
|
-
|
|
83
|
-
safelistIcons.forEach((iconName) => {
|
|
84
|
-
copyFile(iconName, false);
|
|
85
|
-
copyFile(iconName, true);
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
files.forEach(async (file) => {
|
|
89
|
-
const fileContents = fs.existsSync(file) ? fs.readFileSync(file).toString() : "";
|
|
90
|
-
|
|
91
|
-
/* Objects across the project */
|
|
92
|
-
const objectRegExp = /(\{|[^{])[^}]*\b\w*icon\w*:\s*["']([^"']+)["'][^}]*}/gi;
|
|
93
|
-
const objectMatches = fileContents.match(objectRegExp);
|
|
94
|
-
|
|
95
|
-
if (objectMatches) {
|
|
96
|
-
for (const match of objectMatches) {
|
|
97
|
-
const iconNameRegex = /\w*(icon)\w*:\s*["']([^"'\s]+)["']/gi;
|
|
98
|
-
const iconNameMatch = iconNameRegex.exec(match);
|
|
99
|
-
const iconName = iconNameMatch && iconNameMatch[2];
|
|
100
|
-
|
|
101
|
-
const iconFillRegex = /\w*(fill)\w*:\s*(true|false)/gi;
|
|
102
|
-
const fillMatch = iconFillRegex.exec(match);
|
|
103
|
-
const fill = fillMatch ? fillMatch[2] : defaultVariants.fill;
|
|
104
|
-
|
|
105
|
-
try {
|
|
106
|
-
if (iconName) {
|
|
107
|
-
copyFile(iconName, fill);
|
|
108
|
-
}
|
|
109
|
-
} catch (error) {
|
|
110
|
-
// console.log(error);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
iconNameRegex.lastIndex = 0;
|
|
114
|
-
iconFillRegex.lastIndex = 0;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/* UIcon */
|
|
119
|
-
const regexName = /\bname\s*=\s*["']([^"'\s]+)["']/;
|
|
120
|
-
const regexFill = /(:(fill)="([^"]*)"|fill)/;
|
|
121
|
-
|
|
122
|
-
const matchNameArray = fileContents.match(/<UIcon[^>]+>/g);
|
|
123
|
-
|
|
124
|
-
if (matchNameArray) {
|
|
125
|
-
for (const match of matchNameArray) {
|
|
126
|
-
const iconNameMatch = regexName.exec(match);
|
|
127
|
-
const iconFillMatch = regexFill.exec(match);
|
|
128
|
-
|
|
129
|
-
const iconName = iconNameMatch ? iconNameMatch[1] : null;
|
|
130
|
-
const fill = iconFillMatch ? iconFillMatch[1] : defaultVariants.fill;
|
|
131
|
-
|
|
132
|
-
try {
|
|
133
|
-
if (iconName) {
|
|
134
|
-
if (iconFillMatch && iconFillMatch[3]) {
|
|
135
|
-
copyFile(iconName, false);
|
|
136
|
-
copyFile(iconName, true);
|
|
137
|
-
} else {
|
|
138
|
-
copyFile(iconName, fill);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
} catch (error) {
|
|
142
|
-
// console.log(error);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/* UIcon with ternary operator */
|
|
148
|
-
const ternaryRegexName = /\bname="[^']*'([^']*)'\s*:\s*'([^']*)'/;
|
|
149
|
-
const ternaryRegexFill = /(:(fill)="([^"]*)"|fill)/;
|
|
150
|
-
|
|
151
|
-
const ternaryMatchNameArray = fileContents.match(/<UIcon[^>]+>/g);
|
|
152
|
-
|
|
153
|
-
if (ternaryMatchNameArray) {
|
|
154
|
-
for (const match of ternaryMatchNameArray) {
|
|
155
|
-
const iconNameMatch = ternaryRegexName.exec(match);
|
|
156
|
-
const iconFillMatch = ternaryRegexFill.exec(match);
|
|
157
|
-
|
|
158
|
-
const fill = iconFillMatch ? iconFillMatch[1] : defaultVariants.fill;
|
|
159
|
-
|
|
160
|
-
try {
|
|
161
|
-
if (iconFillMatch && iconFillMatch[3]) {
|
|
162
|
-
copyFile(iconNameMatch[1], false);
|
|
163
|
-
copyFile(iconNameMatch[2], true);
|
|
164
|
-
copyFile(iconNameMatch[1], false);
|
|
165
|
-
copyFile(iconNameMatch[2], true);
|
|
166
|
-
} else {
|
|
167
|
-
copyFile(iconNameMatch[1], fill);
|
|
168
|
-
copyFile(iconNameMatch[2], fill);
|
|
169
|
-
}
|
|
170
|
-
} catch (error) {
|
|
171
|
-
// console.log(error);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
function getFiles(dirPath, extension, fileList) {
|
|
179
|
-
const files = fs.readdirSync(dirPath);
|
|
180
|
-
|
|
181
|
-
fileList = fileList || [];
|
|
182
|
-
|
|
183
|
-
files.forEach((file) => {
|
|
184
|
-
const filePath = path.join(dirPath, file);
|
|
185
|
-
const stat = fs.statSync(filePath);
|
|
186
|
-
|
|
187
|
-
if (stat.isDirectory()) {
|
|
188
|
-
fileList = getFiles(filePath, extension, fileList);
|
|
189
|
-
} else {
|
|
190
|
-
const isStorybookStory =
|
|
191
|
-
filePath.endsWith(STORYBOOK_STORY_EXTENSION) && extension !== STORYBOOK_STORY_EXTENSION;
|
|
192
|
-
|
|
193
|
-
if (filePath.endsWith(extension) && !isStorybookStory) {
|
|
194
|
-
fileList.push(filePath);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
return fileList;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
function copyFile(name, fill) {
|
|
203
|
-
name = name.toLowerCase();
|
|
204
|
-
fill = Boolean(fill);
|
|
205
|
-
|
|
206
|
-
const library = defaultVariants.library;
|
|
207
|
-
const weight = defaultVariants.weight;
|
|
208
|
-
const style = defaultVariants.style;
|
|
209
|
-
|
|
210
|
-
const require = createRequire(import.meta.url);
|
|
211
|
-
|
|
212
|
-
/* eslint-disable prettier/prettier */
|
|
213
|
-
const libraries = {
|
|
214
|
-
"@material-symbols": {
|
|
215
|
-
source: `${library}/svg-${weight}/${style}/${name}${fill ? "-fill" : ""}.svg`,
|
|
216
|
-
destination: `${DESTINATION_DIR}/${library}/svg-${weight}/${style}/${name}${fill ? "-fill" : ""}.svg`,
|
|
217
|
-
},
|
|
218
|
-
"bootstrap-icons": {
|
|
219
|
-
source: `${library}/icons/${name}${fill ? "-fill" : ""}.svg`,
|
|
220
|
-
destination: `${DESTINATION_DIR}/${library}/icons/${name}${fill ? "-fill" : ""}.svg`,
|
|
221
|
-
},
|
|
222
|
-
heroicons: {
|
|
223
|
-
source: `${library}/${style}/${fill ? "solid" : "outline"}/${name}.svg`,
|
|
224
|
-
destination: `${DESTINATION_DIR}/${library}/${style}/${fill ? "solid" : "outline"}/${name}.svg`,
|
|
225
|
-
},
|
|
226
|
-
};
|
|
227
|
-
/* eslint-enable prettier/prettier */
|
|
228
|
-
|
|
229
|
-
const { source, destination } = libraries[library];
|
|
230
|
-
|
|
231
|
-
if (fs.existsSync(destination)) {
|
|
232
|
-
return;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
const destDir = path.dirname(destination);
|
|
236
|
-
|
|
237
|
-
fs.mkdirSync(destDir, { recursive: true });
|
|
238
|
-
fs.copyFile(require.resolve(source), destination, (err) => {
|
|
239
|
-
if (args.debug || isDebug) {
|
|
240
|
-
err
|
|
241
|
-
? console.error(`Error copying icon "${name}":`, err)
|
|
242
|
-
: console.log(`Icon "${name}" copied successfully!`);
|
|
243
|
-
}
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
function parseArgs() {
|
|
248
|
-
const args = process.argv.slice(2);
|
|
249
|
-
const parsedArgs = {};
|
|
250
|
-
|
|
251
|
-
let currentKey = null;
|
|
252
|
-
|
|
253
|
-
for (let i = 0; i < args.length; i++) {
|
|
254
|
-
const arg = args[i];
|
|
255
|
-
|
|
256
|
-
if (arg.startsWith("--")) {
|
|
257
|
-
const key = arg.slice(2);
|
|
258
|
-
|
|
259
|
-
parsedArgs[key] = true;
|
|
260
|
-
currentKey = key;
|
|
261
|
-
} else if (currentKey) {
|
|
262
|
-
parsedArgs[currentKey] = arg;
|
|
263
|
-
currentKey = null;
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
return parsedArgs;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
function getSafelistIcons() {
|
|
271
|
-
return vuelessConfig.component ? vuelessConfig.component[U_ICON]?.safelistIcons || [] : [];
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
function getMergedConfig() {
|
|
275
|
-
if (fs.existsSync(DEFAULT_CONFIG_PATH)) {
|
|
276
|
-
const defaultConfigFile = fs.readFileSync(DEFAULT_CONFIG_PATH).toString();
|
|
277
|
-
|
|
278
|
-
const defaultConfig = getDefaultConfigJson(defaultConfigFile);
|
|
279
|
-
const globalConfig = vuelessConfig.component || {};
|
|
280
|
-
|
|
281
|
-
return merge(defaultConfig.defaultVariants, globalConfig[U_ICON]?.defaultVariants);
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
function getDefaultConfigJson(fileContents) {
|
|
286
|
-
const objectStartIndex = fileContents.indexOf("{");
|
|
287
|
-
const objectString = fileContents.substring(objectStartIndex).replace("};", "}");
|
|
288
|
-
|
|
289
|
-
// indirect eval
|
|
290
|
-
return (0, eval)("(" + objectString + ")"); // Converting into JS object
|
|
291
|
-
}
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-console */
|
|
2
|
-
|
|
3
|
-
import fs from "fs";
|
|
4
|
-
import { compileTemplate } from "vue/compiler-sfc";
|
|
5
|
-
import { optimize as optimizeSvg } from "svgo";
|
|
6
|
-
|
|
7
|
-
const DEFAULT_SVGO_CONFIG = {
|
|
8
|
-
plugins: [
|
|
9
|
-
{
|
|
10
|
-
name: "preset-default",
|
|
11
|
-
params: {
|
|
12
|
-
overrides: {
|
|
13
|
-
removeViewBox: false,
|
|
14
|
-
convertColors: {
|
|
15
|
-
currentColor: true,
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
},
|
|
19
|
-
},
|
|
20
|
-
],
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export async function loadSvg(id, options) {
|
|
24
|
-
const { defaultImport = "url", svgo = true, svgoConfig = DEFAULT_SVGO_CONFIG } = options;
|
|
25
|
-
const svgRegex = /\.svg(\?(raw|url|component|skipsvgo))?$/;
|
|
26
|
-
|
|
27
|
-
if (!id.match(svgRegex)) {
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
let svg;
|
|
32
|
-
const [path, query] = id.split("?", 2);
|
|
33
|
-
const importType = query || defaultImport;
|
|
34
|
-
|
|
35
|
-
// use default svg loader
|
|
36
|
-
if (importType === "url" && !path.includes(".generated")) {
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
try {
|
|
41
|
-
svg = await fs.promises.readFile(path, "utf-8");
|
|
42
|
-
} catch (ex) {
|
|
43
|
-
console.warn(
|
|
44
|
-
"\n",
|
|
45
|
-
`${id} couldn't be loaded by vite-plugin-vue-vueless, fallback to default loader.`,
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (importType === "raw") {
|
|
52
|
-
return `export default ${JSON.stringify(svg)}`;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (svgo !== false && query !== "skipsvgo") {
|
|
56
|
-
svg = optimizeSvg(svg, {
|
|
57
|
-
...svgoConfig,
|
|
58
|
-
path,
|
|
59
|
-
}).data;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// prevent compileTemplate from removing the style tag
|
|
63
|
-
svg = svg.replace(/<style/g, '<component is="style"').replace(/<\/style/g, "</component");
|
|
64
|
-
|
|
65
|
-
const { code } = compileTemplate({
|
|
66
|
-
id: JSON.stringify(id),
|
|
67
|
-
source: svg,
|
|
68
|
-
filename: path,
|
|
69
|
-
transformAssetUrls: false,
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
return `
|
|
73
|
-
${code}
|
|
74
|
-
export default { render: render }
|
|
75
|
-
`;
|
|
76
|
-
}
|
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import path from "path";
|
|
3
|
-
|
|
4
|
-
import vuelessConfig from "../../../vueless.config.js";
|
|
5
|
-
import { brandColors } from "../../service.tailwind";
|
|
6
|
-
import { components } from "./unpluginComponentsResolver.js";
|
|
7
|
-
|
|
8
|
-
const COMPONENTS_WITH_COLOR_PROP = [
|
|
9
|
-
"UButton",
|
|
10
|
-
"ULink",
|
|
11
|
-
"UDropdownButton",
|
|
12
|
-
"UDropdownBadge",
|
|
13
|
-
"UDropdownLink",
|
|
14
|
-
"UCheckbox",
|
|
15
|
-
"UCheckboxGroup",
|
|
16
|
-
"UCheckboxMultiState",
|
|
17
|
-
"USwitch",
|
|
18
|
-
"URadio",
|
|
19
|
-
"URadioCard",
|
|
20
|
-
"URadioGroup",
|
|
21
|
-
"UHeader",
|
|
22
|
-
"UText",
|
|
23
|
-
"UAlert",
|
|
24
|
-
"UMoney",
|
|
25
|
-
"UBadge",
|
|
26
|
-
"UModalConfirm",
|
|
27
|
-
"UIcon",
|
|
28
|
-
"UDot",
|
|
29
|
-
];
|
|
30
|
-
|
|
31
|
-
export function createTailwindSafelist() {
|
|
32
|
-
const safelist = [];
|
|
33
|
-
|
|
34
|
-
const srcVueFiles = getFiles("src", ".vue");
|
|
35
|
-
const vuelessVueFiles = getFiles(".vueless", ".vue");
|
|
36
|
-
const vuelessLayoutVueFiles = getFiles(".vueless-layouts", ".vue");
|
|
37
|
-
const vuelessJsConfigFiles = getFiles(".vueless", ".config.js");
|
|
38
|
-
|
|
39
|
-
const files = [
|
|
40
|
-
...srcVueFiles,
|
|
41
|
-
...vuelessVueFiles,
|
|
42
|
-
...vuelessLayoutVueFiles,
|
|
43
|
-
...vuelessJsConfigFiles,
|
|
44
|
-
];
|
|
45
|
-
|
|
46
|
-
/* Generate safelist */
|
|
47
|
-
COMPONENTS_WITH_COLOR_PROP.forEach((component) => {
|
|
48
|
-
const { colors, isExistsComponent } = findColors(files, component);
|
|
49
|
-
|
|
50
|
-
if (isExistsComponent && colors.length) {
|
|
51
|
-
// eslint-disable-next-line vue/max-len, prettier/prettier
|
|
52
|
-
const defaultConfigPath = vuelessJsConfigFiles.find((file) => checkDefaultConfig(file, component));
|
|
53
|
-
|
|
54
|
-
const defaultSafelist = getDefaultConfig(defaultConfigPath)?.safelist;
|
|
55
|
-
const customSafelist =
|
|
56
|
-
vuelessConfig.component && vuelessConfig.component[component]?.safelist;
|
|
57
|
-
|
|
58
|
-
const colorString = colors.join("|");
|
|
59
|
-
|
|
60
|
-
const selectedSafelist = customSafelist
|
|
61
|
-
? customSafelist && customSafelist(colorString)
|
|
62
|
-
: defaultSafelist && defaultSafelist(colorString);
|
|
63
|
-
|
|
64
|
-
if (selectedSafelist) {
|
|
65
|
-
safelist.push(...selectedSafelist);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
process.env.SAFELIST_JSON = JSON.stringify(safelist);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function getFiles(dirPath, extension, fileList) {
|
|
74
|
-
const files = fs.readdirSync(dirPath);
|
|
75
|
-
|
|
76
|
-
fileList = fileList || [];
|
|
77
|
-
|
|
78
|
-
files.forEach((file) => {
|
|
79
|
-
const filePath = path.join(dirPath, file);
|
|
80
|
-
const stat = fs.statSync(filePath);
|
|
81
|
-
|
|
82
|
-
if (stat.isDirectory()) {
|
|
83
|
-
fileList = getFiles(filePath, extension, fileList);
|
|
84
|
-
} else {
|
|
85
|
-
filePath.endsWith(extension) && fileList.push(filePath);
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
return fileList;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function findColors(files, component) {
|
|
93
|
-
const colors = [];
|
|
94
|
-
const brandColor = getBrandColor();
|
|
95
|
-
|
|
96
|
-
if (brandColor && brandColor !== "grayscale") {
|
|
97
|
-
colors.push(brandColor);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (!brandColors.includes("gray")) {
|
|
101
|
-
brandColors.push("gray");
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/* Add safelist colors from config */
|
|
105
|
-
getSafelistColorsFromConfig(component).forEach((color) => addColor(color, colors));
|
|
106
|
-
|
|
107
|
-
let isExistsComponent = false;
|
|
108
|
-
|
|
109
|
-
files.forEach((file) => {
|
|
110
|
-
const fileContents = fs.existsSync(file) ? fs.readFileSync(file).toString() : "";
|
|
111
|
-
|
|
112
|
-
const isDefaultConfig = checkDefaultConfig(file, component);
|
|
113
|
-
|
|
114
|
-
/* Collect color from config objects */
|
|
115
|
-
if (isDefaultConfig) {
|
|
116
|
-
const colorRegExp = /\bcolor\s*:\s*["']([^"'\s]+)["']/g;
|
|
117
|
-
const matchedColors = fileContents.match(colorRegExp);
|
|
118
|
-
|
|
119
|
-
if (matchedColors) {
|
|
120
|
-
for (const match of matchedColors) {
|
|
121
|
-
const matchedColor = colorRegExp.exec(match);
|
|
122
|
-
|
|
123
|
-
addColor(matchedColor && matchedColor[1], colors);
|
|
124
|
-
|
|
125
|
-
colorRegExp.lastIndex = 0;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/* Collect color from U[Component] */
|
|
131
|
-
const componentRegExp = new RegExp(`<${component}[^>]+>`, "g");
|
|
132
|
-
const matchedComponent = fileContents.match(componentRegExp);
|
|
133
|
-
|
|
134
|
-
if (matchedComponent) {
|
|
135
|
-
isExistsComponent = true;
|
|
136
|
-
|
|
137
|
-
/* single value prop */
|
|
138
|
-
const colorRegExp = /\bcolor\s*=\s*["']([^"'\s]+)["']/;
|
|
139
|
-
|
|
140
|
-
for (const match of matchedComponent) {
|
|
141
|
-
const matchedColor = colorRegExp.exec(match);
|
|
142
|
-
|
|
143
|
-
addColor(matchedColor && matchedColor[1], colors);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/* ternary value prop */
|
|
147
|
-
const ternaryRegExp = /\bcolor="[^']*'([^']*)'\s*:\s*'([^']*)'/;
|
|
148
|
-
|
|
149
|
-
for (const match of matchedComponent) {
|
|
150
|
-
const matchedColors = ternaryRegExp.exec(match);
|
|
151
|
-
|
|
152
|
-
addColor(matchedColors && matchedColors[1], colors);
|
|
153
|
-
addColor(matchedColors && matchedColors[2], colors);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
return { colors, isExistsComponent };
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
function addColor(color, colors) {
|
|
162
|
-
if (brandColors.includes(color) && !colors.includes(color)) {
|
|
163
|
-
colors.push(color);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
function getSafelistColorsFromConfig(component) {
|
|
168
|
-
const globalSafelistColors = vuelessConfig.safelistColors || [];
|
|
169
|
-
const componentSafelistColors =
|
|
170
|
-
(vuelessConfig.component && vuelessConfig.component[component]?.safelistColors) || [];
|
|
171
|
-
|
|
172
|
-
return [...globalSafelistColors, ...componentSafelistColors];
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
function getBrandColor(component) {
|
|
176
|
-
return vuelessConfig.component
|
|
177
|
-
? vuelessConfig.component[component]?.defaultVariants?.color
|
|
178
|
-
: vuelessConfig.brand || "";
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
function checkDefaultConfig(filePath, component) {
|
|
182
|
-
return filePath.includes(components[component]) && filePath.endsWith("default.config.js");
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
function getDefaultConfig(path) {
|
|
186
|
-
if (fs.existsSync(path)) {
|
|
187
|
-
const defaultConfigFile = fs.readFileSync(path).toString();
|
|
188
|
-
|
|
189
|
-
const objectStartIndex = defaultConfigFile.indexOf("{");
|
|
190
|
-
const objectString = defaultConfigFile.substring(objectStartIndex).replace("};", "}");
|
|
191
|
-
|
|
192
|
-
// indirect eval
|
|
193
|
-
return (0, eval)("(" + objectString + ")"); // Converting into JS object
|
|
194
|
-
}
|
|
195
|
-
}
|