@ui5/webcomponents-tools 0.0.0-fca1107e7 → 0.0.0-fd426fe8a

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 (43) hide show
  1. package/CHANGELOG.md +1078 -1
  2. package/README.md +2 -5
  3. package/assets-meta.js +1 -8
  4. package/components-package/eslint.js +59 -31
  5. package/components-package/nps.js +50 -30
  6. package/components-package/vite.config.js +7 -11
  7. package/components-package/wdio.js +415 -405
  8. package/icons-collection/nps.js +2 -2
  9. package/lib/cem/custom-elements-manifest.config.mjs +74 -45
  10. package/lib/cem/event.mjs +69 -32
  11. package/lib/cem/schema-internal.json +65 -0
  12. package/lib/cem/types-internal.d.ts +14 -2
  13. package/lib/cem/utils.mjs +69 -30
  14. package/lib/cem/validate.js +37 -40
  15. package/lib/create-icons/index.js +13 -10
  16. package/lib/create-illustrations/index.js +19 -1
  17. package/lib/create-new-component/{tsFileContentTemplate.js → Component.js} +12 -9
  18. package/lib/create-new-component/ComponentTemplate.js +12 -0
  19. package/lib/create-new-component/index.js +14 -22
  20. package/lib/css-processors/css-processor-components.mjs +3 -2
  21. package/lib/css-processors/css-processor-themes.mjs +2 -7
  22. package/lib/css-processors/shared.mjs +4 -24
  23. package/lib/dev-server/{dev-server.js → dev-server.mjs} +4 -4
  24. package/lib/dev-server/virtual-index-html-plugin.js +24 -20
  25. package/lib/generate-json-imports/i18n.js +46 -62
  26. package/lib/generate-json-imports/themes.js +17 -36
  27. package/lib/hbs2ui5/RenderTemplates/LitRenderer.js +12 -7
  28. package/lib/hbs2ui5/index.js +3 -3
  29. package/lib/i18n/defaults.js +3 -2
  30. package/lib/remove-dev-mode/remove-dev-mode.mjs +37 -0
  31. package/lib/scoping/get-all-tags.js +9 -2
  32. package/lib/scoping/lint-src.js +8 -7
  33. package/package.json +9 -8
  34. package/tsconfig.json +18 -0
  35. package/components-package/wdio.sync.js +0 -368
  36. package/lib/create-new-component/jsFileContentTemplate.js +0 -73
  37. package/lib/css-processors/css-processor-component-styles.mjs +0 -47
  38. package/lib/generate-custom-elements-manifest/index.js +0 -271
  39. package/lib/jsdoc/config.json +0 -29
  40. package/lib/jsdoc/configTypescript.json +0 -29
  41. package/lib/jsdoc/plugin.js +0 -2468
  42. package/lib/jsdoc/preprocess.js +0 -146
  43. package/lib/jsdoc/template/publish.js +0 -4120
package/lib/cem/utils.mjs CHANGED
@@ -3,6 +3,8 @@ import path from "path";
3
3
 
4
4
  let documentationErrors = new Map();
5
5
 
6
+ const packageRegex = /^((@([a-z0-9._-]+)\/)?([a-z0-9._-]+))/;
7
+
6
8
  const getDeprecatedStatus = (jsdocComment) => {
7
9
  const deprecatedTag = findTag(jsdocComment, "deprecated");
8
10
  return deprecatedTag?.name
@@ -14,12 +16,23 @@ const getDeprecatedStatus = (jsdocComment) => {
14
16
  : undefined;
15
17
  };
16
18
 
19
+ const getExperimentalStatus = (jsdocComment) => {
20
+ const experimentalTag = findTag(jsdocComment, "experimental");
21
+ return experimentalTag?.name
22
+ ? experimentalTag.description
23
+ ? `${experimentalTag.name} ${experimentalTag.description}`
24
+ : experimentalTag.name
25
+ : experimentalTag
26
+ ? true
27
+ : undefined;
28
+ };
29
+
17
30
  const toKebabCase = str => {
18
31
  return str.replaceAll(/[A-Z]+(?![a-z])|[A-Z]/g, ($, ofs) => (ofs ? "-" : "") + $.toLowerCase())
19
32
  }
20
33
 
21
34
  const normalizeDescription = (description) => {
22
- return typeof description === 'string' ? description.replaceAll(/^-\s+|^(\n)+|(\n)+$/g, ""): description;
35
+ return typeof description === 'string' ? description.replaceAll(/^-\s+|^(\n)+|(\n)+$/g, "") : description;
23
36
  }
24
37
 
25
38
  const getTypeRefs = (ts, node, member) => {
@@ -100,10 +113,22 @@ const findPackageName = (ts, sourceFile, typeName) => {
100
113
  if (currentModuleSpecifier?.text?.startsWith(".")) {
101
114
  return packageJSON?.name;
102
115
  } else {
103
- return Object.keys(packageJSON?.dependencies || {}).find(
104
- (dependency) =>
105
- currentModuleSpecifier?.text?.startsWith(`${dependency}/`)
106
- );
116
+ // my-package/test
117
+ // my-package
118
+ // @scope/my-package
119
+ // my.package
120
+ // _mypackage
121
+ // mypackage-
122
+ // scope/my-package/test
123
+ // @scope/my-package/test
124
+ const match = currentModuleSpecifier?.text.match(packageRegex);
125
+ let packageName;
126
+
127
+ if (match) {
128
+ packageName = match[1];
129
+ }
130
+
131
+ return packageName || undefined;
107
132
  }
108
133
  }
109
134
  };
@@ -145,23 +170,24 @@ const findImportPath = (ts, sourceFile, typeName, modulePath) => {
145
170
  ?.replace("src", "dist")?.replace(".ts", ".js") || undefined
146
171
  );
147
172
  } else {
148
- const packageName = Object.keys(packageJSON?.dependencies || {}).find(
149
- (dependency) =>
150
- currentModuleSpecifier?.text?.startsWith(dependency)
151
- );
152
- return currentModuleSpecifier?.text
153
- ?.replace(`${packageName}/`, "") || undefined;
173
+ let packageName = currentModuleSpecifier?.text?.replace(packageRegex, "") || undefined;
174
+
175
+ if (packageName?.startsWith("/")) {
176
+ packageName = packageName.replace("/", "");
177
+ }
178
+
179
+ return packageName;
154
180
  }
155
181
  }
156
182
  };
157
183
 
158
184
 
159
185
  const isClass = text => {
160
- return text.includes("@abstract") || text.includes("@class") || text.includes("@constructor");
186
+ return text.includes("@abstract") || text.includes("@class") || text.includes("@constructor");
161
187
  };
162
188
 
163
189
  const normalizeTagType = (type) => {
164
- return type?.trim();
190
+ return type?.trim();
165
191
  }
166
192
 
167
193
  const packageJSON = JSON.parse(fs.readFileSync("./package.json"));
@@ -211,13 +237,13 @@ const commonTags = ["public", "protected", "private", "since", "deprecated"];
211
237
  const allowedTags = {
212
238
  field: [...commonTags, "formEvents", "formProperty", "default"],
213
239
  slot: [...commonTags, "default"],
214
- event: [...commonTags, "param", "allowPreventDefault", "native"],
240
+ event: [...commonTags, "param", "native", "allowPreventDefault"],
215
241
  eventParam: [...commonTags],
216
242
  method: [...commonTags, "param", "returns", "override"],
217
- class: [...commonTags, "constructor", "class", "abstract", "implements", "extends", "slot", "csspart"],
218
- enum: [...commonTags],
219
- enumMember: [...commonTags],
220
- interface: [...commonTags],
243
+ class: [...commonTags, "constructor", "class", "abstract", "experimental", "implements", "extends", "slot", "csspart"],
244
+ enum: [...commonTags, "experimental",],
245
+ enumMember: [...commonTags, "experimental",],
246
+ interface: [...commonTags, "experimental",],
221
247
  };
222
248
  allowedTags.getter = [...allowedTags.field, "override"]
223
249
 
@@ -230,19 +256,29 @@ const tagMatchCallback = (tag, tagName) => {
230
256
  };
231
257
 
232
258
  const findDecorator = (node, decoratorName) => {
233
- return node?.decorators?.find(
259
+ return (node?.modifiers || node?.decorators)?.find(
234
260
  (decorator) =>
235
261
  decorator?.expression?.expression?.text === decoratorName
236
262
  );
237
263
  };
238
264
 
239
265
  const findAllDecorators = (node, decoratorName) => {
240
- return (
241
- node?.decorators?.filter(
242
- (decorator) =>
243
- decorator?.expression?.expression?.text === decoratorName
244
- ) || []
245
- );
266
+ if (typeof decoratorName === "string") {
267
+ return (node?.modifiers || node?.decorators)?.filter(decorator => decorator?.expression?.expression?.text === decoratorName) || [];
268
+ }
269
+
270
+ if (Array.isArray(decoratorName)) {
271
+ return (node?.modifiers || node?.decorators)?.filter(decorator => {
272
+ if (decorator?.expression?.expression?.text) {
273
+ return decoratorName.includes(decorator.expression.expression.text);
274
+ }
275
+
276
+ return false;
277
+ }
278
+ ) || [];
279
+ }
280
+
281
+ return [];
246
282
  };
247
283
 
248
284
  const hasTag = (jsDoc, tagName) => {
@@ -272,7 +308,7 @@ const findAllTags = (jsDoc, tagName) => {
272
308
  };
273
309
 
274
310
  const validateJSDocTag = (tag) => {
275
- const booleanTags = ["private", "protected", "public", "abstract", "allowPreventDefault", "native", "formProperty", "constructor", "override"];
311
+ const booleanTags = ["private", "protected", "public", "abstract", "native", "allowPreventDefault", "formProperty", "constructor", "override"];
276
312
  let tagName = tag.tag;
277
313
 
278
314
  if (booleanTags.includes(tag.tag)) {
@@ -284,6 +320,8 @@ const validateJSDocTag = (tag) => {
284
320
  return !tag.name && !tag.type && !tag.description;
285
321
  case "deprecated":
286
322
  return !tag.type;
323
+ case "experimental":
324
+ return !tag.type;
287
325
  case "extends":
288
326
  return !tag.type && tag.name && !tag.description;
289
327
  case "implements":
@@ -316,7 +354,7 @@ const validateJSDocComment = (fieldType, jsdocComment, node, moduleDoc) => {
316
354
  let isValid = false
317
355
 
318
356
  if (fieldType === "event" && tag?.tag === "param") {
319
- isValid = allowedTags[fieldType]?.includes(tag.tag) && validateJSDocTag({...tag, tag: "eventparam"});
357
+ isValid = allowedTags[fieldType]?.includes(tag.tag) && validateJSDocTag({ ...tag, tag: "eventparam" });
320
358
  } else {
321
359
  isValid = allowedTags[fieldType]?.includes(tag.tag) && validateJSDocTag(tag);
322
360
  }
@@ -345,26 +383,27 @@ const displayDocumentationErrors = () => {
345
383
  [...documentationErrors.keys()].forEach(modulePath => {
346
384
  const moduleErrors = documentationErrors.get(modulePath);
347
385
 
348
- console.log(`=== ERROR: ${moduleErrors.length > 1 ? `${moduleErrors.length} problems` : "Problem"} found in file: ${modulePath}:`)
386
+ console.log(`=== ERROR: ${moduleErrors.length > 1 ? `${moduleErrors.length} problems` : "Problem"} found in file: ${modulePath}:`)
349
387
  moduleErrors.forEach(moduleError => {
350
388
  errorsCount++;
351
389
  console.log(`\t- ${moduleError}`)
352
390
  })
353
391
  })
354
392
 
355
- if(errorsCount) {
393
+ if (errorsCount) {
356
394
  throw new Error(`Found ${errorsCount} errors in the description of the public API.`);
357
395
  }
358
396
  }
359
397
 
360
398
  const formatArrays = (typeText) => {
361
- return typeText?.replaceAll(/(\S+)\[\]/g, "Array<$1>")
399
+ return typeText?.replaceAll(/(\S+)\[\]/g, "Array<$1>")
362
400
  }
363
401
 
364
402
  export {
365
403
  getPrivacyStatus,
366
404
  getSinceStatus,
367
405
  getDeprecatedStatus,
406
+ getExperimentalStatus,
368
407
  getType,
369
408
  getReference,
370
409
  validateJSDocComment,
@@ -1,11 +1,6 @@
1
1
  const fs = require('fs');
2
2
  const Ajv = require('ajv');
3
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
4
  // Load your JSON schema
10
5
  const extenalSchema = require('./schema.json');
11
6
  const internalSchema = require('./schema-internal.json');
@@ -14,47 +9,49 @@ const internalSchema = require('./schema-internal.json');
14
9
  const inputFilePath = path.join(process.cwd(), "dist/custom-elements.json"); // Update with your file path
15
10
  const customManifest = fs.readFileSync(inputFilePath, 'utf8');
16
11
  const inputDataInternal = JSON.parse(customManifest);
12
+ const devMode = process.env.UI5_CEM_MODE === "dev";
17
13
 
18
14
  inputDataInternal.modules.forEach(moduleDoc => {
19
- moduleDoc.exports = moduleDoc.exports.
20
- filter(e => moduleDoc.declarations.find(d => d.name === e.declaration.name && ["class", "function", "variable", "enum"].includes(d.kind)) || e.name === "default");
15
+ moduleDoc.exports = moduleDoc.exports.
16
+ filter(e => moduleDoc.declarations.find(d => d.name === e.declaration.name && ["class", "function", "variable", "enum"].includes(d.kind)) || e.name === "default");
21
17
  })
22
18
 
23
19
  const clearProps = (data) => {
24
- if (Array.isArray(data)) {
25
- for (let i = 0; i < data.length; i++) {
26
- if (typeof data[i] === "object") {
27
- if (["enum", "interface"].includes(data[i].kind)) {
28
- data.splice(i, 1);
29
- i--;
30
- } else {
31
- clearProps(data[i]);
32
- }
33
- }
34
- }
35
- } else if (typeof data === "object") {
36
- Object.keys(data).forEach(prop => {
37
- if (prop.startsWith("_ui5")) {
38
- delete data[prop];
39
- } else if (typeof data[prop] === "object") {
40
- clearProps(data[prop]);
41
- }
42
- });
43
- }
20
+ if (Array.isArray(data)) {
21
+ for (let i = 0; i < data.length; i++) {
22
+ if (typeof data[i] === "object") {
23
+ if (["enum", "interface"].includes(data[i].kind)) {
24
+ data.splice(i, 1);
25
+ i--;
26
+ } else {
27
+ clearProps(data[i]);
28
+ }
29
+ }
30
+ }
31
+ } else if (typeof data === "object") {
32
+ Object.keys(data).forEach(prop => {
33
+ if (prop.startsWith("_ui5")) {
34
+ delete data[prop];
35
+ } else if (typeof data[prop] === "object") {
36
+ clearProps(data[prop]);
37
+ }
38
+ });
39
+ }
44
40
 
45
- return data;
41
+ return data;
46
42
  }
47
43
 
48
44
  const ajv = new Ajv({ allowUnionTypes: true, allError: true })
49
45
  let validate = ajv.compile(internalSchema)
50
46
 
51
47
  // Validate the JSON data against the schema
52
- if (argv.dev) {
53
- if (validate(inputDataInternal)) {
54
- console.log('Internal custom element manifest is validated successfully');
55
- } else {
56
- throw new Error(`Validation of internal custom elements manifest failed: ${validate.errors}`);
57
- }
48
+ if (devMode) {
49
+ if (validate(inputDataInternal)) {
50
+ console.log('Internal custom element manifest is validated successfully');
51
+ } else {
52
+ console.log(validate.errors)
53
+ throw new Error(`Validation of internal custom elements manifest failed: ${validate.errors}`);
54
+ }
58
55
  }
59
56
 
60
57
  const inputDataExternal = clearProps(JSON.parse(JSON.stringify(inputDataInternal)));
@@ -62,9 +59,9 @@ validate = ajv.compile(extenalSchema)
62
59
 
63
60
  // Validate the JSON data against the schema
64
61
  if (validate(inputDataExternal)) {
65
- console.log('Custom element manifest is validated successfully');
66
- fs.writeFileSync(inputFilePath, JSON.stringify(inputDataExternal, null, 2), 'utf8');
67
- fs.writeFileSync(inputFilePath.replace("custom-elements", "custom-elements-internal"), JSON.stringify(inputDataInternal, null, 2), 'utf8');
68
- } else if (argv.dev) {
69
- throw new Error(`Validation of public custom elements manifest failed: ${validate.errors}`);
70
- }
62
+ console.log('Custom element manifest is validated successfully');
63
+ fs.writeFileSync(inputFilePath, JSON.stringify(inputDataExternal, null, 2), 'utf8');
64
+ fs.writeFileSync(inputFilePath.replace("custom-elements", "custom-elements-internal"), JSON.stringify(inputDataInternal, null, 2), 'utf8');
65
+ } else if (devMode) {
66
+ throw new Error(`Validation of public custom elements manifest failed: ${validate.errors}`);
67
+ }
@@ -21,8 +21,8 @@ export default "${collection}/${name}";
21
21
  export { pathData, ltr, accData };`;
22
22
 
23
23
 
24
- const iconAccTemplate = (name, pathData, ltr, accData, collection, packageName) => `import { registerIcon } from "@ui5/webcomponents-base/dist/asset-registries/Icons.js";
25
- import { ${accData.key} } from "../generated/i18n/i18n-defaults.js";
24
+ const iconAccTemplate = (name, pathData, ltr, accData, collection, packageName, versioned) => `import { registerIcon } from "@ui5/webcomponents-base/dist/asset-registries/Icons.js";
25
+ import { ${accData.key} } from "${versioned ? "../" : "./"}generated/i18n/i18n-defaults.js";
26
26
 
27
27
  const name = "${name}";
28
28
  const pathData = "${pathData}";
@@ -38,14 +38,16 @@ export { pathData, ltr, accData };`;
38
38
 
39
39
 
40
40
 
41
- const collectionTemplate = (name, versions, fullName) => `import { isLegacyThemeFamily } from "@ui5/webcomponents-base/dist/config/Theme.js";
41
+ const collectionTemplate = (name, versions, fullName) => `import { isLegacyThemeFamilyAsync } from "@ui5/webcomponents-base/dist/config/Theme.js";
42
42
  import { pathData as pathData${versions[0]}, ltr, accData } from "./${versions[0]}/${name}.js";
43
43
  import { pathData as pathData${versions[1]} } from "./${versions[1]}/${name}.js";
44
44
 
45
- const pathData = isLegacyThemeFamily() ? pathData${versions[0]} : pathData${versions[1]};
45
+ const getPathData = async() => {
46
+ return await isLegacyThemeFamilyAsync() ? pathDatav4 : pathDatav5;
47
+ };
46
48
 
47
49
  export default "${fullName}";
48
- export { pathData, ltr, accData };`;
50
+ export { getPathData, ltr, accData };`;
49
51
 
50
52
 
51
53
  const typeDefinitionTemplate = (name, accData, collection) => `declare const pathData: string;
@@ -56,13 +58,13 @@ declare const _default: "${collection}/${name}";
56
58
  export default _default;
57
59
  export { pathData, ltr, accData };`
58
60
 
59
- const collectionTypeDefinitionTemplate = (name, accData) => `declare const pathData: string;
61
+ const collectionTypeDefinitionTemplate = (name, accData) => `declare const getPathData: () => Promise<string>;
60
62
  declare const ltr: boolean;
61
63
  declare const accData: ${accData ? '{ key: string; defaultText: string; }' : null}
62
64
  declare const _default: "${name}";
63
65
 
64
66
  export default _default;
65
- export { pathData, ltr, accData };`
67
+ export { getPathData, ltr, accData };`
66
68
 
67
69
 
68
70
  const svgTemplate = (pathData) => `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
@@ -82,8 +84,9 @@ const createIcons = async (file) => {
82
84
  const acc = iconData.acc;
83
85
  const packageName = json.packageName;
84
86
  const collection = json.collection;
87
+ const versioned = json.version;
85
88
 
86
- const content = acc ? iconAccTemplate(name, pathData, ltr, acc, collection, packageName) : iconTemplate(name, pathData, ltr, collection, packageName);
89
+ const content = acc ? iconAccTemplate(name, pathData, ltr, acc, collection, packageName, versioned) : iconTemplate(name, pathData, ltr, collection, packageName);
87
90
 
88
91
  promises.push(fs.writeFile(path.join(destDir, `${name}.js`), content));
89
92
  promises.push(fs.writeFile(path.join(destDir, `${name}.svg`), svgTemplate(pathData)));
@@ -91,10 +94,10 @@ const createIcons = async (file) => {
91
94
 
92
95
  // For versioned icons collections, the script creates top level (unversioned) module that internally imports the versioned ones.
93
96
  // For example, the top level "@ui5/ui5-webcomponents-icons/dist/accept.js" imports:
94
- // - "@ui5/ui5-webcomponents-icons/dist/v5/accept.js"
97
+ // - "@ui5/ui5-webcomponents-icons/dist/v5/accept.js"
95
98
  // - "@ui5/ui5-webcomponents-icons/dist/v4/accept.js"
96
99
 
97
- if (json.version) {
100
+ if (versioned) {
98
101
  // The exported value from the top level (unversioned) icon module depends on whether the collection is the default,
99
102
  // to add or not the collection name to the exported value:
100
103
  // For the default collection (SAPIcons) we export just the icon name - "export default { 'accept' }"
@@ -20,7 +20,15 @@ const generate = async () => {
20
20
  SuccessScreen: "SuccessScreen",
21
21
  NoMail: "NoMail",
22
22
  NoSavedItems: "NoSavedItems",
23
- NoTasks: "NoTasks"
23
+ NoTasks: "NoTasks",
24
+ NoDimensionsSet: "NoDimensionsSet",
25
+ AddPeople: "AddPeople",
26
+ AddColumn: "AddColumn",
27
+ SortColumn: "SortColumn",
28
+ FilterTable: "FilterTable",
29
+ ResizeColumn: "ResizeColumn",
30
+ GroupTable: "GroupTable",
31
+ UploadCollection: "UploadCollection"
24
32
  };
25
33
 
26
34
  const FALLBACK_TEXTS = {
@@ -47,6 +55,16 @@ const generate = async () => {
47
55
  SimpleNotFoundMagnifier: ORIGINAL_TEXTS.NoSearchResults,
48
56
  SimpleReload: ORIGINAL_TEXTS.UnableToLoad,
49
57
  SimpleTask: ORIGINAL_TEXTS.NoTasks,
58
+ NoChartData: ORIGINAL_TEXTS.NoDimensionsSet,
59
+ AddingColumns: ORIGINAL_TEXTS.AddColumn,
60
+ SortingColumns: ORIGINAL_TEXTS.SortColumn,
61
+ FilteringColumns: ORIGINAL_TEXTS.FilterTable,
62
+ ResizingColumns: ORIGINAL_TEXTS.ResizeColumn,
63
+ GroupingColumns: ORIGINAL_TEXTS.GroupTable,
64
+ AddPeopleToCalendar: ORIGINAL_TEXTS.AddPeople,
65
+ DragFilesToUpload: ORIGINAL_TEXTS.UploadCollection,
66
+ KeyTask: ORIGINAL_TEXTS.SuccessScreen,
67
+ ReceiveAppreciation: ORIGINAL_TEXTS.BalloonSky,
50
68
  SuccessBalloon: ORIGINAL_TEXTS.BalloonSky,
51
69
  SuccessCheckMark: ORIGINAL_TEXTS.SuccessScreen,
52
70
  SuccessHighFive: ORIGINAL_TEXTS.BalloonSky
@@ -1,12 +1,12 @@
1
- const tsFileContentTemplate = (componentName, tagName, library, packageName) => {
1
+ const Component = (componentName, tagName, library, packageName) => {
2
2
  return `import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
3
3
  import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js";
4
4
  import property from "@ui5/webcomponents-base/dist/decorators/property.js";
5
5
  import slot from "@ui5/webcomponents-base/dist/decorators/slot.js";
6
- import event from "@ui5/webcomponents-base/dist/decorators/event.js";
7
- import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
6
+ import event from "@ui5/webcomponents-base/dist/decorators/event-strict.js";
7
+ import jsxRenderer from "@ui5/webcomponents-base/dist/renderer/JsxRenderer.js";
8
8
 
9
- import ${componentName}Template from "./generated/templates/${componentName}Template.lit.js";
9
+ import ${componentName}Template from "./${componentName}Template.js";
10
10
 
11
11
  // Styles
12
12
  import ${componentName}Css from "./generated/themes/${componentName}.css.js";
@@ -30,10 +30,9 @@ import ${componentName}Css from "./generated/themes/${componentName}.css.js";
30
30
  */
31
31
  @customElement({
32
32
  tag: "${tagName}",
33
- renderer: litRender,
33
+ renderer: jsxRenderer,
34
34
  styles: ${componentName}Css,
35
35
  template: ${componentName}Template,
36
- dependencies: [],
37
36
  })
38
37
 
39
38
  /**
@@ -42,8 +41,12 @@ import ${componentName}Css from "./generated/themes/${componentName}.css.js";
42
41
  *
43
42
  * @public
44
43
  */
45
- @event("interact", { detail: { /* event payload ( optional ) */ } })
44
+ @event("interact")
46
45
  class ${componentName} extends UI5Element {
46
+ eventDetails!: {
47
+ "interact": void,
48
+ };
49
+
47
50
  /**
48
51
  * Defines the value of the component.
49
52
  *
@@ -51,7 +54,7 @@ class ${componentName} extends UI5Element {
51
54
  * @public
52
55
  */
53
56
  @property()
54
- value!: string;
57
+ value?: string;
55
58
 
56
59
  /**
57
60
  * Defines the text of the component.
@@ -68,4 +71,4 @@ export default ${componentName};
68
71
  `;
69
72
  };
70
73
 
71
- module.exports = tsFileContentTemplate;
74
+ module.exports = Component;
@@ -0,0 +1,12 @@
1
+ const ComponentTemplate = (componentName) => {
2
+ return `import type ${componentName} from "./${componentName}.js";
3
+
4
+ export default function ${componentName}Template(this: ${componentName}) {
5
+ return (
6
+ <div>Hello World!</div>
7
+ );
8
+ }
9
+ `;
10
+ };
11
+
12
+ module.exports = ComponentTemplate;
@@ -1,18 +1,17 @@
1
1
  const fs = require("fs");
2
- const path = require("path");
3
2
  const prompts = require("prompts");
4
- const jsFileContentTemplate = require("./jsFileContentTemplate.js");
5
- const tsFileContentTemplate = require("./tsFileContentTemplate.js");
3
+ const Component = require("./Component.js");
4
+ const ComponentTemplate= require("./ComponentTemplate.js");
6
5
 
7
6
  /**
8
- * Hyphanates the given PascalCase string, f.e.:
9
- * Foo -> "my-foo" (adds preffix)
10
- * FooBar -> "foo-bar"
7
+ * Hyphanates the given PascalCase string and adds prefix, f.e.:
8
+ * Foo -> "my-foo"
9
+ * FooBar -> "my-foo-bar"
11
10
  */
12
11
  const hyphaneteComponentName = (componentName) => {
13
12
  const result = componentName.replace(/([a-z])([A-Z])/g, '$1-$2' ).toLowerCase();
14
13
 
15
- return result.includes("-") ? result : `my-${result}`;
14
+ return `my-${result}`;
16
15
  };
17
16
 
18
17
  /**
@@ -58,23 +57,17 @@ const getLibraryName = packageName => {
58
57
  return packageName.substr("webcomponents-".length);
59
58
  };
60
59
 
61
- const generateFiles = (componentName, tagName, library, packageName, isTypeScript) => {
60
+ const generateFiles = (componentName, tagName, library, packageName) => {
62
61
  componentName = capitalizeFirstLetter(componentName);
63
62
  const filePaths = {
64
- "main": isTypeScript
65
- ? `./src/${componentName}.ts`
66
- : `./src/${componentName}.js`,
63
+ "main": `./src/${componentName}.ts`,
67
64
  "css": `./src/themes/${componentName}.css`,
68
- "template": `./src/${componentName}.hbs`,
65
+ "template": `./src/${componentName}Template.tsx`,
69
66
  };
70
67
 
71
- const FileContentTemplate = isTypeScript
72
- ? tsFileContentTemplate(componentName, tagName, library, packageName)
73
- : jsFileContentTemplate(componentName, tagName, library, packageName);
74
-
75
- fs.writeFileSync(filePaths.main, FileContentTemplate, { flag: "wx+" });
68
+ fs.writeFileSync(filePaths.main, Component(componentName, tagName, library, packageName), { flag: "wx+" });
76
69
  fs.writeFileSync(filePaths.css, "", { flag: "wx+" });
77
- fs.writeFileSync(filePaths.template, "<div>Hello World</div>", { flag: "wx+" });
70
+ fs.writeFileSync(filePaths.template, ComponentTemplate(componentName), { flag: "wx+" });
78
71
 
79
72
  console.log(`Successfully generated ${filePaths.main}`);
80
73
  console.log(`Successfully generated ${filePaths.css}`);
@@ -82,8 +75,8 @@ const generateFiles = (componentName, tagName, library, packageName, isTypeScrip
82
75
 
83
76
  // Change the color of the output
84
77
  console.warn('\x1b[33m%s\x1b[0m', `
85
- Make sure to import the component in your bundle by using:
86
- import "./dist/${componentName}.js";`);
78
+ Now, import the component in "src/bundle.esm.ts" via: import "./${componentName}.js";
79
+ And, add it to your HTML: <${tagName}></${tagName}>.`);
87
80
  }
88
81
 
89
82
  // Main function
@@ -112,10 +105,9 @@ const createWebComponent = async () => {
112
105
  }
113
106
  }
114
107
 
115
- const isTypeScript = fs.existsSync(path.join(process.cwd(), "tsconfig.json"));
116
108
  const tagName = hyphaneteComponentName(componentName);
117
109
 
118
- generateFiles(componentName, tagName, library, packageName, isTypeScript);
110
+ generateFiles(componentName, tagName, library, packageName);
119
111
  };
120
112
 
121
113
  createWebComponent();
@@ -22,13 +22,14 @@ let customPlugin = {
22
22
  build.onEnd(result => {
23
23
  result.outputFiles.forEach(async f => {
24
24
  // scoping
25
- const newText = scopeVariables(f.text, packageJSON);
25
+ let newText = scopeVariables(f.text, packageJSON);
26
+ newText = newText.replaceAll(/\\/g, "\\\\"); // Escape backslashes as they might appear in css rules
26
27
  await mkdir(path.dirname(f.path), {recursive: true});
27
28
  writeFile(f.path, newText);
28
29
 
29
30
  // JS/TS
30
31
  const jsPath = f.path.replace(/dist[\/\\]css/, "src/generated/").replace(".css", extension);
31
- const jsContent = getFileContent(tsMode, jsPath, packageJSON.name, "\`" + newText + "\`", true);
32
+ const jsContent = getFileContent(packageJSON.name, "\`" + newText + "\`", true);
32
33
  writeFileIfChanged(jsPath, jsContent);
33
34
  });
34
35
  })
@@ -42,16 +42,11 @@ let scopingPlugin = {
42
42
  // JSON
43
43
  const jsonPath = f.path.replace(/dist[\/\\]css/, "dist/generated/assets").replace(".css", ".css.json");
44
44
  await mkdir(path.dirname(jsonPath), {recursive: true});
45
- const data = {
46
- packageName: packageJSON.name,
47
- fileName: jsonPath.substr(jsonPath.lastIndexOf("themes")),
48
- content: newText,
49
- };
50
- writeFileIfChanged(jsonPath, JSON.stringify({_: data}));
45
+ writeFileIfChanged(jsonPath, JSON.stringify(newText));
51
46
 
52
47
  // JS/TS
53
48
  const jsPath = f.path.replace(/dist[\/\\]css/, "src/generated/").replace(".css", extension);
54
- const jsContent = getFileContent(tsMode, jsPath, packageJSON.name, "\`" + newText + "\`");
49
+ const jsContent = getFileContent(packageJSON.name, "\`" + newText + "\`");
55
50
  writeFileIfChanged(jsPath, jsContent);
56
51
  });
57
52
  })
@@ -42,35 +42,15 @@ const getDefaultThemeCode = packageName => {
42
42
  import defaultThemeBase from "@ui5/webcomponents-theming/dist/generated/themes/${DEFAULT_THEME}/parameters-bundle.css.js";
43
43
  import defaultTheme from "./${DEFAULT_THEME}/parameters-bundle.css.js";
44
44
 
45
- registerThemePropertiesLoader("@ui5/webcomponents-theming", "${DEFAULT_THEME}", async () => defaultThemeBase);
46
- registerThemePropertiesLoader("${packageName}", "${DEFAULT_THEME}", async () => defaultTheme);
45
+ registerThemePropertiesLoader("@" + "ui5" + "/" + "webcomponents-theming", "${DEFAULT_THEME}", async () => defaultThemeBase);
46
+ registerThemePropertiesLoader(${ packageName.split("").map(c => `"${c}"`).join (" + ") }, "${DEFAULT_THEME}", async () => defaultTheme);
47
47
  `;
48
48
  };
49
49
 
50
- const getFileContent = (tsMode, targetFile, packageName, css, includeDefaultTheme) => {
51
- if (tsMode) {
52
- return getTSContent(targetFile, packageName, css, includeDefaultTheme);
53
- }
54
-
55
- return getJSContent(targetFile, packageName, css, includeDefaultTheme);
56
- }
57
-
58
- const getTSContent = (targetFile, packageName, css, includeDefaultTheme) => {
59
- const typeImport = "import type { StyleData } from \"@ui5/webcomponents-base/dist/types.js\";"
50
+ const getFileContent = (packageName, css, includeDefaultTheme) => {
60
51
  const defaultTheme = includeDefaultTheme ? getDefaultThemeCode(packageName) : "";
61
-
62
- // tabs are intentionally mixed to have proper identation in the produced file
63
- return `${typeImport}
64
- ${defaultTheme}
65
- const styleData: StyleData = {packageName:"${packageName}",fileName:"${targetFile.substr(targetFile.lastIndexOf("themes"))}",content:${css}};
66
- export default styleData;
67
- `;
52
+ return `${defaultTheme}export default ${css.trim()}`
68
53
  }
69
54
 
70
- const getJSContent = (targetFile, packageName, css, includeDefaultTheme) => {
71
- const defaultTheme = includeDefaultTheme ? getDefaultThemeCode(packageName) : "";
72
-
73
- return `${defaultTheme}export default {packageName:"${packageName}",fileName:"${targetFile.substr(targetFile.lastIndexOf("themes"))}",content:${css}}`
74
- }
75
55
 
76
56
  export { writeFileIfChanged, stripThemingBaseContent, getFileContent}
@@ -1,7 +1,7 @@
1
- const fs = require("fs/promises");
2
- const { createServer } = require('vite');
3
- const yargs = require('yargs/yargs')
4
- const { hideBin } = require('yargs/helpers')
1
+ import fs from "fs/promises";
2
+ import { createServer } from 'vite';
3
+ import yargs from 'yargs';
4
+ import { hideBin } from 'yargs/helpers';
5
5
 
6
6
  const argv = yargs(hideBin(process.argv))
7
7
  .alias("c", "config")