@ui5/webcomponents-tools 2.15.0-rc.0 → 2.15.0-rc.2
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/CHANGELOG.md +19 -0
- package/bin/dev.js +3 -2
- package/bin/ui5nps.js +228 -0
- package/components-package/nps.js +59 -65
- package/icons-collection/nps.js +17 -12
- package/lib/generate-js-imports/illustrations.js +39 -43
- package/lib/generate-json-imports/i18n.js +1 -1
- package/lib/icons-hash/icons-hash.mjs +149 -0
- package/package.json +6 -7
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,25 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [2.15.0-rc.2](https://github.com/UI5/webcomponents/compare/v2.15.0-rc.1...v2.15.0-rc.2) (2025-09-25)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @ui5/webcomponents-tools
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# [2.15.0-rc.1](https://github.com/UI5/webcomponents/compare/v2.15.0-rc.0...v2.15.0-rc.1) (2025-09-25)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Bug Fixes
|
|
18
|
+
|
|
19
|
+
* **ui5-illustrated-message:** fix imports filter ([#12271](https://github.com/UI5/webcomponents/issues/12271)) ([f62d703](https://github.com/UI5/webcomponents/commit/f62d703b58aa4460dbc5a293c277290b48ca851f))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
6
25
|
# [2.15.0-rc.0](https://github.com/UI5/webcomponents/compare/v2.14.0...v2.15.0-rc.0) (2025-09-11)
|
|
7
26
|
|
|
8
27
|
**Note:** Version bump only for package @ui5/webcomponents-tools
|
package/bin/dev.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
const child_process = require("child_process");
|
|
4
|
+
const { comma } = require("postcss/lib/list");
|
|
4
5
|
|
|
5
6
|
let command = process.argv[2];
|
|
6
7
|
const argument = process.argv[3];
|
|
@@ -10,7 +11,7 @@ if (command === "watch") {
|
|
|
10
11
|
command = `watch.${argument}`;
|
|
11
12
|
}
|
|
12
13
|
} else if (command === "test") {
|
|
13
|
-
command =
|
|
14
|
+
command = ["test", ...process.argv.slice(3)].join(" ");
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
child_process.execSync(`
|
|
17
|
+
child_process.execSync(`ui5nps "${command}"`, {stdio: 'inherit'});
|
package/bin/ui5nps.js
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
const { exec } = require("child_process");
|
|
8
|
+
|
|
9
|
+
const SCRIPT_NAMES = [
|
|
10
|
+
"package-scripts.js",
|
|
11
|
+
"package-scripts.cjs",
|
|
12
|
+
"package-scripts.mjs"
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Parser for UI5 package scripts with support for parallel and sequential execution
|
|
17
|
+
*/
|
|
18
|
+
class Parser {
|
|
19
|
+
scripts;
|
|
20
|
+
envs;
|
|
21
|
+
parsedScripts = new Map();
|
|
22
|
+
resolvedScripts = new Map();
|
|
23
|
+
|
|
24
|
+
constructor() {
|
|
25
|
+
const { scripts, envs } = this.getScripts();
|
|
26
|
+
|
|
27
|
+
this.scripts = scripts;
|
|
28
|
+
this.envs = envs;
|
|
29
|
+
|
|
30
|
+
// Parse scripts on initialization
|
|
31
|
+
this.parseScripts();
|
|
32
|
+
|
|
33
|
+
[...this.parsedScripts.keys()].forEach(key => {
|
|
34
|
+
this.resolveScripts(`${key}`);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Recursively parses script definitions from package-scripts file
|
|
40
|
+
* @param {Object} scripts - Script definitions object
|
|
41
|
+
* @param {string} parentKey - Parent key for nested scripts
|
|
42
|
+
*/
|
|
43
|
+
parseScripts(scripts = this.scripts, parentKey = "") {
|
|
44
|
+
for (const [key, value] of Object.entries(scripts)) {
|
|
45
|
+
if (key === "__ui5envs") continue; // Skip envs key
|
|
46
|
+
|
|
47
|
+
if (parentKey && key === "default") {
|
|
48
|
+
this.parsedScripts.set(parentKey, value);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const fullKey = parentKey ? `${parentKey}.${key}` : key;
|
|
52
|
+
|
|
53
|
+
if (typeof value === "string") {
|
|
54
|
+
this.parsedScripts.set(fullKey, value);
|
|
55
|
+
} else if (typeof value === "object") {
|
|
56
|
+
this.parseScripts(value, fullKey);
|
|
57
|
+
} else {
|
|
58
|
+
throw new Error(`Invalid script definition for key: ${fullKey}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Resolves script commands and determines if they should run in parallel
|
|
65
|
+
* @param {string} commandName - Name of the command to resolve
|
|
66
|
+
* @returns {Object} Resolved command object with commands array and parallel flag
|
|
67
|
+
*/
|
|
68
|
+
resolveScripts(commandName) {
|
|
69
|
+
if (this.resolvedScripts.has(commandName)) {
|
|
70
|
+
return this.resolvedScripts.get(commandName);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
let executableCommand = this.parsedScripts.get(commandName);
|
|
74
|
+
if (executableCommand === undefined) {
|
|
75
|
+
throw new Error(`Command "${commandName}" not found in scripts`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (!executableCommand.startsWith("ui5nps") && !executableCommand.startsWith("ui5nps-p")) {
|
|
79
|
+
this.resolvedScripts.set(commandName, { commandName, commands: [executableCommand], parallel: false });
|
|
80
|
+
return this.resolvedScripts.get(commandName);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const parts = executableCommand.trim().split(" ").filter(Boolean).slice(1); // Remove "ui5nps" or ui5nps-p part
|
|
84
|
+
const commands = [];
|
|
85
|
+
for (const part of parts) {
|
|
86
|
+
if (!this.parsedScripts.has(part)) {
|
|
87
|
+
throw new Error(`Referenced command "${part}" not found in scripts`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const parsedScript = this.parsedScripts.get(part);
|
|
91
|
+
|
|
92
|
+
if (parsedScript && (parsedScript.startsWith("ui5nps") || parsedScript.startsWith("ui5nps-p"))) {
|
|
93
|
+
this.resolveScripts(part);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
commands.push(this.resolvedScripts.get(part) || parsedScript);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
this.resolvedScripts.set(commandName, { commandName, commands, parallel: executableCommand.startsWith("ui5nps-p") });
|
|
101
|
+
|
|
102
|
+
return this.resolvedScripts.get(commandName);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Loads and validates package-scripts file
|
|
107
|
+
* @returns {Object} Object containing scripts and environment variables
|
|
108
|
+
*/
|
|
109
|
+
getScripts() {
|
|
110
|
+
let packageScriptPath;
|
|
111
|
+
|
|
112
|
+
for (const scriptName of SCRIPT_NAMES) {
|
|
113
|
+
const filePath = path.join(process.cwd(), scriptName);
|
|
114
|
+
if (fs.existsSync(filePath)) {
|
|
115
|
+
packageScriptPath = filePath;
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Package-script file should be in the current working directory
|
|
121
|
+
if (!packageScriptPath) {
|
|
122
|
+
console.error("No package-scripts.js/cjs/mjs file found in the current directory.");
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const packageScript = require(packageScriptPath);
|
|
127
|
+
let scripts;
|
|
128
|
+
let envs;
|
|
129
|
+
|
|
130
|
+
if (packageScript.__esModule) {
|
|
131
|
+
scripts = packageScript.default.scripts;
|
|
132
|
+
} else {
|
|
133
|
+
scripts = packageScript.scripts;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Package-script should provide default export with scripts object
|
|
137
|
+
if (!scripts || typeof scripts !== "object") {
|
|
138
|
+
console.error("No valid 'scripts' object found in package-scripts file.");
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
envs = scripts.__ui5envs;
|
|
143
|
+
|
|
144
|
+
// Package-script should provide default export with scripts object
|
|
145
|
+
if (envs && typeof envs !== "object") {
|
|
146
|
+
console.error("No valid 'envs' object found in package-scripts file.");
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return { scripts, envs };
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Executes a command or command object (with parallel/sequential support)
|
|
155
|
+
* @param {string|Object} command - Command string or command object with commands array
|
|
156
|
+
* @returns {Promise} Promise that resolves when command(s) complete
|
|
157
|
+
*/
|
|
158
|
+
async executeCommand(command) {
|
|
159
|
+
if (typeof command === "string" && command) {
|
|
160
|
+
return new Promise((resolve, reject) => {
|
|
161
|
+
console.log(`= Executing command: ${command}`);
|
|
162
|
+
const child = exec(command, { stdio: "inherit", env: { ...process.env, ...this.envs } });
|
|
163
|
+
|
|
164
|
+
child.stdout.on("data", (data) => {
|
|
165
|
+
console.log(data);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
child.stderr.on("data", (data) => {
|
|
169
|
+
console.error(data);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
child.on("error", (err) => {
|
|
173
|
+
console.error("Failed to start:", err);
|
|
174
|
+
reject(err);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
child.on("close", (code) => {
|
|
178
|
+
code === 0 ? resolve() : reject(new Error(`Exit ${code}`));
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
} else if (typeof command === "object" && command.commands) {
|
|
182
|
+
if (command.parallel) {
|
|
183
|
+
// Execute commands in parallel
|
|
184
|
+
const promises = command.commands.filter(Boolean).map(cmd => this.executeCommand(cmd));
|
|
185
|
+
await Promise.all(promises);
|
|
186
|
+
} else {
|
|
187
|
+
// Execute commands sequentially
|
|
188
|
+
for (const cmd of command.commands) {
|
|
189
|
+
await this.executeCommand(cmd);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Main execution method for a named command
|
|
197
|
+
* @param {string} commandName - Name of the command to execute
|
|
198
|
+
* @returns {Promise} Promise that resolves when execution completes
|
|
199
|
+
*/
|
|
200
|
+
async execute(commandName) {
|
|
201
|
+
const command = this.resolvedScripts.get(commandName);
|
|
202
|
+
|
|
203
|
+
if (!command) {
|
|
204
|
+
throw new Error(`Command "${commandName}" not found in scripts`);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return this.executeCommand(this.resolvedScripts.get(commandName));
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const parser = new Parser();
|
|
212
|
+
|
|
213
|
+
// Basic input validation
|
|
214
|
+
const commands = process.argv.slice(2);
|
|
215
|
+
if (commands.length === 0) {
|
|
216
|
+
console.error("Usage: ui5nps <command> [command2] [command3] ...");
|
|
217
|
+
console.error("No commands provided.");
|
|
218
|
+
process.exit(1);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
(async () => {
|
|
222
|
+
for (const commandName of commands) {
|
|
223
|
+
await parser.execute(commandName);
|
|
224
|
+
}
|
|
225
|
+
})().catch(error => {
|
|
226
|
+
console.error("Error executing commands:", error);
|
|
227
|
+
process.exit(1);
|
|
228
|
+
});
|
|
@@ -7,25 +7,8 @@ if (process.env.DEPLOY) {
|
|
|
7
7
|
websiteBaseUrl = "/webcomponents/";
|
|
8
8
|
} else if (process.env.DEPLOY_NIGHTLY) {
|
|
9
9
|
websiteBaseUrl = "/webcomponents/nightly/";
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const cypressEnvVariables = (options, predefinedVars) => {
|
|
13
|
-
let variables = [];
|
|
14
|
-
const { cypress_code_coverage, cypress_acc_tests } = options.internal ?? {};
|
|
15
|
-
|
|
16
|
-
// Handle environment variables like TEST_SUITE
|
|
17
|
-
if (predefinedVars) {
|
|
18
|
-
variables = [...predefinedVars];
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// The coverage task is always registered and requires an explicit variable whether to generate a report or not
|
|
22
|
-
variables.push(`CYPRESS_COVERAGE=${!!cypress_code_coverage}`);
|
|
23
|
-
|
|
24
|
-
if (cypress_acc_tests) {
|
|
25
|
-
variables.push("CYPRESS_UI5_ACC=true");
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return variables.length ? `cross-env ${variables.join(" ")}` : "";
|
|
10
|
+
} else if (process.env.DEPLOYMENT_TYPE === "preview" && process.env.PR_NUMBER) {
|
|
11
|
+
websiteBaseUrl = `/webcomponents/pr-${process.env.PR_NUMBER}/`;
|
|
29
12
|
}
|
|
30
13
|
|
|
31
14
|
const getScripts = (options) => {
|
|
@@ -36,7 +19,7 @@ const getScripts = (options) => {
|
|
|
36
19
|
const createIllustrationsJSImportsScript = illustrations.join(" && ");
|
|
37
20
|
|
|
38
21
|
// The script creates the "src/generated/js-imports/Illustration.js" file that registers loaders (dynamic JS imports) for each illustration
|
|
39
|
-
const createIllustrationsLoadersScript = illustrationsData.map(illustrations => `node ${LIB}/generate-js-imports/illustrations.js ${illustrations.
|
|
22
|
+
const createIllustrationsLoadersScript = illustrationsData.map(illustrations => `node ${LIB}/generate-js-imports/illustrations.js ${illustrations.path} ${illustrations.dynamicImports.outputFile} ${illustrations.set} ${illustrations.collection} ${illustrations.dynamicImports.location} ${illustrations.dynamicImports.filterOut.join(",")}`).join(" && ");
|
|
40
23
|
|
|
41
24
|
const tsOption = !options.legacy || options.jsx;
|
|
42
25
|
const tsCommandOld = tsOption ? "tsc" : "";
|
|
@@ -45,7 +28,6 @@ const getScripts = (options) => {
|
|
|
45
28
|
if (options.noWatchTS) {
|
|
46
29
|
tsWatchCommandStandalone = "";
|
|
47
30
|
}
|
|
48
|
-
const tsCrossEnv = tsOption ? "cross-env UI5_TS=true" : "";
|
|
49
31
|
|
|
50
32
|
if (tsOption) {
|
|
51
33
|
try {
|
|
@@ -74,97 +56,109 @@ const getScripts = (options) => {
|
|
|
74
56
|
eslintConfig = "";
|
|
75
57
|
} else {
|
|
76
58
|
// no custom configuration - use default from tools project
|
|
77
|
-
eslintConfig = `--config
|
|
59
|
+
eslintConfig = `--config "${require.resolve("@ui5/webcomponents-tools/components-package/eslint.js")}"`;
|
|
78
60
|
}
|
|
79
61
|
|
|
80
62
|
const scripts = {
|
|
81
|
-
|
|
63
|
+
__ui5envs: {
|
|
64
|
+
UI5_CEM_MODE: options.dev,
|
|
65
|
+
UI5_TS: !!tsOption,
|
|
66
|
+
CYPRESS_COVERAGE: !!(options.internal?.cypress_code_coverage),
|
|
67
|
+
CYPRESS_UI5_ACC: !!(options.internal?.cypress_acc_tests),
|
|
68
|
+
},
|
|
69
|
+
clean: {
|
|
70
|
+
default: 'ui5nps clean.generated scope.testPages.clean',
|
|
71
|
+
generated: 'rimraf src/generated && rimraf dist',
|
|
72
|
+
},
|
|
82
73
|
lint: `eslint . ${eslintConfig}`,
|
|
83
74
|
lintfix: `eslint . ${eslintConfig} --fix`,
|
|
84
75
|
generate: {
|
|
85
|
-
default:
|
|
86
|
-
all:
|
|
87
|
-
styleRelated: "
|
|
76
|
+
default: `ui5nps prepare.all`,
|
|
77
|
+
all: `ui5nps-p build.templates build.i18n prepare.styleRelated copyProps build.illustrations`, // concurently
|
|
78
|
+
styleRelated: "ui5nps build.styles build.jsonImports build.jsImports",
|
|
88
79
|
},
|
|
89
80
|
prepare: {
|
|
90
|
-
default:
|
|
91
|
-
all:
|
|
92
|
-
styleRelated: "
|
|
81
|
+
default: `ui5nps clean prepare.all copy copyProps prepare.typescript generateAPI`,
|
|
82
|
+
all: `ui5nps-p build.templates build.i18n prepare.styleRelated build.illustrations`, // concurently
|
|
83
|
+
styleRelated: "ui5nps build.styles build.jsonImports build.jsImports",
|
|
93
84
|
typescript: tsCommandOld,
|
|
94
85
|
},
|
|
95
86
|
build: {
|
|
96
|
-
default: "
|
|
97
|
-
templates: `mkdirp src/generated/templates &&
|
|
87
|
+
default: "ui5nps prepare lint build.bundle", // build.bundle2
|
|
88
|
+
templates: options.legacy ? `mkdirp src/generated/templates && node "${LIB}/hbs2ui5/index.js" -d src/ -o src/generated/templates` : "",
|
|
98
89
|
styles: {
|
|
99
|
-
default: `
|
|
90
|
+
default: `ui5nps-p build.styles.themes build.styles.components`, // concurently
|
|
100
91
|
themes: `node "${LIB}/css-processors/css-processor-themes.mjs"`,
|
|
92
|
+
themesWithWatch: `node "${LIB}/css-processors/css-processor-themes.mjs" -w`,
|
|
101
93
|
components: `node "${LIB}/css-processors/css-processor-components.mjs"`,
|
|
94
|
+
componentsWithWatch: `node "${LIB}/css-processors/css-processor-components.mjs" -w`,
|
|
102
95
|
},
|
|
103
96
|
i18n: {
|
|
104
|
-
default: "
|
|
97
|
+
default: "ui5nps build.i18n.defaultsjs build.i18n.json",
|
|
105
98
|
defaultsjs: `node "${LIB}/i18n/defaults.js" src/i18n src/generated/i18n`,
|
|
106
99
|
json: `node "${LIB}/i18n/toJSON.js" src/i18n dist/generated/assets/i18n`,
|
|
107
100
|
},
|
|
108
101
|
jsonImports: {
|
|
109
|
-
default: "
|
|
110
|
-
themes: `node "${LIB}/generate-json-imports/themes.js"
|
|
111
|
-
i18n: `node "${LIB}/generate-json-imports/i18n.js"
|
|
102
|
+
default: "ui5nps build.jsonImports.themes build.jsonImports.i18n",
|
|
103
|
+
themes: `node "${LIB}/generate-json-imports/themes.js" src/themes src/generated/json-imports`,
|
|
104
|
+
i18n: `node "${LIB}/generate-json-imports/i18n.js" src/i18n src/generated/json-imports`,
|
|
112
105
|
},
|
|
113
106
|
jsImports: {
|
|
114
|
-
default: "
|
|
107
|
+
default: "ui5nps build.jsImports.illustrationsLoaders",
|
|
115
108
|
illustrationsLoaders: createIllustrationsLoadersScript,
|
|
116
109
|
},
|
|
117
|
-
bundle: `vite build ${viteConfig} --mode testing
|
|
110
|
+
bundle: `vite build ${viteConfig} --mode testing --base ${websiteBaseUrl}`,
|
|
118
111
|
bundle2: ``,
|
|
119
112
|
illustrations: createIllustrationsJSImportsScript,
|
|
120
113
|
},
|
|
121
114
|
copyProps: `node "${LIB}/copy-and-watch/index.js" --silent "src/i18n/*.properties" dist/`,
|
|
115
|
+
copyPropsWithWatch: `node "${LIB}/copy-and-watch/index.js" --silent "src/i18n/*.properties" dist/ --watch --safe --skip-initial-copy`,
|
|
122
116
|
copy: {
|
|
123
|
-
default: "
|
|
124
|
-
src: `node "${LIB}/copy-and-watch/index.js" --silent "src/**/*.{js,json}" dist
|
|
125
|
-
props: `node "${LIB}/copy-and-watch/index.js" --silent "src/i18n/*.properties" dist
|
|
117
|
+
default: options.legacy ? "ui5nps copy.src copy.props" : "",
|
|
118
|
+
src: options.legacy ? `node "${LIB}/copy-and-watch/index.js" --silent "src/**/*.{js,json}" dist/` : "",
|
|
119
|
+
props: options.legacy ? `node "${LIB}/copy-and-watch/index.js" --silent "src/i18n/*.properties" dist/` : "",
|
|
126
120
|
},
|
|
127
121
|
watch: {
|
|
128
|
-
default:
|
|
129
|
-
devServer: '
|
|
130
|
-
src: '
|
|
122
|
+
default: `ui5nps-p watch.templates watch.typescript watch.src watch.styles watch.i18n watch.props`, // concurently
|
|
123
|
+
devServer: 'ui5nps-p watch.default watch.bundle', // concurently
|
|
124
|
+
src: options.legacy ? 'ui5nps "copy.src --watch --safe --skip-initial-copy"' : "",
|
|
131
125
|
typescript: tsWatchCommandStandalone,
|
|
132
|
-
props: '
|
|
126
|
+
props: 'ui5nps copyPropsWithWatch',
|
|
133
127
|
bundle: `node ${LIB}/dev-server/dev-server.mjs ${viteConfig}`,
|
|
134
128
|
styles: {
|
|
135
|
-
default: '
|
|
136
|
-
themes: '
|
|
137
|
-
components: `
|
|
129
|
+
default: 'ui5nps-p watch.styles.themes watch.styles.components', // concurently
|
|
130
|
+
themes: 'ui5nps build.styles.themesWithWatch',
|
|
131
|
+
components: `ui5nps build.styles.componentsWithWatch`,
|
|
138
132
|
},
|
|
139
|
-
templates: 'chokidar "src/**/*.hbs" -i "src/generated" -c "
|
|
140
|
-
i18n: 'chokidar "src/i18n/messagebundle.properties" -c "
|
|
133
|
+
templates: options.legacy ? 'chokidar "src/**/*.hbs" -i "src/generated" -c "ui5nps build.templates"' : "",
|
|
134
|
+
i18n: 'chokidar "src/i18n/messagebundle.properties" -c "ui5nps build.i18n.defaultsjs"'
|
|
141
135
|
},
|
|
142
|
-
start: "
|
|
136
|
+
start: "ui5nps prepare watch.devServer",
|
|
143
137
|
test: `node "${LIB}/test-runner/test-runner.js"`,
|
|
144
|
-
"test-cy-ci":
|
|
145
|
-
"test-cy-ci-suite-1":
|
|
146
|
-
"test-cy-ci-suite-2":
|
|
147
|
-
"test-cy-
|
|
148
|
-
"test-suite-
|
|
149
|
-
"test-
|
|
150
|
-
startWithScope: "
|
|
138
|
+
"test-cy-ci": `cypress run --component --browser chrome`,
|
|
139
|
+
"test-cy-ci-suite-1": `cypress run --component --browser chrome --spec "**/specs/[A-C]*.cy.{js,jsx,ts,tsx},**/specs/[^D-Z]*.cy.{js,jsx,ts,tsx}"`,
|
|
140
|
+
"test-cy-ci-suite-2": `cypress run --component --browser chrome --spec "**/specs/[D-L]*.cy.{js,jsx,ts,tsx}"`,
|
|
141
|
+
"test-cy-ci-suite-3": `cypress run --component --browser chrome --spec "**/specs/[M-S]*.cy.{js,jsx,ts,tsx}"`,
|
|
142
|
+
"test-cy-ci-suite-4": `cypress run --component --browser chrome --spec "**/specs/[T-Z]*.cy.{js,jsx,ts,tsx}"`,
|
|
143
|
+
"test-cy-open": `cypress open --component --browser chrome`,
|
|
144
|
+
startWithScope: "ui5nps scope.prepare scope.watchWithBundle",
|
|
151
145
|
scope: {
|
|
152
|
-
prepare: "
|
|
146
|
+
prepare: "ui5nps scope.lint scope.testPages",
|
|
153
147
|
lint: `node "${LIB}/scoping/lint-src.js"`,
|
|
154
148
|
testPages: {
|
|
155
|
-
default: "
|
|
149
|
+
default: "ui5nps scope.testPages.clean scope.testPages.copy scope.testPages.replace",
|
|
156
150
|
clean: "rimraf test/pages/scoped",
|
|
157
151
|
copy: `node "${LIB}/copy-and-watch/index.js" --silent "test/pages/**/*" test/pages/scoped`,
|
|
158
152
|
replace: `node "${LIB}/scoping/scope-test-pages.js" test/pages/scoped demo`,
|
|
159
153
|
},
|
|
160
|
-
watchWithBundle: '
|
|
161
|
-
watch: '
|
|
154
|
+
watchWithBundle: 'ui5nps-p scope.watch scope.bundle', // concurently
|
|
155
|
+
watch: 'ui5nps-p watch.templates watch.props watch.styles', // concurently
|
|
162
156
|
bundle: `node ${LIB}/dev-server/dev-server.mjs ${viteConfig}`,
|
|
163
157
|
},
|
|
164
158
|
generateAPI: {
|
|
165
|
-
default: tsOption ? "
|
|
166
|
-
generateCEM:
|
|
167
|
-
validateCEM:
|
|
159
|
+
default: tsOption ? "ui5nps generateAPI.generateCEM generateAPI.validateCEM" : "",
|
|
160
|
+
generateCEM: `cem analyze --config "${LIB}/cem/custom-elements-manifest.config.mjs"`,
|
|
161
|
+
validateCEM: `node "${LIB}/cem/validate.js"`,
|
|
168
162
|
},
|
|
169
163
|
};
|
|
170
164
|
|
package/icons-collection/nps.js
CHANGED
|
@@ -7,7 +7,7 @@ const createIconImportsCommand = (options) => {
|
|
|
7
7
|
return `node "${LIB}/create-icons/index.js" "${options.collectionName}"`;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
const command
|
|
10
|
+
const command = { default: "ui5nps" };
|
|
11
11
|
options.versions.forEach((v) => {
|
|
12
12
|
command.default += ` build.icons.create${v}`;
|
|
13
13
|
command[`create${v}`] = `node "${LIB}/create-icons/index.js" "${options.collectionName}" "${v}"`;
|
|
@@ -16,17 +16,19 @@ const createIconImportsCommand = (options) => {
|
|
|
16
16
|
return command;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
const hashesCheck = cmd => `(node "${LIB}/icons-hash/icons-hash.mjs" check) || (${cmd} && node "${LIB}/icons-hash/icons-hash.mjs" save)`;
|
|
20
|
+
|
|
19
21
|
const copyIconAssetsCommand = (options) => {
|
|
20
22
|
if (!options.versions) {
|
|
21
|
-
return
|
|
22
|
-
default: "
|
|
23
|
+
return {
|
|
24
|
+
default: "ui5nps copy.json-imports copy.icon-collection",
|
|
23
25
|
"json-imports": `node "${LIB}/copy-and-watch/index.js" --silent "src/**/*.js" dist/`,
|
|
24
26
|
"icon-collection": `node "${LIB}/copy-and-watch/index.js" --silent "src/*.json" src/generated/assets/`,
|
|
25
27
|
}
|
|
26
28
|
}
|
|
27
29
|
|
|
28
|
-
const command
|
|
29
|
-
default: "
|
|
30
|
+
const command = {
|
|
31
|
+
default: "ui5nps copy.json-imports ",
|
|
30
32
|
"json-imports": `node "${LIB}/copy-and-watch/index.js" --silent "src/**/*.js" dist/`,
|
|
31
33
|
};
|
|
32
34
|
|
|
@@ -42,22 +44,25 @@ const getScripts = (options) => {
|
|
|
42
44
|
const createJSImportsCmd = createIconImportsCommand(options);
|
|
43
45
|
const copyAssetsCmd = copyIconAssetsCommand(options);
|
|
44
46
|
const tsCommand = !options.legacy ? "tsc --build" : "";
|
|
45
|
-
const
|
|
47
|
+
const tsOption = !options.legacy;
|
|
46
48
|
|
|
47
49
|
const scripts = {
|
|
50
|
+
__ui5envs:{
|
|
51
|
+
UI5_TS: tsOption,
|
|
52
|
+
},
|
|
48
53
|
clean: "rimraf dist && rimraf src/generated",
|
|
49
54
|
copy: copyAssetsCmd,
|
|
50
|
-
generate:
|
|
55
|
+
generate: hashesCheck(`ui5nps clean copy build.i18n build.icons build.jsonImports copyjson`),
|
|
51
56
|
copyjson: "copy-and-watch \"src/generated/**/*.json\" dist/generated/",
|
|
52
57
|
build: {
|
|
53
|
-
default:
|
|
58
|
+
default: hashesCheck(`ui5nps clean copy build.i18n typescript build.icons build.jsonImports`),
|
|
54
59
|
i18n: {
|
|
55
|
-
default: "
|
|
56
|
-
defaultsjs: `
|
|
57
|
-
json: `
|
|
60
|
+
default: "ui5nps build.i18n.defaultsjs build.i18n.json",
|
|
61
|
+
defaultsjs: `node "${LIB}/i18n/defaults.js" src/i18n src/generated/i18n`,
|
|
62
|
+
json: `node "${LIB}/i18n/toJSON.js" src/i18n src/generated/assets/i18n`,
|
|
58
63
|
},
|
|
59
64
|
jsonImports: {
|
|
60
|
-
default: "
|
|
65
|
+
default: "ui5nps build.jsonImports.i18n",
|
|
61
66
|
i18n: `node "${LIB}/generate-json-imports/i18n.js" src/generated/assets/i18n src/generated/json-imports`,
|
|
62
67
|
},
|
|
63
68
|
icons: createJSImportsCmd,
|
|
@@ -2,72 +2,68 @@ const fs = require("fs").promises;
|
|
|
2
2
|
const path = require("path");
|
|
3
3
|
|
|
4
4
|
const generateDynamicImportLines = async (fileNames, location, exclusionPatterns = []) => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
const generateAvailableIllustrationsArray = (fileNames, exclusionPatterns = []) => {
|
|
17
|
-
return JSON.stringify(
|
|
18
|
-
fileNames
|
|
19
|
-
.filter((fileName) => !exclusionPatterns.some((pattern) => fileName.startsWith(pattern)))
|
|
20
|
-
.map((fileName) => fileName.replace(".js", ""))
|
|
21
|
-
);
|
|
5
|
+
const packageName = JSON.parse(await fs.readFile("package.json")).name;
|
|
6
|
+
return fileNames
|
|
7
|
+
.filter((fileName) => !exclusionPatterns.some((pattern) => fileName.startsWith(pattern)))
|
|
8
|
+
.map((fileName) => {
|
|
9
|
+
const illustrationName = fileName.replace(".svg", "");
|
|
10
|
+
const illustrationPath = `${location}/${illustrationName}`;
|
|
11
|
+
return `\t\tcase "${fileName.replace('.js', '')}": return (await import(/* webpackChunkName: "${packageName.replace("@", "").replace("/", "-")}-${illustrationName.toLowerCase()}" */ "${illustrationPath}.js")).default;`;
|
|
12
|
+
})
|
|
13
|
+
.join("\n");
|
|
22
14
|
};
|
|
23
15
|
|
|
24
16
|
const generateDynamicImportsFileContent = (dynamicImports, availableIllustrations, collection, set, prefix = "") => {
|
|
25
|
-
|
|
26
|
-
|
|
17
|
+
return `// @ts-nocheck
|
|
18
|
+
import { registerIllustrationLoader } from "@ui5/webcomponents-base/dist/asset-registries/Illustrations.js";
|
|
27
19
|
|
|
28
20
|
export const loadIllustration = async (illustrationName) => {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
21
|
+
const collectionAndPrefix = "${set}/${collection}/${prefix}";
|
|
22
|
+
const cleanIllustrationName = illustrationName.startsWith(collectionAndPrefix) ? illustrationName.replace(collectionAndPrefix, "") : illustrationName;
|
|
23
|
+
switch (cleanIllustrationName) {
|
|
32
24
|
${dynamicImports}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
25
|
+
default:
|
|
26
|
+
throw new Error("[Illustrations] Illustration not found: " + illustrationName);
|
|
27
|
+
}
|
|
36
28
|
};
|
|
37
29
|
|
|
38
30
|
const loadAndCheck = async (illustrationName) => {
|
|
39
|
-
|
|
40
|
-
|
|
31
|
+
const data = await loadIllustration(illustrationName);
|
|
32
|
+
return data;
|
|
41
33
|
};
|
|
42
34
|
|
|
43
35
|
${availableIllustrations}.forEach((illustrationName) =>
|
|
44
|
-
|
|
36
|
+
registerIllustrationLoader(\`${set}/${collection}/${prefix}\${illustrationName}\`, loadAndCheck)
|
|
45
37
|
);
|
|
46
38
|
`;
|
|
47
39
|
};
|
|
48
40
|
|
|
49
41
|
const getMatchingFiles = async (folder, pattern) => {
|
|
50
|
-
|
|
51
|
-
|
|
42
|
+
const dir = await fs.readdir(folder);
|
|
43
|
+
return dir.filter((fileName) => fileName.match(pattern));
|
|
52
44
|
};
|
|
53
45
|
|
|
54
46
|
const generateIllustrations = async (config) => {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const normalizedInputFolder = path.normalize(inputFolder);
|
|
58
|
-
const normalizedOutputFile = path.normalize(outputFile);
|
|
47
|
+
const { inputFolder, outputFile, collection, location, prefix, filterOut, set } = config;
|
|
59
48
|
|
|
60
|
-
|
|
49
|
+
const normalizedInputFolder = path.normalize(inputFolder);
|
|
50
|
+
const normalizedOutputFile = path.normalize(outputFile);
|
|
61
51
|
|
|
62
|
-
|
|
63
|
-
const availableIllustrations = generateAvailableIllustrationsArray(illustrations, filterOut);
|
|
52
|
+
const svgFiles = await getMatchingFiles(normalizedInputFolder, /\.svg$/);
|
|
64
53
|
|
|
65
|
-
|
|
54
|
+
const illustrations = [
|
|
55
|
+
...new Set(
|
|
56
|
+
svgFiles
|
|
57
|
+
.filter(name => !name.includes("sapIllus-Patterns"))
|
|
58
|
+
.map(name => name.split("-").pop().replace(".svg", ""))
|
|
59
|
+
),
|
|
60
|
+
];
|
|
66
61
|
|
|
67
|
-
|
|
68
|
-
|
|
62
|
+
const dynamicImports = await generateDynamicImportLines(illustrations, location, filterOut);
|
|
63
|
+
const contentDynamic = generateDynamicImportsFileContent(dynamicImports, JSON.stringify(illustrations), collection, set, prefix);
|
|
69
64
|
|
|
70
|
-
|
|
65
|
+
await fs.mkdir(path.dirname(normalizedOutputFile), { recursive: true });
|
|
66
|
+
await fs.writeFile(normalizedOutputFile, contentDynamic);
|
|
71
67
|
};
|
|
72
68
|
|
|
73
69
|
// Parse configuration from command-line arguments
|
|
@@ -77,10 +73,10 @@ const config = {
|
|
|
77
73
|
set: process.argv[4],
|
|
78
74
|
collection: process.argv[5],
|
|
79
75
|
location: process.argv[6],
|
|
80
|
-
filterOut: process.argv
|
|
76
|
+
filterOut: process.argv[7].slice().split(","),
|
|
81
77
|
};
|
|
82
78
|
|
|
83
79
|
// Run the generation process
|
|
84
80
|
generateIllustrations(config).catch((error) => {
|
|
85
|
-
|
|
81
|
+
console.error("Error generating illustrations:", error);
|
|
86
82
|
});
|
|
@@ -44,7 +44,7 @@ const generate = async () => {
|
|
|
44
44
|
// All languages present in the file system
|
|
45
45
|
const files = await fs.readdir(inputFolder);
|
|
46
46
|
const languages = files.map(file => {
|
|
47
|
-
const matches = file.match(/messagebundle_(.+?).
|
|
47
|
+
const matches = file.match(/messagebundle_(.+?).properties$/);
|
|
48
48
|
return matches ? matches[1] : undefined;
|
|
49
49
|
}).filter(key => !!key);
|
|
50
50
|
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import fs from "fs/promises";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import ignore from "ignore";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = path.dirname(__filename);
|
|
8
|
+
|
|
9
|
+
// -------------------
|
|
10
|
+
// FNV-1a 32-bit hash
|
|
11
|
+
// -------------------
|
|
12
|
+
function fnv1aHash(str) {
|
|
13
|
+
let hash = 0x811c9dc5;
|
|
14
|
+
for (let i = 0; i < str.length; i++) {
|
|
15
|
+
hash ^= str.charCodeAt(i);
|
|
16
|
+
hash = (hash * 0x01000193) >>> 0;
|
|
17
|
+
}
|
|
18
|
+
return hash.toString(16);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function findGitignoreFiles(startDir) {
|
|
22
|
+
const gitignores = [];
|
|
23
|
+
let currentDir = path.resolve(startDir);
|
|
24
|
+
while (true) {
|
|
25
|
+
const candidate = path.join(currentDir, ".gitignore");
|
|
26
|
+
try {
|
|
27
|
+
await fs.access(candidate);
|
|
28
|
+
gitignores.push(candidate);
|
|
29
|
+
} catch { }
|
|
30
|
+
const parentDir = path.dirname(currentDir);
|
|
31
|
+
if (parentDir === currentDir) break;
|
|
32
|
+
currentDir = parentDir;
|
|
33
|
+
}
|
|
34
|
+
return gitignores;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async function loadIgnoreRules(dir) {
|
|
38
|
+
const files = await findGitignoreFiles(dir);
|
|
39
|
+
const ig = ignore();
|
|
40
|
+
for (const file of files) {
|
|
41
|
+
const content = await fs.readFile(file, "utf8");
|
|
42
|
+
ig.add(content);
|
|
43
|
+
}
|
|
44
|
+
return ig;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function walkDir(dir, ig, baseDir) {
|
|
48
|
+
const results = [];
|
|
49
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
50
|
+
|
|
51
|
+
for (const entry of entries) {
|
|
52
|
+
const absPath = path.join(dir, entry.name);
|
|
53
|
+
let relPath = path.relative(baseDir, absPath).replace(/\\/g, "/"); // normalize for .gitignore
|
|
54
|
+
|
|
55
|
+
if (ig.ignores(relPath) || relPath.startsWith("dist/")) continue;
|
|
56
|
+
|
|
57
|
+
if (entry.isDirectory()) {
|
|
58
|
+
results.push(...await walkDir(absPath, ig, baseDir));
|
|
59
|
+
} else {
|
|
60
|
+
results.push(relPath);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return results;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Hash file content + mtime
|
|
67
|
+
async function hashFile(filePath) {
|
|
68
|
+
const stat = await fs.stat(filePath);
|
|
69
|
+
const content = await fs.readFile(filePath, "utf8");
|
|
70
|
+
return fnv1aHash(String(stat.mtimeMs) + content);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function getRepoName(repoPath) {
|
|
74
|
+
return repoPath.split("/").pop();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async function computeHashes(repoPath, ig) {
|
|
78
|
+
const files = await walkDir(repoPath, ig, repoPath);
|
|
79
|
+
const hashEntries = await Promise.all(
|
|
80
|
+
files.map(async (file) => {
|
|
81
|
+
const absPath = path.join(repoPath, file);
|
|
82
|
+
const hash = await hashFile(absPath);
|
|
83
|
+
return [path.relative(process.cwd(), absPath), hash];
|
|
84
|
+
})
|
|
85
|
+
);
|
|
86
|
+
return Object.fromEntries(hashEntries);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async function saveHashes(repoPath, ig) {
|
|
90
|
+
const distPath = path.join(repoPath, "dist");
|
|
91
|
+
await fs.mkdir(distPath, { recursive: true });
|
|
92
|
+
const ui5iconsHashPath = path.join(distPath, ".ui5iconsHash");
|
|
93
|
+
|
|
94
|
+
// Cache the hashes for both the icons and tools packages, since the output depends on the content of both.
|
|
95
|
+
const hashes = {
|
|
96
|
+
...(await computeHashes(repoPath, ig)),
|
|
97
|
+
...(await computeHashes(path.resolve(__dirname, "../../"), ig)),
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
await fs.writeFile(ui5iconsHashPath, JSON.stringify(hashes, null, 2), "utf8");
|
|
101
|
+
console.log(`Saved build hashes for the ${getRepoName(repoPath)} package.`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async function checkHashes(repoPath, ig) {
|
|
105
|
+
const ui5iconsHashPath = path.join(repoPath, "dist", ".ui5iconsHash");
|
|
106
|
+
let oldHashes = {};
|
|
107
|
+
try {
|
|
108
|
+
const raw = await fs.readFile(ui5iconsHashPath, "utf8");
|
|
109
|
+
oldHashes = JSON.parse(raw);
|
|
110
|
+
} catch {
|
|
111
|
+
console.log(`No build hashes found for the ${getRepoName(repoPath)} package. Building it now.`);
|
|
112
|
+
process.exit(1);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Compare the hashes for both the icons and tools packages, since the output depends on the content of both.
|
|
116
|
+
const newHashes = {
|
|
117
|
+
...(await computeHashes(repoPath, ig)),
|
|
118
|
+
...(await computeHashes(path.resolve(__dirname, "../../"), ig)),
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
let changed = false;
|
|
122
|
+
for (const file of new Set([...Object.keys(oldHashes), ...Object.keys(newHashes)])) {
|
|
123
|
+
if (oldHashes[file] !== newHashes[file]) {
|
|
124
|
+
changed = true;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (!changed) {
|
|
129
|
+
console.log(`No changes detected in the ${getRepoName(repoPath)} package.`);
|
|
130
|
+
} else {
|
|
131
|
+
console.log(`Changes detected in the ${getRepoName(repoPath)} package. Rebuilding it.`);
|
|
132
|
+
process.exit(1);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async function main() {
|
|
137
|
+
const mode = process.argv[2];
|
|
138
|
+
if (!["save", "check"].includes(mode)) {
|
|
139
|
+
throw new Error("Usage: node hashes.js <save|check>");
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const repoPath = process.cwd();
|
|
143
|
+
const ig = await loadIgnoreRules(repoPath);
|
|
144
|
+
|
|
145
|
+
if (mode === "save") await saveHashes(repoPath, ig);
|
|
146
|
+
if (mode === "check") await checkHashes(repoPath, ig);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
main().catch(console.error);
|
package/package.json
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ui5/webcomponents-tools",
|
|
3
|
-
"version": "2.15.0-rc.
|
|
3
|
+
"version": "2.15.0-rc.2",
|
|
4
4
|
"description": "UI5 Web Components: webcomponents.tools",
|
|
5
5
|
"author": "SAP SE (https://www.sap.com)",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
|
-
"private": false,
|
|
8
7
|
"keywords": [
|
|
9
8
|
"openui5",
|
|
10
9
|
"sapui5",
|
|
11
10
|
"ui5"
|
|
12
11
|
],
|
|
13
|
-
"scripts": {},
|
|
14
12
|
"bin": {
|
|
15
|
-
"
|
|
16
|
-
"wc-create-ui5-element": "bin/create-ui5-element.js"
|
|
13
|
+
"ui5nps": "bin/ui5nps.js",
|
|
14
|
+
"wc-create-ui5-element": "bin/create-ui5-element.js",
|
|
15
|
+
"wc-dev": "bin/dev.js"
|
|
17
16
|
},
|
|
18
17
|
"repository": {
|
|
19
18
|
"type": "git",
|
|
@@ -53,10 +52,10 @@
|
|
|
53
52
|
"glob-parent": "^6.0.2",
|
|
54
53
|
"globby": "^13.1.1",
|
|
55
54
|
"handlebars": "^4.7.7",
|
|
55
|
+
"ignore": "^7.0.5",
|
|
56
56
|
"is-port-reachable": "^3.1.0",
|
|
57
57
|
"json-beautify": "^1.1.1",
|
|
58
58
|
"mkdirp": "^1.0.4",
|
|
59
|
-
"nps": "^5.10.0",
|
|
60
59
|
"postcss": "^8.4.5",
|
|
61
60
|
"postcss-cli": "^9.1.0",
|
|
62
61
|
"postcss-selector-parser": "^6.0.10",
|
|
@@ -83,5 +82,5 @@
|
|
|
83
82
|
"esbuild": "^0.25.0",
|
|
84
83
|
"yargs": "^17.5.1"
|
|
85
84
|
},
|
|
86
|
-
"gitHead": "
|
|
85
|
+
"gitHead": "ed55cd91014aec191705b37b57e8cf5dc8cc95ce"
|
|
87
86
|
}
|