@ui5/webcomponents-tools 0.0.0-dcd8e5389 → 0.0.0-ddc5fe31b
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 +413 -0
- package/README.md +2 -1
- package/assets-meta.js +16 -7
- package/components-package/eslint.js +2 -0
- package/components-package/nps.js +38 -31
- package/components-package/postcss.components.js +1 -21
- package/components-package/postcss.themes.js +1 -26
- package/components-package/wdio.js +15 -3
- package/components-package/wdio.sync.js +9 -1
- package/icons-collection/nps.js +8 -6
- package/lib/amd-to-es6/index.js +104 -0
- package/lib/cem/custom-elements-manifest.config.mjs +482 -0
- package/lib/cem/event.mjs +131 -0
- package/lib/cem/schema-internal.json +1357 -0
- package/lib/cem/schema.json +1098 -0
- package/lib/cem/types-internal.d.ts +802 -0
- package/lib/cem/types.d.ts +736 -0
- package/lib/cem/utils.mjs +379 -0
- package/lib/cem/validate.js +65 -0
- package/lib/create-illustrations/index.js +32 -28
- package/lib/create-new-component/index.js +1 -1
- package/lib/create-new-component/tsFileContentTemplate.js +2 -11
- package/lib/css-processors/css-processor-components.mjs +77 -0
- package/lib/css-processors/css-processor-themes.mjs +79 -0
- package/lib/css-processors/scope-variables.mjs +46 -0
- package/lib/{postcss-css-to-esm/index.js → css-processors/shared.mjs} +36 -50
- package/lib/dev-server/custom-hot-update-plugin.js +39 -0
- package/lib/generate-custom-elements-manifest/index.js +51 -107
- package/lib/generate-js-imports/illustrations.js +78 -64
- package/lib/generate-json-imports/i18n.js +10 -5
- package/lib/generate-json-imports/themes.js +10 -5
- package/lib/hbs2lit/src/litVisitor2.js +1 -1
- package/lib/hbs2ui5/RenderTemplates/LitRenderer.js +4 -4
- package/lib/jsdoc/preprocess.js +1 -1
- package/lib/postcss-combine-duplicated-selectors/index.js +12 -5
- package/lib/scoping/get-all-tags.js +1 -1
- package/lib/scoping/scope-test-pages.js +2 -1
- package/package.json +9 -9
- package/lib/esm-abs-to-rel/index.js +0 -58
- package/lib/postcss-css-to-json/index.js +0 -47
- package/lib/postcss-new-files/index.js +0 -36
- package/lib/postcss-p/postcss-p.mjs +0 -14
- package/lib/replace-global-core/index.js +0 -25
@@ -0,0 +1,379 @@
|
|
1
|
+
import fs from "fs";
|
2
|
+
import path from "path";
|
3
|
+
|
4
|
+
let documentationErrors = new Map();
|
5
|
+
|
6
|
+
const getDeprecatedStatus = (jsdocComment) => {
|
7
|
+
const deprecatedTag = findTag(jsdocComment, "deprecated");
|
8
|
+
return deprecatedTag?.name
|
9
|
+
? deprecatedTag.description
|
10
|
+
? `${deprecatedTag.name} ${deprecatedTag.description}`
|
11
|
+
: deprecatedTag.name
|
12
|
+
: deprecatedTag
|
13
|
+
? true
|
14
|
+
: undefined;
|
15
|
+
};
|
16
|
+
|
17
|
+
const normalizeDescription = (description) => {
|
18
|
+
return typeof description === 'string' ? description.replaceAll(/^-\s+|^(\n)+|(\n)+$/g, ""): description;
|
19
|
+
}
|
20
|
+
|
21
|
+
const getTypeRefs = (ts, node, member) => {
|
22
|
+
const extractTypeRefs = (type) => {
|
23
|
+
if (type?.kind === ts.SyntaxKind.TypeReference) {
|
24
|
+
return type.typeArguments?.length
|
25
|
+
? type.typeArguments.map((typeRef) => typeRef.typeName?.text)
|
26
|
+
: [type.typeName?.text];
|
27
|
+
} else if (type?.kind === ts.SyntaxKind.ArrayType) {
|
28
|
+
return [type.elementType?.typeName?.text];
|
29
|
+
} else if (type?.kind === ts.SyntaxKind.UnionType) {
|
30
|
+
return type.types
|
31
|
+
.map((type) => extractTypeRefs(type))
|
32
|
+
.flat(1);
|
33
|
+
} else if (type?.kind === ts.SyntaxKind.TemplateLiteralType) {
|
34
|
+
if (member?.type) {
|
35
|
+
member.type.text = member.type.text.replaceAll?.(/`|\${|}/g, "");
|
36
|
+
}
|
37
|
+
|
38
|
+
return type.templateSpans?.length
|
39
|
+
? type.templateSpans.map((typeRef) => typeRef.type?.typeName?.text)
|
40
|
+
: [type.typeName?.text];
|
41
|
+
}
|
42
|
+
};
|
43
|
+
|
44
|
+
let typeRefs = extractTypeRefs(node.type) || node?.typeArguments?.map(n => extractTypeRefs(n)).flat(2);
|
45
|
+
|
46
|
+
if (typeRefs) {
|
47
|
+
typeRefs = typeRefs.filter((e) => !!e);
|
48
|
+
}
|
49
|
+
|
50
|
+
return typeRefs?.length ? typeRefs : undefined;
|
51
|
+
};
|
52
|
+
|
53
|
+
const getSinceStatus = (jsdocComment) => {
|
54
|
+
const sinceTag = findTag(jsdocComment, "since");
|
55
|
+
return sinceTag
|
56
|
+
? sinceTag.description
|
57
|
+
? `${sinceTag.name} ${sinceTag.description}`
|
58
|
+
: sinceTag.name
|
59
|
+
: undefined;
|
60
|
+
};
|
61
|
+
|
62
|
+
const getPrivacyStatus = (jsdocComment) => {
|
63
|
+
const privacyTag = findTag(jsdocComment, ["public", "private", "protected"]);
|
64
|
+
return privacyTag?.tag || "private";
|
65
|
+
};
|
66
|
+
|
67
|
+
const findPackageName = (ts, sourceFile, typeName) => {
|
68
|
+
const localStatements = [
|
69
|
+
ts.SyntaxKind.EnumDeclaration,
|
70
|
+
ts.SyntaxKind.InterfaceDeclaration,
|
71
|
+
ts.SyntaxKind.ClassDeclaration,
|
72
|
+
ts.SyntaxKind.TypeAliasDeclaration,
|
73
|
+
];
|
74
|
+
|
75
|
+
const isLocalDeclared = sourceFile.statements.some(
|
76
|
+
(statement) =>
|
77
|
+
localStatements.includes(statement.kind) && statement?.name?.text === typeName
|
78
|
+
);
|
79
|
+
|
80
|
+
if (isLocalDeclared) {
|
81
|
+
return packageJSON?.name;
|
82
|
+
} else {
|
83
|
+
const importStatements = sourceFile.statements?.filter(
|
84
|
+
(statement) => statement.kind === ts.SyntaxKind.ImportDeclaration
|
85
|
+
);
|
86
|
+
const currentModuleSpecifier = importStatements.find((statement) => {
|
87
|
+
if (statement.importClause?.name?.text === typeName) {
|
88
|
+
return true;
|
89
|
+
}
|
90
|
+
|
91
|
+
return statement.importClause?.namedBindings?.elements?.some(
|
92
|
+
(element) => element.name?.text === typeName
|
93
|
+
);
|
94
|
+
})?.moduleSpecifier;
|
95
|
+
|
96
|
+
if (currentModuleSpecifier?.text?.startsWith(".")) {
|
97
|
+
return packageJSON?.name;
|
98
|
+
} else {
|
99
|
+
return Object.keys(packageJSON?.dependencies || {}).find(
|
100
|
+
(dependency) =>
|
101
|
+
currentModuleSpecifier?.text?.startsWith(`${dependency}/`)
|
102
|
+
);
|
103
|
+
}
|
104
|
+
}
|
105
|
+
};
|
106
|
+
|
107
|
+
const findImportPath = (ts, sourceFile, typeName, modulePath) => {
|
108
|
+
const localStatements = [
|
109
|
+
ts.SyntaxKind.EnumDeclaration,
|
110
|
+
ts.SyntaxKind.InterfaceDeclaration,
|
111
|
+
ts.SyntaxKind.ClassDeclaration,
|
112
|
+
ts.SyntaxKind.TypeAliasDeclaration,
|
113
|
+
];
|
114
|
+
|
115
|
+
const isLocalDeclared = sourceFile.statements.some(
|
116
|
+
(statement) =>
|
117
|
+
localStatements.includes(statement.kind) && statement?.name?.text === typeName
|
118
|
+
);
|
119
|
+
|
120
|
+
if (isLocalDeclared) {
|
121
|
+
return (
|
122
|
+
modulePath?.replace("src", "dist")?.replace(".ts", ".js") || undefined
|
123
|
+
);
|
124
|
+
} else {
|
125
|
+
const importStatements = sourceFile.statements?.filter(
|
126
|
+
(statement) => statement.kind === ts.SyntaxKind.ImportDeclaration
|
127
|
+
);
|
128
|
+
const currentModuleSpecifier = importStatements.find((statement) => {
|
129
|
+
if (statement.importClause?.name?.text === typeName) {
|
130
|
+
return true;
|
131
|
+
}
|
132
|
+
|
133
|
+
return statement.importClause?.namedBindings?.elements?.some(
|
134
|
+
(element) => element.name?.text === typeName
|
135
|
+
);
|
136
|
+
})?.moduleSpecifier;
|
137
|
+
|
138
|
+
if (currentModuleSpecifier?.text?.startsWith(".")) {
|
139
|
+
return (
|
140
|
+
path.join(path.dirname(modulePath), currentModuleSpecifier.text)
|
141
|
+
?.replace("src", "dist")?.replace(".ts", ".js") || undefined
|
142
|
+
);
|
143
|
+
} else {
|
144
|
+
const packageName = Object.keys(packageJSON?.dependencies || {}).find(
|
145
|
+
(dependency) =>
|
146
|
+
currentModuleSpecifier?.text?.startsWith(dependency)
|
147
|
+
);
|
148
|
+
return currentModuleSpecifier?.text
|
149
|
+
?.replace(`${packageName}/`, "") || undefined;
|
150
|
+
}
|
151
|
+
}
|
152
|
+
};
|
153
|
+
|
154
|
+
|
155
|
+
const isClass = text => {
|
156
|
+
return text.includes("@abstract") || text.includes("@class") || text.includes("@constructor");
|
157
|
+
};
|
158
|
+
|
159
|
+
const normalizeTagType = (type) => {
|
160
|
+
return type?.trim();
|
161
|
+
}
|
162
|
+
|
163
|
+
const packageJSON = JSON.parse(fs.readFileSync("./package.json"));
|
164
|
+
|
165
|
+
const getReference = (ts, type, classNode, modulePath) => {
|
166
|
+
let sourceFile = classNode.parent;
|
167
|
+
|
168
|
+
while (sourceFile && sourceFile.kind !== ts.SyntaxKind.SourceFile) {
|
169
|
+
sourceFile = sourceFile.parent;
|
170
|
+
}
|
171
|
+
|
172
|
+
const typeName =
|
173
|
+
typeof type === "string"
|
174
|
+
? normalizeTagType(type)
|
175
|
+
: type.class?.expression?.text ||
|
176
|
+
type.typeExpression?.type?.getText() ||
|
177
|
+
type.typeExpression?.type?.elementType?.typeName?.text;
|
178
|
+
const packageName = findPackageName(ts, sourceFile, typeName);
|
179
|
+
const importPath = findImportPath(
|
180
|
+
ts,
|
181
|
+
sourceFile,
|
182
|
+
typeName,
|
183
|
+
modulePath
|
184
|
+
)?.replace(`${packageName}/`, "");
|
185
|
+
|
186
|
+
return packageName && {
|
187
|
+
name: typeName,
|
188
|
+
package: packageName,
|
189
|
+
module: importPath,
|
190
|
+
};
|
191
|
+
};
|
192
|
+
|
193
|
+
const getType = (type) => {
|
194
|
+
const typeName = typeof type === "string" ? normalizeTagType(type) : type?.type;
|
195
|
+
|
196
|
+
const multiple =
|
197
|
+
typeName?.endsWith("[]") || typeName?.startsWith("Array<");
|
198
|
+
const name = multiple
|
199
|
+
? typeName?.replace("[]", "")?.replace("Array<", "")?.replace(">", "")
|
200
|
+
: typeName;
|
201
|
+
|
202
|
+
return typeName ? { typeName: multiple ? `Array<${name}>` : typeName, name, multiple } : undefined;
|
203
|
+
};
|
204
|
+
|
205
|
+
const commonTags = ["public", "protected", "private", "since", "deprecated"];
|
206
|
+
|
207
|
+
const allowedTags = {
|
208
|
+
field: [...commonTags, "formEvents", "formProperty", "default"],
|
209
|
+
slot: [...commonTags, "default"],
|
210
|
+
event: [...commonTags, "param", "allowPreventDefault", "native"],
|
211
|
+
eventParam: [...commonTags],
|
212
|
+
method: [...commonTags, "param", "returns", "override"],
|
213
|
+
class: [...commonTags, "constructor", "class", "abstract", "implements", "extends", "slot", "csspart"],
|
214
|
+
enum: [...commonTags],
|
215
|
+
enumMember: [...commonTags],
|
216
|
+
interface: [...commonTags],
|
217
|
+
};
|
218
|
+
allowedTags.getter = [...allowedTags.field, "override"]
|
219
|
+
|
220
|
+
const tagMatchCallback = (tag, tagName) => {
|
221
|
+
const currentTagName = tag.tag;
|
222
|
+
|
223
|
+
return typeof tagName === "string"
|
224
|
+
? currentTagName === tagName
|
225
|
+
: tagName.includes(currentTagName);
|
226
|
+
};
|
227
|
+
|
228
|
+
const findDecorator = (node, decoratorName) => {
|
229
|
+
return node?.decorators?.find(
|
230
|
+
(decorator) =>
|
231
|
+
decorator?.expression?.expression?.text === decoratorName
|
232
|
+
);
|
233
|
+
};
|
234
|
+
|
235
|
+
const findAllDecorators = (node, decoratorName) => {
|
236
|
+
return (
|
237
|
+
node?.decorators?.filter(
|
238
|
+
(decorator) =>
|
239
|
+
decorator?.expression?.expression?.text === decoratorName
|
240
|
+
) || []
|
241
|
+
);
|
242
|
+
};
|
243
|
+
|
244
|
+
const hasTag = (jsDoc, tagName) => {
|
245
|
+
if (!jsDoc) {
|
246
|
+
return;
|
247
|
+
}
|
248
|
+
|
249
|
+
return jsDoc?.tags?.some((tag) => tagMatchCallback(tag, tagName));
|
250
|
+
};
|
251
|
+
|
252
|
+
const findTag = (jsDoc, tagName) => {
|
253
|
+
if (!jsDoc) {
|
254
|
+
return;
|
255
|
+
}
|
256
|
+
|
257
|
+
return jsDoc?.tags?.find((tag) => tagMatchCallback(tag, tagName));
|
258
|
+
};
|
259
|
+
|
260
|
+
const findAllTags = (jsDoc, tagName) => {
|
261
|
+
if (!jsDoc) {
|
262
|
+
return [];
|
263
|
+
}
|
264
|
+
|
265
|
+
const foundTags = jsDoc?.tags?.filter((tag) => tagMatchCallback(tag, tagName));
|
266
|
+
|
267
|
+
return foundTags || [];
|
268
|
+
};
|
269
|
+
|
270
|
+
const validateJSDocTag = (tag) => {
|
271
|
+
const booleanTags = ["private", "protected", "public", "abstract", "allowPreventDefault", "native", "formProperty", "constructor", "override"];
|
272
|
+
let tagName = tag.tag;
|
273
|
+
|
274
|
+
if (booleanTags.includes(tag.tag)) {
|
275
|
+
tagName = "boolean";
|
276
|
+
}
|
277
|
+
|
278
|
+
switch (tagName) {
|
279
|
+
case "boolean":
|
280
|
+
return !tag.name && !tag.type && !tag.description;
|
281
|
+
case "deprecated":
|
282
|
+
return !tag.type;
|
283
|
+
case "extends":
|
284
|
+
return !tag.type && tag.name && !tag.description;
|
285
|
+
case "implements":
|
286
|
+
return tag.type && !tag.name && !tag.description;
|
287
|
+
case "slot":
|
288
|
+
return tag.type && tag.name && tag.description;
|
289
|
+
case "csspart":
|
290
|
+
return !tag.type && tag.name && tag.description;
|
291
|
+
case "since":
|
292
|
+
return !tag.type && tag.name;
|
293
|
+
case "returns":
|
294
|
+
return !tag.type && tag.name;
|
295
|
+
case "default":
|
296
|
+
return !tag.type && !tag.description;
|
297
|
+
case "class":
|
298
|
+
return !tag.type;
|
299
|
+
case "param":
|
300
|
+
return !tag.type && tag.name;
|
301
|
+
case "eventparam":
|
302
|
+
return tag.type && tag.name;
|
303
|
+
case "formEvents":
|
304
|
+
return !tag.type && tag.name;
|
305
|
+
default:
|
306
|
+
return false;
|
307
|
+
}
|
308
|
+
};
|
309
|
+
|
310
|
+
const validateJSDocComment = (fieldType, jsdocComment, node, moduleDoc) => {
|
311
|
+
return !!jsdocComment?.tags?.every((tag) => {
|
312
|
+
let isValid = false
|
313
|
+
|
314
|
+
if (fieldType === "event" && tag?.tag === "param") {
|
315
|
+
isValid = allowedTags[fieldType]?.includes(tag.tag) && validateJSDocTag({...tag, tag: "eventparam"});
|
316
|
+
} else {
|
317
|
+
isValid = allowedTags[fieldType]?.includes(tag.tag) && validateJSDocTag(tag);
|
318
|
+
}
|
319
|
+
|
320
|
+
if (!isValid) {
|
321
|
+
logDocumentationError(moduleDoc.path, `Incorrect use of @${tag.tag}. Ensure it is part of ${fieldType} JSDoc tags.`)
|
322
|
+
}
|
323
|
+
|
324
|
+
return !!isValid;
|
325
|
+
});
|
326
|
+
};
|
327
|
+
|
328
|
+
const logDocumentationError = (modulePath, message) => {
|
329
|
+
let moduleErrors = documentationErrors.get(modulePath);
|
330
|
+
|
331
|
+
if (!moduleErrors) {
|
332
|
+
documentationErrors.set(modulePath, []);
|
333
|
+
moduleErrors = documentationErrors.get(modulePath);
|
334
|
+
}
|
335
|
+
|
336
|
+
moduleErrors.push(message);
|
337
|
+
}
|
338
|
+
|
339
|
+
const displayDocumentationErrors = () => {
|
340
|
+
let errorsCount = 0;
|
341
|
+
[...documentationErrors.keys()].forEach(modulePath => {
|
342
|
+
const moduleErrors = documentationErrors.get(modulePath);
|
343
|
+
|
344
|
+
console.log(`=== ERROR: ${moduleErrors.length > 1 ? `${moduleErrors.length} problems` : "Problem"} found in file: ${modulePath}:`)
|
345
|
+
moduleErrors.forEach(moduleError => {
|
346
|
+
errorsCount++;
|
347
|
+
console.log(`\t- ${moduleError}`)
|
348
|
+
})
|
349
|
+
})
|
350
|
+
|
351
|
+
if(errorsCount) {
|
352
|
+
throw new Error(`Found ${errorsCount} errors in the description of the public API.`);
|
353
|
+
}
|
354
|
+
}
|
355
|
+
|
356
|
+
const formatArrays = (typeText) => {
|
357
|
+
return typeText?.replaceAll(/(\S+)\[\]/g, "Array<$1>")
|
358
|
+
}
|
359
|
+
|
360
|
+
export {
|
361
|
+
getPrivacyStatus,
|
362
|
+
getSinceStatus,
|
363
|
+
getDeprecatedStatus,
|
364
|
+
getType,
|
365
|
+
getReference,
|
366
|
+
validateJSDocComment,
|
367
|
+
findDecorator,
|
368
|
+
findAllDecorators,
|
369
|
+
hasTag,
|
370
|
+
findTag,
|
371
|
+
findAllTags,
|
372
|
+
getTypeRefs,
|
373
|
+
normalizeDescription,
|
374
|
+
formatArrays,
|
375
|
+
isClass,
|
376
|
+
normalizeTagType,
|
377
|
+
displayDocumentationErrors,
|
378
|
+
logDocumentationError,
|
379
|
+
};
|
@@ -0,0 +1,65 @@
|
|
1
|
+
const fs = require('fs');
|
2
|
+
const Ajv = require('ajv');
|
3
|
+
const path = require('path');
|
4
|
+
const yargs = require('yargs/yargs')
|
5
|
+
const { hideBin } = require('yargs/helpers')
|
6
|
+
const argv = yargs(hideBin(process.argv))
|
7
|
+
.argv;
|
8
|
+
|
9
|
+
// Load your JSON schema
|
10
|
+
const extenalSchema = require('./schema.json');
|
11
|
+
const internalSchema = require('./schema-internal.json');
|
12
|
+
|
13
|
+
// Load your JSON data from the input file
|
14
|
+
const inputFilePath = path.join(process.cwd(), "dist/custom-elements.json"); // Update with your file path
|
15
|
+
const customManifest = fs.readFileSync(inputFilePath, 'utf8');
|
16
|
+
const inputDataInternal = JSON.parse(customManifest);
|
17
|
+
|
18
|
+
const clearProps = (data) => {
|
19
|
+
if (Array.isArray(data)) {
|
20
|
+
for (let i = 0; i < data.length; i++) {
|
21
|
+
if (typeof data[i] === "object") {
|
22
|
+
if (["enum", "interface"].includes(data[i].kind)) {
|
23
|
+
data.splice(i, 1);
|
24
|
+
i--;
|
25
|
+
} else {
|
26
|
+
clearProps(data[i]);
|
27
|
+
}
|
28
|
+
}
|
29
|
+
}
|
30
|
+
} else if (typeof data === "object") {
|
31
|
+
Object.keys(data).forEach(prop => {
|
32
|
+
if (prop.startsWith("_ui5")) {
|
33
|
+
delete data[prop];
|
34
|
+
} else if (typeof data[prop] === "object") {
|
35
|
+
clearProps(data[prop]);
|
36
|
+
}
|
37
|
+
});
|
38
|
+
}
|
39
|
+
|
40
|
+
return data;
|
41
|
+
}
|
42
|
+
|
43
|
+
const ajv = new Ajv({ allowUnionTypes: true, allError: true })
|
44
|
+
let validate = ajv.compile(internalSchema)
|
45
|
+
|
46
|
+
// Validate the JSON data against the schema
|
47
|
+
if (argv.dev) {
|
48
|
+
if (validate(inputDataInternal)) {
|
49
|
+
console.log('Internal custom element manifest is validated successfully');
|
50
|
+
} else {
|
51
|
+
throw new Error(`Validation of internal custom elements manifest failed: ${validate.errors}`);
|
52
|
+
}
|
53
|
+
}
|
54
|
+
|
55
|
+
const inputDataExternal = clearProps(JSON.parse(JSON.stringify(inputDataInternal)));
|
56
|
+
validate = ajv.compile(extenalSchema)
|
57
|
+
|
58
|
+
// Validate the JSON data against the schema
|
59
|
+
if (validate(inputDataExternal)) {
|
60
|
+
console.log('Custom element manifest is validated successfully');
|
61
|
+
fs.writeFileSync(inputFilePath, JSON.stringify(inputDataExternal, null, 2), 'utf8');
|
62
|
+
fs.writeFileSync(inputFilePath.replace("custom-elements", "custom-elements-internal"), JSON.stringify(inputDataInternal, null, 2), 'utf8');
|
63
|
+
} else if (argv.dev) {
|
64
|
+
throw new Error(`Validation of public custom elements manifest failed: ${validate.errors}`);
|
65
|
+
}
|
@@ -57,15 +57,25 @@ const generate = async () => {
|
|
57
57
|
const illustrationsPrefix = process.argv[4];
|
58
58
|
const illustrationSet = process.argv[5];
|
59
59
|
const destPath = process.argv[6];
|
60
|
+
const collection = process.argv[7];
|
60
61
|
const fileNamePattern = new RegExp(`${illustrationsPrefix}-.+-(.+).svg`);
|
61
|
-
// collect each illustration name because each one should have Sample.js file
|
62
|
+
// collect each illustration name because each one should have Sample.js file
|
62
63
|
const fileNames = new Set();
|
63
64
|
|
65
|
+
try {
|
66
|
+
await fs.access(srcPath);
|
67
|
+
} catch (error) {
|
68
|
+
console.log(`The path ${srcPath} does not exist.`);
|
69
|
+
return Promise.resolve(null);
|
70
|
+
}
|
71
|
+
|
72
|
+
console.log(`Generating illustrations from ${srcPath} to ${destPath}`)
|
73
|
+
|
64
74
|
const svgImportTemplate = svgContent => {
|
65
75
|
return `export default \`${svgContent}\`;`
|
66
76
|
};
|
67
77
|
const svgToJs = async fileName => {
|
68
|
-
const svg = await fs.readFile(path.join(srcPath, fileName), {encoding: "utf-8"});
|
78
|
+
const svg = await fs.readFile(path.join(srcPath, fileName), { encoding: "utf-8" });
|
69
79
|
const fileContent = svgImportTemplate(svg);
|
70
80
|
fileName = fileName.replace(/\.svg$/, ".js");
|
71
81
|
|
@@ -84,54 +94,47 @@ const generate = async () => {
|
|
84
94
|
|
85
95
|
const illustrationNameUpperCase = illustrationNameForTranslation.toUpperCase();
|
86
96
|
|
87
|
-
return
|
97
|
+
return `import { registerIllustration } from "@ui5/webcomponents-base/dist/asset-registries/Illustrations.js";
|
88
98
|
import dialogSvg from "./${illustrationsPrefix}-Dialog-${illustrationName}.js";
|
89
99
|
import sceneSvg from "./${illustrationsPrefix}-Scene-${illustrationName}.js";
|
90
|
-
import spotSvg from "./${illustrationsPrefix}-Spot-${illustrationName}.js"
|
91
|
-
import {
|
100
|
+
import spotSvg from "./${illustrationsPrefix}-Spot-${illustrationName}.js";${
|
101
|
+
defaultText ? `import {
|
92
102
|
IM_TITLE_${illustrationNameUpperCase},
|
93
103
|
IM_SUBTITLE_${illustrationNameUpperCase},
|
94
|
-
} from "../generated/i18n/i18n-defaults.js"
|
104
|
+
} from "../generated/i18n/i18n-defaults.js";` : ``}
|
95
105
|
|
96
106
|
const name = "${illustrationName}";
|
97
107
|
const set = "${illustrationSet}";
|
108
|
+
const collection = "${collection}";${defaultText ? `
|
98
109
|
const title = IM_TITLE_${illustrationNameUpperCase};
|
99
|
-
const subtitle = IM_SUBTITLE_${illustrationNameUpperCase}
|
110
|
+
const subtitle = IM_SUBTITLE_${illustrationNameUpperCase};` : ``}
|
100
111
|
|
101
112
|
registerIllustration(name, {
|
102
113
|
dialogSvg,
|
103
114
|
sceneSvg,
|
104
|
-
spotSvg
|
115
|
+
spotSvg,${defaultText ? `
|
105
116
|
title,
|
106
|
-
subtitle
|
117
|
+
subtitle,` : ``}
|
107
118
|
set,
|
119
|
+
collection,
|
108
120
|
});
|
109
121
|
|
122
|
+
export default "${illustrationSet === "fiori" ? "" : `${illustrationSet}/`}${illustrationName}";
|
110
123
|
export {
|
111
124
|
dialogSvg,
|
112
125
|
sceneSvg,
|
113
126
|
spotSvg,
|
114
|
-
};`
|
115
|
-
|
116
|
-
import dialogSvg from "./${illustrationsPrefix}-Dialog-${illustrationName}.js";
|
117
|
-
import sceneSvg from "./${illustrationsPrefix}-Scene-${illustrationName}.js";
|
118
|
-
import spotSvg from "./${illustrationsPrefix}-Spot-${illustrationName}.js";
|
119
|
-
|
120
|
-
const name = "${illustrationName}";
|
121
|
-
const set = "${illustrationSet}";
|
127
|
+
};`
|
128
|
+
};
|
122
129
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
});
|
130
|
+
const illustrationTypeDefinition = illustrationName => {
|
131
|
+
return `declare const dialogSvg: string;
|
132
|
+
declare const sceneSvg: string;
|
133
|
+
declare const spotSvg: string;
|
134
|
+
declare const _default: "${illustrationSet === "fiori" ? "" : `${illustrationSet}/`}${illustrationName}";
|
129
135
|
|
130
|
-
export
|
131
|
-
|
132
|
-
sceneSvg,
|
133
|
-
spotSvg,
|
134
|
-
};`
|
136
|
+
export default _default;
|
137
|
+
export { dialogSvg, sceneSvg, spotSvg };`
|
135
138
|
};
|
136
139
|
|
137
140
|
await fs.mkdir(destPath, { recursive: true });
|
@@ -151,6 +154,7 @@ export {
|
|
151
154
|
|
152
155
|
for (let illustrationName of fileNames) {
|
153
156
|
promises.push(fs.writeFile(path.join(destPath, `${illustrationName}.js`), illustrationImportTemplate(illustrationName)));
|
157
|
+
promises.push(fs.writeFile(path.join(destPath, `${illustrationName}.d.ts`), illustrationTypeDefinition(illustrationName)));
|
154
158
|
}
|
155
159
|
|
156
160
|
return Promise.all(promises);
|
@@ -83,7 +83,7 @@ const generateFiles = (componentName, tagName, library, packageName, isTypeScrip
|
|
83
83
|
// Change the color of the output
|
84
84
|
console.warn('\x1b[33m%s\x1b[0m', `
|
85
85
|
Make sure to import the component in your bundle by using:
|
86
|
-
import
|
86
|
+
import "./dist/${componentName}.js";`);
|
87
87
|
}
|
88
88
|
|
89
89
|
// Main function
|
@@ -25,10 +25,7 @@ import ${componentName}Css from "./generated/themes/${componentName}.css.js";
|
|
25
25
|
* <code>import ${packageName}/dist/${componentName}.js";</code>
|
26
26
|
*
|
27
27
|
* @constructor
|
28
|
-
* @
|
29
|
-
* @alias sap.ui.webc.${library}.${componentName}
|
30
|
-
* @extends sap.ui.webc.base.UI5Element
|
31
|
-
* @tagname ${tagName}
|
28
|
+
* @extends UI5Element
|
32
29
|
* @public
|
33
30
|
*/
|
34
31
|
@customElement({
|
@@ -43,7 +40,6 @@ import ${componentName}Css from "./generated/themes/${componentName}.css.js";
|
|
43
40
|
* Example custom event.
|
44
41
|
* Please keep in mind that all public events should be documented in the API Reference as shown below.
|
45
42
|
*
|
46
|
-
* @event sap.ui.webc.${library}.${componentName}#interact
|
47
43
|
* @public
|
48
44
|
*/
|
49
45
|
@event("interact", { detail: { /* event payload ( optional ) */ } })
|
@@ -51,9 +47,7 @@ class ${componentName} extends UI5Element {
|
|
51
47
|
/**
|
52
48
|
* Defines the value of the component.
|
53
49
|
*
|
54
|
-
* @
|
55
|
-
* @name sap.ui.webc.${library}.${componentName}.prototype.value
|
56
|
-
* @defaultvalue ""
|
50
|
+
* @default ""
|
57
51
|
* @public
|
58
52
|
*/
|
59
53
|
@property()
|
@@ -62,9 +56,6 @@ class ${componentName} extends UI5Element {
|
|
62
56
|
/**
|
63
57
|
* Defines the text of the component.
|
64
58
|
*
|
65
|
-
* @type {Node[]}
|
66
|
-
* @name sap.ui.webc.${library}.${componentName}.prototype.default
|
67
|
-
* @slot
|
68
59
|
* @public
|
69
60
|
*/
|
70
61
|
@slot({ type: Node, "default": true })
|
@@ -0,0 +1,77 @@
|
|
1
|
+
import { globby } from "globby";
|
2
|
+
import * as esbuild from 'esbuild'
|
3
|
+
import * as fs from "fs";
|
4
|
+
import * as path from "path";
|
5
|
+
import { writeFile, mkdir } from "fs/promises";
|
6
|
+
import chokidar from "chokidar";
|
7
|
+
import scopeVariables from "./scope-variables.mjs";
|
8
|
+
import { writeFileIfChanged, getFileContent } from "./shared.mjs";
|
9
|
+
|
10
|
+
const tsMode = process.env.UI5_TS === "true";
|
11
|
+
const extension = tsMode ? ".css.ts" : ".css.js";
|
12
|
+
|
13
|
+
const packageJSON = JSON.parse(fs.readFileSync("./package.json"))
|
14
|
+
const inputFilesGlob = "src/themes/*.css";
|
15
|
+
const restArgs = process.argv.slice(2);
|
16
|
+
|
17
|
+
let customPlugin = {
|
18
|
+
name: 'ui5-tools',
|
19
|
+
setup(build) {
|
20
|
+
build.initialOptions.write = false;
|
21
|
+
|
22
|
+
build.onEnd(result => {
|
23
|
+
result.outputFiles.forEach(async f => {
|
24
|
+
// scoping
|
25
|
+
const newText = scopeVariables(f.text, packageJSON);
|
26
|
+
await mkdir(path.dirname(f.path), {recursive: true});
|
27
|
+
writeFile(f.path, newText);
|
28
|
+
|
29
|
+
// JS/TS
|
30
|
+
const jsPath = f.path.replace(/dist[\/\\]css/, "src/generated/").replace(".css", extension);
|
31
|
+
const jsContent = getFileContent(tsMode, jsPath, packageJSON.name, "\`" + newText + "\`", true);
|
32
|
+
writeFileIfChanged(jsPath, jsContent);
|
33
|
+
});
|
34
|
+
})
|
35
|
+
},
|
36
|
+
}
|
37
|
+
|
38
|
+
const getConfig = async () => {
|
39
|
+
const config = {
|
40
|
+
entryPoints: await globby(inputFilesGlob),
|
41
|
+
bundle: true,
|
42
|
+
minify: true,
|
43
|
+
outdir: 'dist/css',
|
44
|
+
outbase: 'src',
|
45
|
+
plugins: [
|
46
|
+
customPlugin,
|
47
|
+
]
|
48
|
+
};
|
49
|
+
return config;
|
50
|
+
}
|
51
|
+
|
52
|
+
if (restArgs.includes("-w")) {
|
53
|
+
let ready;
|
54
|
+
let config = await getConfig();
|
55
|
+
let ctx = await esbuild.context(config);
|
56
|
+
await ctx.watch()
|
57
|
+
console.log('watching...')
|
58
|
+
|
59
|
+
// when new component css files are added, they do not trigger a build as no one directly imports them
|
60
|
+
// restart the watch mode with the new entry points if a css file is added.
|
61
|
+
const watcher = chokidar.watch(inputFilesGlob);
|
62
|
+
watcher.on("ready", () => {
|
63
|
+
ready = true; // Initial scan is over -> waiting for new files
|
64
|
+
});
|
65
|
+
watcher.on("add", async path => {
|
66
|
+
if (ready) {
|
67
|
+
// new file
|
68
|
+
ctx.dispose();
|
69
|
+
config = await getConfig();
|
70
|
+
ctx = await esbuild.context(config);
|
71
|
+
ctx.watch();
|
72
|
+
}
|
73
|
+
});
|
74
|
+
} else {
|
75
|
+
const config = await getConfig();
|
76
|
+
const result = await esbuild.build(config);
|
77
|
+
}
|