@ui5/webcomponents-tools 0.0.0-453158269 → 0.0.0-47cc17a26

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 (135) hide show
  1. package/CHANGELOG.md +2086 -0
  2. package/LICENSE.txt +201 -0
  3. package/README.md +7 -10
  4. package/assets-meta.js +12 -11
  5. package/bin/dev.js +3 -6
  6. package/bin/ui5nps.js +265 -0
  7. package/components-package/eslint.js +66 -2
  8. package/components-package/nps.js +148 -69
  9. package/components-package/postcss.components.js +1 -21
  10. package/components-package/postcss.themes.js +1 -26
  11. package/components-package/vite.config.js +9 -0
  12. package/components-package/wdio.js +69 -17
  13. package/icons-collection/nps.js +32 -18
  14. package/lib/amd-to-es6/index.js +107 -0
  15. package/lib/amd-to-es6/no-remaining-require.js +33 -0
  16. package/lib/cem/cem.js +12 -0
  17. package/lib/cem/custom-elements-manifest.config.mjs +530 -0
  18. package/lib/cem/event.mjs +168 -0
  19. package/lib/cem/patch/@custom-elements-manifest/analyzer/cli.js +128 -0
  20. package/lib/cem/patch/@custom-elements-manifest/analyzer/package.json +59 -0
  21. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/browser-entrypoint.js +23 -0
  22. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/create.js +117 -0
  23. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/arrow-function.js +26 -0
  24. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/class-jsdoc.js +157 -0
  25. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/classes.js +20 -0
  26. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createArrowFunction.js +17 -0
  27. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createAttribute.js +24 -0
  28. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createClass.js +301 -0
  29. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createClassField.js +26 -0
  30. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createFunctionLike.js +73 -0
  31. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createMixin.js +33 -0
  32. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createVariable.js +22 -0
  33. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/handlers.js +338 -0
  34. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/custom-elements-define-calls.js +90 -0
  35. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/exports.js +156 -0
  36. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/function-like.js +24 -0
  37. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/mixins.js +29 -0
  38. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/reexported-wrapped-mixin-exports.js +84 -0
  39. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/variables.js +34 -0
  40. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/collect-phase/collect-imports.js +101 -0
  41. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/catalyst/catalyst.js +11 -0
  42. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/catalyst/controller.js +34 -0
  43. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/catalyst-major-2/catalyst.js +11 -0
  44. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/catalyst-major-2/controller.js +34 -0
  45. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/decorators/attr.js +53 -0
  46. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/decorators/custom-element-decorator.js +36 -0
  47. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/fast/fast.js +7 -0
  48. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/lit.js +13 -0
  49. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/member-denylist.js +21 -0
  50. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/method-denylist.js +20 -0
  51. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/property-decorator.js +94 -0
  52. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/static-properties.js +121 -0
  53. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/utils.js +66 -0
  54. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/stencil/stencil.js +129 -0
  55. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/index.js +80 -0
  56. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/link-phase/cleanup-classes.js +25 -0
  57. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/link-phase/field-denylist.js +22 -0
  58. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/link-phase/method-denylist.js +25 -0
  59. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/post-processing/apply-inheritance.js +78 -0
  60. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/post-processing/is-custom-element.js +34 -0
  61. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/post-processing/link-class-to-tagname.js +27 -0
  62. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/post-processing/remove-unexported-declarations.js +23 -0
  63. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/post-processing/resolve-initializers.js +52 -0
  64. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/ast-helpers.js +186 -0
  65. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/cli-helpers.js +164 -0
  66. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/exports.js +44 -0
  67. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/find-external-manifests.js +67 -0
  68. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/imports.js +25 -0
  69. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/index.js +71 -0
  70. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/jsdoc.js +19 -0
  71. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/manifest-helpers.js +194 -0
  72. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/mixins.js +112 -0
  73. package/lib/cem/schema-internal.json +1422 -0
  74. package/lib/cem/schema.json +1098 -0
  75. package/lib/cem/types-internal.d.ts +808 -0
  76. package/lib/cem/types.d.ts +736 -0
  77. package/lib/cem/utils.mjs +423 -0
  78. package/lib/cem/validate.js +76 -0
  79. package/lib/copy-and-watch/index.js +105 -97
  80. package/lib/copy-list/index.js +16 -10
  81. package/lib/create-icons/index.js +74 -25
  82. package/lib/create-illustrations/index.js +88 -45
  83. package/lib/create-new-component/Component.js +74 -0
  84. package/lib/create-new-component/ComponentTemplate.js +12 -0
  85. package/lib/create-new-component/index.js +62 -101
  86. package/lib/css-processors/css-processor-components.mjs +92 -0
  87. package/lib/css-processors/css-processor-themes.mjs +102 -0
  88. package/lib/css-processors/scope-variables.mjs +49 -0
  89. package/lib/css-processors/shared.mjs +46 -0
  90. package/lib/dev-server/custom-hot-update-plugin.js +39 -0
  91. package/lib/dev-server/dev-server.mjs +78 -0
  92. package/lib/dev-server/virtual-index-html-plugin.js +56 -0
  93. package/lib/generate-js-imports/illustrations.js +85 -0
  94. package/lib/generate-json-imports/i18n.js +62 -69
  95. package/lib/generate-json-imports/themes.js +34 -43
  96. package/lib/hbs2lit/src/compiler.js +16 -5
  97. package/lib/hbs2lit/src/litVisitor2.js +85 -22
  98. package/lib/hbs2lit/src/svgProcessor.js +12 -5
  99. package/lib/hbs2ui5/RenderTemplates/LitRenderer.js +39 -6
  100. package/lib/hbs2ui5/index.js +23 -6
  101. package/lib/i18n/defaults.js +30 -8
  102. package/lib/i18n/toJSON.js +15 -11
  103. package/lib/icons-hash/icons-hash.mjs +149 -0
  104. package/lib/postcss-combine-duplicated-selectors/index.js +12 -5
  105. package/lib/remove-dev-mode/remove-dev-mode.mjs +51 -0
  106. package/lib/rimraf/rimraf.js +31 -0
  107. package/lib/scoping/get-all-tags.js +11 -11
  108. package/lib/scoping/lint-src.js +8 -7
  109. package/lib/scoping/scope-test-pages.js +2 -1
  110. package/lib/test-runner/test-runner.js +71 -0
  111. package/package.json +45 -33
  112. package/tsconfig.json +18 -0
  113. package/components-package/rollup-plugins/empty-module.js +0 -15
  114. package/components-package/rollup.js +0 -150
  115. package/components-package/wdio.sync.js +0 -360
  116. package/lib/documentation/index.js +0 -168
  117. package/lib/documentation/templates/api-component-since.js +0 -3
  118. package/lib/documentation/templates/api-css-variables-section.js +0 -24
  119. package/lib/documentation/templates/api-events-section.js +0 -35
  120. package/lib/documentation/templates/api-methods-section.js +0 -26
  121. package/lib/documentation/templates/api-properties-section.js +0 -42
  122. package/lib/documentation/templates/api-slots-section.js +0 -28
  123. package/lib/documentation/templates/template.js +0 -39
  124. package/lib/esm-abs-to-rel/index.js +0 -58
  125. package/lib/jsdoc/config.json +0 -29
  126. package/lib/jsdoc/plugin.js +0 -2436
  127. package/lib/jsdoc/template/publish.js +0 -4112
  128. package/lib/postcss-css-to-esm/index.js +0 -45
  129. package/lib/postcss-css-to-json/index.js +0 -36
  130. package/lib/postcss-new-files/index.js +0 -36
  131. package/lib/postcss-p/postcss-p.mjs +0 -11
  132. package/lib/replace-global-core/index.js +0 -25
  133. package/lib/serve/index.js +0 -46
  134. package/lib/serve/serve.json +0 -3
  135. package/package-lock.json +0 -48
@@ -0,0 +1,56 @@
1
+ const virtualIndexPlugin = () => {
2
+ return {
3
+ name: 'virtual-index-html',
4
+ async config() {
5
+ const path = (await import("path")).default;
6
+ const globby = (await import("globby")).globby;
7
+ const files = await globby(["test/pages/**/*.html", "packages/*/test/pages/**/*.html"]);
8
+
9
+ const rollupInput = {};
10
+
11
+ files.forEach(file => {
12
+ rollupInput[file] = path.resolve(process.cwd(), file);
13
+ });
14
+
15
+ return {
16
+ build: {
17
+ rollupOptions: {
18
+ input: rollupInput
19
+ }
20
+ }
21
+ }
22
+ },
23
+ async configureServer(server) {
24
+ const path = (await import("path")).default;
25
+ const globby = (await import("globby")).globby;
26
+ const files = await globby(["test/pages/**/*.html", "packages/*/test/pages/**/*.html"]);
27
+
28
+ const pagesPerFolder = {};
29
+ files.forEach(file => {
30
+ let folder = pagesPerFolder[path.dirname(file)] = pagesPerFolder[path.dirname(file)] || [];
31
+ folder.push(path.basename(file));
32
+ });
33
+
34
+ server.middlewares.use((req, res, next) => {
35
+ if (req.url === "/") {
36
+ const folders = Object.keys(pagesPerFolder);
37
+
38
+ res.statusCode = 200;
39
+ res.setHeader("Content-Type", "text/html; charset=utf-8");
40
+ res.end(`${folders.map(folder => {
41
+ const pages = pagesPerFolder[folder];
42
+ return `<h1>${folder}</h1>
43
+ ${pages.map(page => {
44
+ return `<li><a href='${folder}/${page}'>${page}</a></li>`
45
+ }).join("")}
46
+ `
47
+ }).join("")}`);
48
+ } else {
49
+ next();
50
+ }
51
+ })
52
+ },
53
+ }
54
+ };
55
+
56
+ module.exports = virtualIndexPlugin;
@@ -0,0 +1,85 @@
1
+ const fs = require("fs").promises;
2
+ const path = require("path");
3
+
4
+ const generateDynamicImportLines = async (fileNames, location, exclusionPatterns = []) => {
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");
14
+ };
15
+
16
+ const generateDynamicImportsFileContent = (dynamicImports, availableIllustrations, collection, set, prefix = "") => {
17
+ return `// @ts-nocheck
18
+ import { registerIllustrationLoader } from "@ui5/webcomponents-base/dist/asset-registries/Illustrations.js";
19
+
20
+ export const loadIllustration = async (illustrationName) => {
21
+ const collectionAndPrefix = "${set}/${collection}/${prefix}";
22
+ const cleanIllustrationName = illustrationName.startsWith(collectionAndPrefix) ? illustrationName.replace(collectionAndPrefix, "") : illustrationName;
23
+ switch (cleanIllustrationName) {
24
+ ${dynamicImports}
25
+ default:
26
+ throw new Error("[Illustrations] Illustration not found: " + illustrationName);
27
+ }
28
+ };
29
+
30
+ const loadAndCheck = async (illustrationName) => {
31
+ const data = await loadIllustration(illustrationName);
32
+ return data;
33
+ };
34
+
35
+ ${availableIllustrations}.forEach((illustrationName) =>
36
+ registerIllustrationLoader(\`${set}/${collection}/${prefix}\${illustrationName}\`, loadAndCheck)
37
+ );
38
+ `;
39
+ };
40
+
41
+ const getMatchingFiles = async (folder, pattern) => {
42
+ const dir = await fs.readdir(folder);
43
+ return dir.filter((fileName) => fileName.match(pattern));
44
+ };
45
+
46
+ const generateIllustrations = async (argv) => {
47
+ const config = {
48
+ inputFolder: argv[2],
49
+ outputFile: argv[3],
50
+ set: argv[4],
51
+ collection: argv[5],
52
+ location: argv[6],
53
+ filterOut: argv[7].slice().split(","),
54
+ };
55
+
56
+
57
+ const { inputFolder, outputFile, collection, location, prefix, filterOut, set } = config;
58
+
59
+ const normalizedInputFolder = path.normalize(inputFolder);
60
+ const normalizedOutputFile = path.normalize(outputFile);
61
+
62
+ const svgFiles = await getMatchingFiles(normalizedInputFolder, /\.svg$/);
63
+
64
+ const illustrations = [
65
+ ...new Set(
66
+ svgFiles
67
+ .filter(name => !name.includes("sapIllus-Patterns"))
68
+ .map(name => name.split("-").pop().replace(".svg", ""))
69
+ ),
70
+ ];
71
+
72
+ const dynamicImports = await generateDynamicImportLines(illustrations, location, filterOut);
73
+ const contentDynamic = generateDynamicImportsFileContent(dynamicImports, JSON.stringify(illustrations), collection, set, prefix);
74
+
75
+ await fs.mkdir(path.dirname(normalizedOutputFile), { recursive: true });
76
+ await fs.writeFile(normalizedOutputFile, contentDynamic);
77
+
78
+ console.log("Generated illustration imports.");
79
+ };
80
+
81
+ if (require.main === module) {
82
+ generateIllustrations(process.argv)
83
+ }
84
+
85
+ exports._ui5mainFn = generateIllustrations;
@@ -1,98 +1,91 @@
1
1
  const fs = require("fs").promises;
2
2
  const path = require('path');
3
3
 
4
- const generate = async () => {
4
+ const isTypeScript = process.env.UI5_TS;
5
+ const ext = isTypeScript ? 'ts' : 'js';
5
6
 
6
- const packageName = JSON.parse(await fs.readFile("package.json")).name;
7
-
8
- const inputFolder = path.normalize(process.argv[2]);
9
- const outputFile = path.normalize(`${process.argv[3]}/i18n-static.js`);
10
- const outputFileDynamic = path.normalize(`${process.argv[3]}/i18n.js`);
11
7
 
12
- // All languages present in the file system
13
- const files = await fs.readdir(inputFolder);
14
- const languages = files.map(file => {
15
- const matches = file.match(/messagebundle_(.+?).json$/);
16
- return matches ? matches[1] : undefined;
17
- }).filter(key => !!key);
8
+ const getContent = function(caseLines, languagesKeysStringArray, packageName) {
9
+ return `// @ts-nocheck
10
+ import { registerI18nLoader } from "@ui5/webcomponents-base/dist/asset-registries/i18n.js";
18
11
 
19
- let contentStatic, contentDynamic;
20
-
21
- // No i18n - just import dependencies, if any
22
- if (languages.length === 0) {
23
- contentStatic = "";
24
- contentDynamic = "";
25
- // There is i18n - generate the full file
26
- } else {
27
- // Keys for the array
28
- const languagesKeysString = languages.map(key => `"${key}": _${key},`).join("\n\t");
29
- const languagesKeysStringArray = languages.map(key => `"${key}",`).join("\n\t");
30
-
31
- // Actual imports for json assets
32
- const assetsImportsString = languages.map(key => `import _${key} from "../assets/i18n/messagebundle_${key}.json";`).join("\n");
33
-
34
- // static imports
35
- contentStatic = `import { registerI18nLoader } from "@ui5/webcomponents-base/dist/asset-registries/i18n.js";
36
-
37
- ${assetsImportsString}
38
-
39
- const bundleMap = {
40
- ${languagesKeysString}
41
- };
12
+ const importMessageBundle = async (localeId) => {
13
+ switch (localeId) {
14
+ ${caseLines}
15
+ default: throw "unknown locale"
16
+ }
17
+ }
42
18
 
43
- const fetchMessageBundle = async (localeId) => {
44
- if (typeof bundleMap[localeId] === "object") {
45
- // inlined from build
46
- throw new Error("[i18n] Inlined JSON not supported with static imports of assets. Use dynamic imports of assets or configure JSON imports as URLs")
19
+ const importAndCheck = async (localeId) => {
20
+ const data = await importMessageBundle(localeId);
21
+ if (typeof data === "string" && data.endsWith(".json")) {
22
+ throw new Error(\`[i18n] Invalid bundling detected - dynamic JSON imports bundled as URLs. Switch to inlining JSON files from the build. Check the \"Assets\" documentation for more information.\`);
47
23
  }
48
- return (await fetch(bundleMap[localeId])).json()
24
+ return data;
49
25
  }
50
26
 
51
27
  const localeIds = [${languagesKeysStringArray}];
52
28
 
53
29
  localeIds.forEach(localeId => {
54
- registerI18nLoader("${packageName}", localeId, fetchMessageBundle);
30
+ registerI18nLoader(${ packageName.split("").map(c => `"${c}"`).join (" + ") }, localeId, importAndCheck);
55
31
  });
56
32
  `;
33
+ }
57
34
 
58
- // Actual imports for json assets
59
- const dynamicImportsString = languages.map(key => ` case "${key}": return (await import("../assets/i18n/messagebundle_${key}.json")).default;`).join("\n");
35
+ const generate = async (argv) => {
60
36
 
61
- // Resulting file content
62
- contentDynamic = `import { registerI18nLoader } from "@ui5/webcomponents-base/dist/asset-registries/i18n.js";
37
+ const packageName = JSON.parse(await fs.readFile("package.json")).name;
63
38
 
64
- const importMessageBundle = async (localeId) => {
65
- switch (localeId) {
66
- ${dynamicImportsString}
67
- default: throw "unknown locale"
68
- }
69
- }
39
+ const inputFolder = path.normalize(argv[2]);
40
+ const outputFileDynamic = path.normalize(`${argv[3]}/i18n.${ext}`);
41
+ const outputFileFetchMetaResolve = path.normalize(`${argv[3]}/i18n-fetch.${ext}`);
42
+ const outputFileDynamicImportJSONImport = path.normalize(`${argv[3]}/i18n-node.${ext}`);
70
43
 
71
- const importAndCheck = async (localeId) => {
72
- const data = await importMessageBundle(localeId);
73
- if (typeof data === "string" && data.endsWith(".json")) {
74
- throw new Error(\`[i18n] Invalid bundling detected - dynamic JSON imports bundled as URLs. Switch to inlining JSON files from the build or use 'import ".../Assets-static.js"'. Check the \"Assets\" documentation for more information.\`);
75
- }
76
- return data;
77
- }
44
+ // All languages present in the file system
45
+ const files = await fs.readdir(inputFolder);
46
+ const languages = files.map(file => {
47
+ const matches = file.match(/messagebundle_(.+?).properties$/);
48
+ return matches ? matches[1] : undefined;
49
+ }).filter(key => !!key);
78
50
 
79
- const localeIds = [${languagesKeysStringArray}];
51
+ let contentDynamic;
52
+ let contentFetchMetaResolve;
53
+ let contentDynamicImportJSONAttr;
80
54
 
81
- localeIds.forEach(localeId => {
82
- registerI18nLoader("${packageName}", localeId, importAndCheck);
83
- });
84
- `;
55
+ // No i18n - just import dependencies, if any
56
+ if (languages.length === 0) {
57
+ contentDynamic = "";
58
+ contentFetchMetaResolve = "";
59
+ contentDynamicImportJSONAttr = "";
60
+ // There is i18n - generate the full file
61
+ } else {
62
+ // Keys for the array
63
+ const languagesKeysStringArray = languages.map(key => `"${key}",`).join("\n\t");
64
+
65
+ // Actual imports for json assets
66
+ const dynamicImportsString = languages.map(key => ` case "${key}": return (await import(/* webpackChunkName: "${packageName.replace("@", "").replace("/", "-")}-messagebundle-${key}" */ "../assets/i18n/messagebundle_${key}.json")).default;`).join("\n");
67
+ const fetchMetaResolveString = languages.map(key => ` case "${key}": return (await fetch(new URL("../assets/i18n/messagebundle_${key}.json", import.meta.url))).json();`).join("\n");
68
+ const dynamicImportJSONAttrString = languages.map(key => ` case "${key}": return (await import(/* webpackChunkName: "${packageName.replace("@", "").replace("/", "-")}-messagebundle-${key}" */ "../assets/i18n/messagebundle_${key}.json", {with: { type: 'json'}})).default;`).join("\n");
85
69
 
70
+ // Resulting file content
86
71
 
72
+ contentDynamic = getContent(dynamicImportsString, languagesKeysStringArray, packageName);
73
+ contentFetchMetaResolve = getContent(fetchMetaResolveString, languagesKeysStringArray, packageName);
74
+ contentDynamicImportJSONAttr = getContent(dynamicImportJSONAttrString, languagesKeysStringArray, packageName);
87
75
  }
88
76
 
89
- await fs.mkdir(path.dirname(outputFile), { recursive: true });
77
+ await fs.mkdir(path.dirname(outputFileDynamic), { recursive: true });
90
78
  return Promise.all([
91
- fs.writeFile(outputFile, contentStatic),
92
79
  fs.writeFile(outputFileDynamic, contentDynamic),
93
- ]);
80
+ fs.writeFile(outputFileFetchMetaResolve, contentFetchMetaResolve),
81
+ fs.writeFile(outputFileDynamicImportJSONImport, contentDynamicImportJSONAttr),
82
+ ]).then(() => {
83
+ console.log("Generated i18n JSON imports.");
84
+ });
94
85
  }
95
86
 
96
- generate().then(() => {
97
- console.log("Generated i18n JSON imports.");
98
- });
87
+ if (require.main === module) {
88
+ generate(process.argv)
89
+ }
90
+
91
+ exports._ui5mainFn = generate;
@@ -2,15 +2,19 @@ const fs = require("fs").promises;
2
2
  const path = require('path');
3
3
  const assets = require("../../assets-meta.js");
4
4
 
5
- const generate = async () => {
6
- const inputFolder = path.normalize(process.argv[2]);
7
- const outputFile = path.normalize(`${process.argv[3]}/Themes-static.js`);
8
- const outputFileDynamic = path.normalize(`${process.argv[3]}/Themes.js`);
5
+ const isTypeScript = process.env.UI5_TS;
6
+ const ext = isTypeScript ? 'ts' : 'js';
9
7
 
10
- // All supported optional themes
8
+ const generate = async (argv) => {
9
+ const inputFolder = path.normalize(argv[2]);
10
+ const outputFileDynamic = path.normalize(`${argv[3]}/Themes.${ext}`);
11
+ const outputFileDynamicImportJSONAttr = path.normalize(`${argv[3]}/Themes-node.${ext}`);
12
+ const outputFileFetchMetaResolve = path.normalize(`${argv[3]}/Themes-fetch.${ext}`);
13
+
14
+ // All supported optional themes
11
15
  const allThemes = assets.themes.all;
12
16
 
13
- // All themes present in the file system
17
+ // All themes present in the file system
14
18
  const dirs = await fs.readdir(inputFolder);
15
19
  const themesOnFileSystem = dirs.map(dir => {
16
20
  const matches = dir.match(/sap_.*$/);
@@ -19,39 +23,19 @@ const generate = async () => {
19
23
 
20
24
  const packageName = JSON.parse(await fs.readFile("package.json")).name;
21
25
 
22
- const importLines = themesOnFileSystem.map(theme => `import ${theme} from "../assets/themes/${theme}/parameters-bundle.css.json";`).join("\n");
23
- const themeUrlsByName = "{\n" + themesOnFileSystem.join(",\n") + "\n}";
24
26
  const availableThemesArray = `[${themesOnFileSystem.map(theme => `"${theme}"`).join(", ")}]`;
25
- const dynamicImportLines = themesOnFileSystem.map(theme => `\t\tcase "${theme}": return (await import("../assets/themes/${theme}/parameters-bundle.css.json")).default;`).join("\n");
26
-
27
-
28
- // static imports file content
29
- const contentStatic = `import { registerThemePropertiesLoader } from "@ui5/webcomponents-base/dist/asset-registries/Themes.js";
30
-
31
- ${importLines}
27
+ const dynamicImportLines = themesOnFileSystem.map(theme => `\t\tcase "${theme}": return (await import(/* webpackChunkName: "${packageName.replace("@", "").replace("/", "-")}-${theme.replace("_", "-")}-parameters-bundle" */"../assets/themes/${theme}/parameters-bundle.css.json")).default;`).join("\n");
28
+ const dynamicImportJSONAttrLines = themesOnFileSystem.map(theme => `\t\tcase "${theme}": return (await import(/* webpackChunkName: "${packageName.replace("@", "").replace("/", "-")}-${theme.replace("_", "-")}-parameters-bundle" */"../assets/themes/${theme}/parameters-bundle.css.json", {with: { type: 'json'}})).default;`).join("\n");
29
+ const fetchMetaResolveLines = themesOnFileSystem.map(theme => `\t\tcase "${theme}": return (await fetch(new URL("../assets/themes/${theme}/parameters-bundle.css.json", import.meta.url))).json();`).join("\n");
32
30
 
33
- const themeUrlsByName = ${themeUrlsByName};
34
- const isInlined = obj => typeof (obj) === "object";
35
-
36
- const loadThemeProperties = async (themeName) => {
37
- if (typeof themeUrlsByName[themeName] === "object") {
38
- // inlined from build
39
- throw new Error("[themes] Inlined JSON not supported with static imports of assets. Use dynamic imports of assets or configure JSON imports as URLs");
40
- }
41
- return (await fetch(themeUrlsByName[themeName])).json();
42
- };
43
-
44
- ${availableThemesArray}
45
- .forEach(themeName => registerThemePropertiesLoader("${packageName}", themeName, loadThemeProperties));
46
- `;
47
-
48
-
49
- // dynamic imports file content
50
- const contentDynamic = `import { registerThemePropertiesLoader } from "@ui5/webcomponents-base/dist/asset-registries/Themes.js";
31
+ // dynamic imports file content
32
+ const contentDynamic = function (lines) {
33
+ return `// @ts-nocheck
34
+ import { registerThemePropertiesLoader } from "@ui5/webcomponents-base/dist/asset-registries/Themes.js";
51
35
 
52
36
  const loadThemeProperties = async (themeName) => {
53
37
  switch (themeName) {
54
- ${dynamicImportLines}
38
+ ${lines}
55
39
  default: throw "unknown theme"
56
40
  }
57
41
  };
@@ -59,22 +43,29 @@ ${dynamicImportLines}
59
43
  const loadAndCheck = async (themeName) => {
60
44
  const data = await loadThemeProperties(themeName);
61
45
  if (typeof data === "string" && data.endsWith(".json")) {
62
- throw new Error(\`[themes] Invalid bundling detected - dynamic JSON imports bundled as URLs. Switch to inlining JSON files from the build or use 'import ".../Assets-static.js"'. Check the \"Assets\" documentation for more information.\`);
46
+ throw new Error(\`[themes] Invalid bundling detected - dynamic JSON imports bundled as URLs. Switch to inlining JSON files from the build. Check the \"Assets\" documentation for more information.\`);
63
47
  }
64
48
  return data;
65
49
  };
66
50
 
67
51
  ${availableThemesArray}
68
- .forEach(themeName => registerThemePropertiesLoader("${packageName}", themeName, loadAndCheck));
52
+ .forEach(themeName => registerThemePropertiesLoader(${packageName.split("").map(c => `"${c}"`).join(" + ")}, themeName, loadAndCheck));
69
53
  `;
54
+ }
70
55
 
71
- await fs.mkdir(path.dirname(outputFile), { recursive: true });
56
+ await fs.mkdir(path.dirname(outputFileDynamic), { recursive: true });
72
57
  return Promise.all([
73
- fs.writeFile(outputFile, contentStatic),
74
- fs.writeFile(outputFileDynamic, contentDynamic)
75
- ]);
58
+ fs.writeFile(outputFileDynamic, contentDynamic(dynamicImportLines)),
59
+ fs.writeFile(outputFileDynamicImportJSONAttr, contentDynamic(dynamicImportJSONAttrLines)),
60
+ fs.writeFile(outputFileFetchMetaResolve, contentDynamic(fetchMetaResolveLines)),
61
+ ]).
62
+ then(() => {
63
+ console.log("Generated themes JSON imports.");
64
+ })
76
65
  };
77
66
 
78
- generate().then(() => {
79
- console.log("Generated themes JSON imports.");
80
- });
67
+ if (require.main === module) {
68
+ generate(process.argv)
69
+ }
70
+
71
+ exports._ui5mainFn = generate;
@@ -12,15 +12,25 @@ const removeWhiteSpaces = (source) => {
12
12
  .replace(/}}\s+{{/g, "}}{{"); // Remove whitespace between }} and {{
13
13
  };
14
14
 
15
- const hbs2lit = async (file) => {
15
+ const hbs2lit = async (file, componentName) => {
16
16
  let sPreprocessed = await includesReplacer.replace(file);
17
17
 
18
18
  sPreprocessed = removeWhiteSpaces(sPreprocessed);
19
19
 
20
+ const blockSignature = process.env.UI5_TS ? `this: ${componentName}` : ""
21
+
22
+ // icons hack
23
+ if (sPreprocessed.startsWith("<g ") || sPreprocessed.startsWith("<g>")) {
24
+ return `
25
+ function block0 (${blockSignature}) {
26
+ return svg\`${sPreprocessed}\`
27
+ }`;
28
+ }
29
+
20
30
  const ast = Handlebars.parse(sPreprocessed);
21
31
 
22
32
  const pv = new PartialsVisitor();
23
- const lv = new HTMLLitVisitor();
33
+ const lv = new HTMLLitVisitor(componentName);
24
34
 
25
35
  let result = "";
26
36
 
@@ -33,10 +43,11 @@ const hbs2lit = async (file) => {
33
43
  let block = lv.blocks[key];
34
44
 
35
45
  if (block.match(/scopeTag/)) {
36
- const matches = block.match(/^(.*?)( => )(.*?);$/);
37
- const scopedCode = matches[3];
46
+ // const matches = block.match(/^(.*?)( => )(.*?);$/);
47
+ const matches = block.match(/^(function .*? \{ return )(.*?);\}$/);
48
+ const scopedCode = matches[2];
38
49
  const normalCode = scopedCode.replace(/\${scopeTag\("/g, "").replace(/", tags, suffix\)}/g, "");
39
- block = `${matches[1]}${matches[2]}suffix ? ${scopedCode} : ${normalCode};`;
50
+ block = `${matches[1]}suffix ? ${scopedCode} : ${normalCode};}`;
40
51
  }
41
52
 
42
53
  result += block + "\n";
@@ -28,14 +28,18 @@ if (!String.prototype.replaceAll) {
28
28
  };
29
29
  }
30
30
 
31
- function HTMLLitVisitor(debug) {
31
+ function HTMLLitVisitor(componentName, debug) {
32
32
  this.blockCounter = 0;
33
33
  this.keys = [];
34
34
  this.blocks = {};
35
35
  this.result = "";
36
36
  this.mainBlock = "";
37
- this.blockPath = "context";
38
- this.blockParameters = ["context", "tags", "suffix"];
37
+ this.blockLevel = 0;
38
+ this.componentName = componentName
39
+ const blockParametersDefinitionTS = [`this: ${componentName}`, "context: UI5Element", "tags: string[]", "suffix: string | undefined"];
40
+ const blockParametersDefinitionJS = ["context", "tags", "suffix"];
41
+ this.blockParametersDefinition = process.env.UI5_TS ? blockParametersDefinitionTS : blockParametersDefinitionJS;
42
+ this.blockParametersUsage = ["this", "context", "tags", "suffix"];
39
43
  this.paths = []; //contains all normalized relative paths
40
44
  this.debug = debug;
41
45
  if (this.debug) {
@@ -51,18 +55,18 @@ HTMLLitVisitor.prototype.Program = function(program) {
51
55
  this.keys.push(key);
52
56
  this.debug && this.blockByNumber.push(key);
53
57
 
54
- this.blocks[this.currentKey()] = "const " + this.currentKey() + " = (" + this.blockParameters.join(", ") + ") => ";
58
+ // this.blocks[this.currentKey()] = "function " + this.currentKey() + ` (this: any, ` + this.blockParametersDefinition.join(", ") + ") { ";
59
+ this.blocks[this.currentKey()] = `function ${this.currentKey()} (${this.blockParametersDefinition.join(", ")}) { `;
55
60
 
56
61
  if (this.keys.length > 1) { //it's a nested block
57
- this.blocks[this.prevKey()] += this.currentKey() + "(" + this.blockParameters.join(", ") + ")";
62
+ this.blocks[this.prevKey()] += this.currentKey() + ".call(" + this.blockParametersUsage.join(", ") + ")";
58
63
  } else {
59
64
  this.mainBlock = this.currentKey();
60
- this.paths.push(this.blockPath);
61
65
  }
62
66
 
63
- this.blocks[this.currentKey()] += "html`";
67
+ this.blocks[this.currentKey()] += "return html`";
64
68
  Visitor.prototype.Program.call(this, program);
65
- this.blocks[this.currentKey()] += "`;";
69
+ this.blocks[this.currentKey()] += "`;}";
66
70
 
67
71
  this.keys.pop(key);
68
72
  };
@@ -99,14 +103,18 @@ HTMLLitVisitor.prototype.MustacheStatement = function(mustache) {
99
103
  this.blocks[this.currentKey()] += "${index}";
100
104
  } else {
101
105
  const path = normalizePath.call(this, mustache.path.original);
102
- const hasCalculatingClasses = path.includes("context.classes");
106
+ const hasCalculatingClasses = path.includes("this.classes");
103
107
 
104
108
  let parsedCode = "";
105
109
 
106
110
  if (isNodeValue && !mustache.escaped) {
107
111
  parsedCode = `\${unsafeHTML(${path})}`;
108
112
  } else if (hasCalculatingClasses) {
109
- parsedCode = `\${classMap(${path})}`;
113
+ if (process.env.UI5_TS) {
114
+ parsedCode = `\${classMap(${path} as ClassMapValue)}`;
115
+ } else {
116
+ parsedCode = `\${classMap(${path})}`;
117
+ }
110
118
  } else if (isStyleAttribute) {
111
119
  parsedCode = `\${styleMap(${path})}`;
112
120
  } else if (skipIfDefined){
@@ -171,22 +179,37 @@ function visitEachBlock(block) {
171
179
  var bParamAdded = false;
172
180
  visitSubExpression.call(this, block);
173
181
 
174
- this.blocks[this.currentKey()] += "${ repeat(" + normalizePath.call(this, block.params[0].original) + ", (item, index) => item._id || index, (item, index) => ";
182
+ const reapeatDirectiveParamsTS = "(item, index) => (item as typeof item & {_id?: any})._id || index, (item, index: number)";
183
+ const reapeatDirectiveParamsJS = "(item, index) => item._id || index, (item, index)";
184
+ const repleatDirectiveParams = process.env.UI5_TS ? reapeatDirectiveParamsTS : reapeatDirectiveParamsJS;
185
+ this.blocks[this.currentKey()] += "${ repeat(" + normalizePath.call(this, block.params[0].original) + ", " + repleatDirectiveParams + " => ";
175
186
  this.paths.push(normalizePath.call(this, block.params[0].original));
176
- this.blockPath = "item";
187
+ this.blockLevel++;
177
188
 
178
- if (this.blockParameters.indexOf("item") === -1) {
189
+ // block params is [this, context, tags, suffix] for top level blocks
190
+ // blcok params is [this, context, tags, suffix, item, index] for nested blocks
191
+ if (!this.blockParametersUsage.includes("index")) {
192
+ // last item is not index, but an each block is processed, add the paramters for further nested blocks
179
193
  bParamAdded = true;
180
- this.blockParameters.unshift("index");
181
- this.blockParameters.unshift("item");
194
+ if (process.env.UI5_TS) {
195
+ this.blockParametersDefinition.push("item: any");
196
+ this.blockParametersDefinition.push("index: number");
197
+ } else {
198
+ this.blockParametersDefinition.push("item");
199
+ this.blockParametersDefinition.push("index");
200
+ }
201
+ this.blockParametersUsage.push("item");
202
+ this.blockParametersUsage.push("index");
182
203
  }
183
204
  this.acceptKey(block, "program");
184
205
  if (bParamAdded) {
185
- this.blockParameters.shift("item");
186
- this.blockParameters.shift("index");
206
+ // if parameters were added at this step, remove the last two
207
+ this.blockParametersDefinition.pop();
208
+ this.blockParametersDefinition.pop();
209
+ this.blockParametersUsage.pop();
210
+ this.blockParametersUsage.pop();
187
211
  }
188
- this.blockPath = "context";
189
-
212
+ this.blockLevel--;
190
213
  this.blocks[this.currentKey()] += ") }";
191
214
  }
192
215
 
@@ -195,12 +218,52 @@ function normalizePath(sPath) {
195
218
 
196
219
  //read carefully - https://github.com/wycats/handlebars.js/issues/1028
197
220
  //kpdecker commented on May 20, 2015
198
- if (result.indexOf("../") === 0) {
199
- let absolutePath = replaceAll(this.paths[this.paths.length - 1], ".", "/") + "/" + result;
221
+
222
+ if (result.indexOf("@root") === 0) {
223
+ // Trying to access root context via the HBS "@root" variable.
224
+ // Example: {{@root.property}} compiles to "context.property" - called from anywhere within the template.
225
+ result = result.replace("@root", "this");
226
+
227
+ } else if (result.indexOf("../") === 0) {
228
+ let absolutePath;
229
+ const levelsUp = (result.match(/..\//g) || []).length;
230
+
231
+ if (this.blockLevel <= levelsUp) {
232
+ // Trying to access root context from nested loops.
233
+ // Example: {{../../property}} compiles to "context.property" - when currently in a nested level loop.
234
+ // Example: {{../../../property}} compile to "context.property" - when requested levels are not present. fallback to root context.
235
+ absolutePath = `this.${replaceAll(result,"../", "")}`;
236
+ } else {
237
+ // Trying to access upper context (one-level-up) and based on the current lelev, that could be "context" or "item".
238
+ // Example: {{../property}} compiles to "context.property" - when called in a top level loop.
239
+ // Example: {{../property}} compiles to "item.property" - when called in a nested level loop.
240
+ // TODO: the second example, although correctly generated to "item.property", "item" will point to the current object within the nested loop,
241
+ // not the upper level loop as intended. So accessing the upper loop from nested loop is currently not working.
242
+ absolutePath = replaceAll(this.paths[this.paths.length - 1 - levelsUp], ".", "/") + "/" + result;
243
+ }
244
+
200
245
  result = replaceAll(path.normalize(absolutePath), path.sep, ".");
246
+
201
247
  } else {
202
- result = result ? replaceAll(this.blockPath + "/" + result, "/", ".") : this.blockPath;
248
+ // When neither "@root", nor "../" are used, use the following contexts:
249
+ // - use "context" - for the top level of execution, e.g "this.blockLevel = 0".
250
+ // - use "item" - for any nested level, e.g "this.blockLevel > 0".
251
+ // Example:
252
+ //
253
+ // {{text}} -> compiles to "context.text"
254
+ // {{#each items}}
255
+ // Item text: {{text}}</div> -> compiles to "item.text"
256
+ // {{#each words}}
257
+ // Word text: {{text}}</div> -> compiles to "item.text"
258
+ // {{/each}}
259
+ // Item text: {{text}}</div> -> compiles to "item.text"
260
+ // {{/each}}
261
+ // {{text}} -> compiles to "context.text"
262
+
263
+ const blockPath = this.blockLevel > 0 ? "item" : "this";
264
+ result = result ? replaceAll(blockPath + "/" + result, "/", ".") : blockPath;
203
265
  }
266
+
204
267
  return result;
205
268
  }
206
269