@ui5/webcomponents-tools 0.0.0-b132dd7b9 → 0.0.0-b3a4f8020

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 (96) hide show
  1. package/CHANGELOG.md +501 -0
  2. package/LICENSE.txt +201 -0
  3. package/README.md +7 -7
  4. package/bin/dev.js +10 -4
  5. package/bin/ui5nps.js +301 -0
  6. package/components-package/nps.js +97 -94
  7. package/components-package/wdio.js +8 -2
  8. package/icons-collection/nps.js +30 -21
  9. package/lib/amd-to-es6/index.js +17 -10
  10. package/lib/cem/cem.js +16 -0
  11. package/lib/cem/custom-elements-manifest.config.mjs +56 -4
  12. package/lib/cem/merge.mjs +220 -0
  13. package/lib/cem/patch/@custom-elements-manifest/analyzer/cli.js +128 -0
  14. package/lib/cem/patch/@custom-elements-manifest/analyzer/package.json +59 -0
  15. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/browser-entrypoint.js +23 -0
  16. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/create.js +117 -0
  17. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/arrow-function.js +26 -0
  18. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/class-jsdoc.js +157 -0
  19. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/classes.js +20 -0
  20. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createArrowFunction.js +17 -0
  21. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createAttribute.js +24 -0
  22. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createClass.js +301 -0
  23. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createClassField.js +26 -0
  24. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createFunctionLike.js +73 -0
  25. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createMixin.js +33 -0
  26. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createVariable.js +22 -0
  27. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/handlers.js +338 -0
  28. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/custom-elements-define-calls.js +90 -0
  29. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/exports.js +156 -0
  30. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/function-like.js +24 -0
  31. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/mixins.js +29 -0
  32. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/reexported-wrapped-mixin-exports.js +84 -0
  33. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/variables.js +34 -0
  34. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/collect-phase/collect-imports.js +101 -0
  35. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/catalyst/catalyst.js +11 -0
  36. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/catalyst/controller.js +34 -0
  37. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/catalyst-major-2/catalyst.js +11 -0
  38. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/catalyst-major-2/controller.js +34 -0
  39. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/decorators/attr.js +53 -0
  40. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/decorators/custom-element-decorator.js +36 -0
  41. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/fast/fast.js +7 -0
  42. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/lit.js +13 -0
  43. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/member-denylist.js +21 -0
  44. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/method-denylist.js +20 -0
  45. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/property-decorator.js +94 -0
  46. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/static-properties.js +121 -0
  47. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/utils.js +66 -0
  48. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/stencil/stencil.js +129 -0
  49. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/index.js +80 -0
  50. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/link-phase/cleanup-classes.js +25 -0
  51. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/link-phase/field-denylist.js +22 -0
  52. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/link-phase/method-denylist.js +25 -0
  53. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/post-processing/apply-inheritance.js +78 -0
  54. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/post-processing/is-custom-element.js +34 -0
  55. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/post-processing/link-class-to-tagname.js +27 -0
  56. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/post-processing/remove-unexported-declarations.js +23 -0
  57. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/post-processing/resolve-initializers.js +52 -0
  58. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/ast-helpers.js +186 -0
  59. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/cli-helpers.js +164 -0
  60. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/exports.js +44 -0
  61. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/find-external-manifests.js +67 -0
  62. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/imports.js +25 -0
  63. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/index.js +71 -0
  64. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/jsdoc.js +19 -0
  65. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/manifest-helpers.js +194 -0
  66. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/mixins.js +112 -0
  67. package/lib/cem/schema-internal.json +41 -1
  68. package/lib/cem/schema.json +41 -1
  69. package/lib/cem/types-internal.d.ts +32 -2
  70. package/lib/cem/types.d.ts +32 -2
  71. package/lib/cem/utils.mjs +13 -3
  72. package/lib/cem/validate.js +61 -47
  73. package/lib/chokidar/chokidar.js +28 -0
  74. package/lib/copy-and-watch/index.js +110 -97
  75. package/lib/copy-list/index.js +18 -10
  76. package/lib/create-icons/index.js +19 -15
  77. package/lib/create-illustrations/index.js +57 -29
  78. package/lib/create-new-component/index.js +5 -3
  79. package/lib/css-processors/css-processor-components.mjs +85 -60
  80. package/lib/css-processors/css-processor-themes.mjs +105 -57
  81. package/lib/css-processors/postcss-plugin.mjs +153 -0
  82. package/lib/css-processors/scope-variables.mjs +26 -1
  83. package/lib/css-processors/shared.mjs +8 -17
  84. package/lib/dev-server/dev-server.mjs +23 -11
  85. package/lib/eslint/eslint.js +44 -0
  86. package/lib/generate-js-imports/illustrations.js +55 -54
  87. package/lib/generate-json-imports/i18n.js +22 -11
  88. package/lib/generate-json-imports/themes.js +24 -12
  89. package/lib/i18n/defaults.js +14 -7
  90. package/lib/i18n/toJSON.js +40 -12
  91. package/lib/icons-hash/icons-hash.mjs +149 -0
  92. package/lib/remove-dev-mode/remove-dev-mode.mjs +38 -24
  93. package/lib/rimraf/rimraf.js +31 -0
  94. package/lib/test-runner/test-runner.js +56 -48
  95. package/lib/vite-bundler/vite-bundler.mjs +35 -0
  96. package/package.json +15 -14
@@ -3,49 +3,47 @@ const fs = require("fs");
3
3
  const LIB = path.join(__dirname, `../lib/`);
4
4
  let websiteBaseUrl = "/";
5
5
 
6
- if (process.env.DEPLOY) {
7
- websiteBaseUrl = "/ui5-webcomponents/";
8
- } else if (process.env.DEPLOY_NIGHTLY) {
9
- websiteBaseUrl = "/ui5-webcomponents/nightly/";
10
- }
11
-
12
- const cypressEnvVariables = (options, predefinedVars) => {
13
- let variables = [];
14
- const { cypress_code_coverage, cypress_acc_tests } = options.internal ?? {};
15
-
16
- // Handle environment variables like TEST_SUITE
17
- if (predefinedVars) {
18
- variables = [...predefinedVars];
19
- }
20
-
21
- // The coverage task is always registered and requires an explicit variable whether to generate a report or not
22
- variables.push(`CYPRESS_COVERAGE=${!!cypress_code_coverage}`);
23
-
24
- if (cypress_acc_tests) {
25
- variables.push("CYPRESS_UI5_ACC=true");
6
+ const isPreview = !!process.env.PR_NUMBER;
7
+ const getPreviewBaseUrl = () => {
8
+ if (process.env.DEPLOYMENT_TYPE === "netlify_preview") {
9
+ return "/";
26
10
  }
11
+ return `/webcomponents/pr-${process.env.PR_NUMBER}/`;
12
+ }
27
13
 
28
- return variables.length ? `cross-env ${variables.join(" ")}` : "";
14
+ if (process.env.DEPLOY) {
15
+ websiteBaseUrl = "/webcomponents/";
16
+ } else if (process.env.DEPLOY_NIGHTLY) {
17
+ websiteBaseUrl = "/webcomponents/nightly/";
18
+ } else if (isPreview) {
19
+ websiteBaseUrl = getPreviewBaseUrl();
29
20
  }
30
21
 
31
22
  const getScripts = (options) => {
32
-
33
23
  // The script creates all JS modules (dist/illustrations/{illustrationName}.js) out of the existing SVGs
34
24
  const illustrationsData = options.illustrationsData || [];
35
- const illustrations = illustrationsData.map(illustration => `node "${LIB}/create-illustrations/index.js" ${illustration.path} ${illustration.defaultText} ${illustration.illustrationsPrefix} ${illustration.set} ${illustration.destinationPath} ${illustration.collection}`);
36
- const createIllustrationsJSImportsScript = illustrations.join(" && ");
37
-
25
+ const createIllustrationsJSImportsScript = {
26
+ default: `ui5nps-p ${illustrationsData.map(illustrations => `build.illustrations.build-${illustrations.set}-${illustrations.collection}`).join(" ")}` // concurently,
27
+ }
28
+ illustrationsData.forEach((illustration) => {
29
+ createIllustrationsJSImportsScript[`build-${illustration.set}-${illustration.collection}`] = `ui5nps-script "${LIB}create-illustrations/index.js" ${illustration.path} ${illustration.defaultText} ${illustration.illustrationsPrefix} ${illustration.set} ${illustration.destinationPath} ${illustration.collection}`
30
+ });
38
31
  // The script creates the "src/generated/js-imports/Illustration.js" file that registers loaders (dynamic JS imports) for each illustration
39
- const createIllustrationsLoadersScript = illustrationsData.map(illustrations => `node ${LIB}/generate-js-imports/illustrations.js ${illustrations.destinationPath} ${illustrations.dynamicImports.outputFile} ${illustrations.set} ${illustrations.collection} ${illustrations.dynamicImports.location} ${illustrations.dynamicImports.filterOut.join(" ")}`).join(" && ");
32
+ const createIllustrationsLoadersScript = {
33
+ default: `ui5nps-p ${illustrationsData.map(illustrations => `build.jsImports.illustrationsLoaders.generate-${illustrations.set}-${illustrations.collection}`).join(" ")}` // concurently,
34
+ }
35
+ illustrationsData.forEach((illustrations) => {
36
+ createIllustrationsLoadersScript[`generate-${illustrations.set}-${illustrations.collection}`] = `ui5nps-script ${LIB}generate-js-imports/illustrations.js ${illustrations.path} ${illustrations.dynamicImports.outputFile} ${illustrations.set} ${illustrations.collection} ${illustrations.dynamicImports.location} ${illustrations.dynamicImports.filterOut.join(",")}`
37
+ });
40
38
 
41
- const tsOption = !options.legacy || options.jsx;
39
+
40
+ const tsOption = !!(!options.legacy || options.jsx);
42
41
  const tsCommandOld = tsOption ? "tsc" : "";
43
42
  let tsWatchCommandStandalone = tsOption ? "tsc --watch" : "";
44
43
  // this command is only used for standalone projects. monorepo projects get their watch from vite, so opt-out here
45
44
  if (options.noWatchTS) {
46
45
  tsWatchCommandStandalone = "";
47
46
  }
48
- const tsCrossEnv = tsOption ? "cross-env UI5_TS=true" : "";
49
47
 
50
48
  if (tsOption) {
51
49
  try {
@@ -68,103 +66,108 @@ const getScripts = (options) => {
68
66
  viteConfig = `-c "${require.resolve("@ui5/webcomponents-tools/components-package/vite.config.js")}"`;
69
67
  }
70
68
 
71
- let eslintConfig;
72
- if (fs.existsSync(".eslintrc.js") || fs.existsSync(".eslintrc.cjs")) {
73
- // preferred way of custom configuration in root project folder
74
- eslintConfig = "";
75
- } else {
76
- // no custom configuration - use default from tools project
77
- eslintConfig = `--config "${require.resolve("@ui5/webcomponents-tools/components-package/eslint.js")}"`;
78
- }
79
-
80
69
  const scripts = {
81
- clean: 'rimraf src/generated && rimraf dist && rimraf .port && nps "scope.testPages.clean"',
82
- lint: `eslint . ${eslintConfig}`,
83
- lintfix: `eslint . ${eslintConfig} --fix`,
70
+ __ui5envs: {
71
+ UI5_CEM_MODE: typeof options.dev === "boolean" ? (options.dev ? "dev" : undefined) : options.dev,
72
+ UI5_TS: `${tsOption}`,
73
+ CSS_VARIABLES_TARGET: options.cssVariablesTarget ?? "root",
74
+ CYPRESS_COVERAGE: !!(options.internal?.cypress_code_coverage),
75
+ },
76
+ clean: {
77
+ "default": "ui5nps clean.generated clean.dist scope.testPages.clean",
78
+ "generated": `ui5nps-script "${LIB}/rimraf/rimraf.js src/generated`,
79
+ "dist": `ui5nps-script "${LIB}/rimraf/rimraf.js dist`,
80
+ },
81
+ lint: `ui5nps-script "${LIB}eslint/eslint.js"`,
82
+ lintfix: `ui5nps-script "${LIB}eslint/eslint.js" --fix`,
84
83
  generate: {
85
- default: `${tsCrossEnv} nps prepare.all`,
86
- all: 'concurrently "nps build.templates" "nps build.i18n" "nps prepare.styleRelated" "nps copyProps" "nps build.illustrations"',
87
- styleRelated: "nps build.styles build.jsonImports build.jsImports",
84
+ default: `ui5nps prepare.all`,
85
+ all: `ui5nps-p build.templates build.i18n prepare.styleRelated copyProps build.illustrations`, // concurently
86
+ styleRelated: "ui5nps build.styles build.jsonImports build.jsImports",
88
87
  },
89
88
  prepare: {
90
- default: `${tsCrossEnv} nps clean prepare.all ${options.legacy ? "copy" : ""} copyProps prepare.typescript generateAPI`,
91
- all: 'concurrently "nps build.templates" "nps build.i18n" "nps prepare.styleRelated" "nps build.illustrations"',
92
- styleRelated: "nps build.styles build.jsonImports build.jsImports",
89
+ default: `ui5nps clean prepare.all copy copyProps prepare.typescript`,
90
+ all: `ui5nps-p build.templates build.i18n prepare.styleRelated build.illustrations`, // concurently
91
+ styleRelated: "ui5nps build.styles build.jsonImports build.jsImports",
93
92
  typescript: tsCommandOld,
94
93
  },
95
94
  build: {
96
- default: "nps prepare lint build.bundle", // build.bundle2
97
- templates: `mkdirp src/generated/templates && ${tsCrossEnv} node "${LIB}/hbs2ui5/index.js" -d src/ -o src/generated/templates`,
95
+ default: "ui5nps prepare lint build.bundle", // build.bundle2
96
+ templates: options.legacy ? `node "${LIB}hbs2ui5/index.js" -d src/ -o src/generated/templates` : "",
98
97
  styles: {
99
- default: `concurrently "nps build.styles.themes" "nps build.styles.components"`,
100
- themes: `node "${LIB}/css-processors/css-processor-themes.mjs"`,
101
- components: `node "${LIB}/css-processors/css-processor-components.mjs"`,
98
+ default: `ui5nps-p build.styles.themes build.styles.components`, // concurently
99
+ themes: `ui5nps-script "${LIB}css-processors/css-processor-themes.mjs"`,
100
+ themesWithWatch: `ui5nps-script "${LIB}css-processors/css-processor-themes.mjs" -w`,
101
+ components: `ui5nps-script "${LIB}css-processors/css-processor-components.mjs"`,
102
+ componentsWithWatch: `ui5nps-script "${LIB}css-processors/css-processor-components.mjs" -w`,
102
103
  },
103
104
  i18n: {
104
- default: "nps build.i18n.defaultsjs build.i18n.json",
105
- defaultsjs: `node "${LIB}/i18n/defaults.js" src/i18n src/generated/i18n`,
106
- json: `node "${LIB}/i18n/toJSON.js" src/i18n dist/generated/assets/i18n`,
105
+ default: "ui5nps build.i18n.defaultsjs build.i18n.json",
106
+ defaultsjs: `ui5nps-script "${LIB}i18n/defaults.js" src/i18n src/generated/i18n`,
107
+ json: `ui5nps-script "${LIB}i18n/toJSON.js" src/i18n dist/generated/assets/i18n`,
107
108
  },
108
109
  jsonImports: {
109
- default: "mkdirp src/generated/json-imports && nps build.jsonImports.themes build.jsonImports.i18n",
110
- themes: `node "${LIB}/generate-json-imports/themes.js" dist/generated/assets/themes src/generated/json-imports`,
111
- i18n: `node "${LIB}/generate-json-imports/i18n.js" dist/generated/assets/i18n src/generated/json-imports`,
110
+ default: "ui5nps build.jsonImports.themes build.jsonImports.i18n",
111
+ themes: `ui5nps-script "${LIB}generate-json-imports/themes.js" src/themes src/generated/json-imports`,
112
+ i18n: `ui5nps-script "${LIB}generate-json-imports/i18n.js" src/i18n src/generated/json-imports`,
112
113
  },
113
114
  jsImports: {
114
- default: "mkdirp src/generated/js-imports && nps build.jsImports.illustrationsLoaders",
115
+ default: "ui5nps build.jsImports.illustrationsLoaders",
115
116
  illustrationsLoaders: createIllustrationsLoadersScript,
116
117
  },
117
- bundle: `vite build ${viteConfig} --mode testing --base ${websiteBaseUrl}`,
118
+ bundle: `ui5nps-script "${LIB}vite-bundler/vite-bundler.mjs" ${viteConfig} --mode testing --base ${websiteBaseUrl}`,
118
119
  bundle2: ``,
119
120
  illustrations: createIllustrationsJSImportsScript,
120
121
  },
121
- copyProps: `node "${LIB}/copy-and-watch/index.js" --silent "src/i18n/*.properties" dist/`,
122
+ copyProps: `ui5nps-script "${LIB}copy-and-watch/index.js" --silent "src/i18n/*.properties" dist/`,
123
+ copyPropsWithWatch: `ui5nps-script "${LIB}copy-and-watch/index.js" --silent "src/i18n/*.properties" dist/ --watch --safe --skip-initial-copy`,
124
+ copySrcWithWatch: `ui5nps-script "${LIB}copy-and-watch/index.js" --silent "src/**/*.{js,json}" dist/ --watch --safe --skip-initial-copy`,
122
125
  copy: {
123
- default: "nps copy.src copy.props",
124
- src: `node "${LIB}/copy-and-watch/index.js" --silent "src/**/*.{js,json}" dist/`,
125
- props: `node "${LIB}/copy-and-watch/index.js" --silent "src/i18n/*.properties" dist/`,
126
+ default: options.legacy ? "ui5nps copy.src copy.props" : "",
127
+ src: options.legacy ? `ui5nps-script "${LIB}copy-and-watch/index.js" --silent "src/**/*.{js,json}" dist/` : "",
128
+ props: options.legacy ? `ui5nps-script "${LIB}copy-and-watch/index.js" --silent "src/i18n/*.properties" dist/` : "",
126
129
  },
127
130
  watch: {
128
- default: `${tsCrossEnv} concurrently "nps watch.templates" "nps watch.typescript" ${options.legacy ? '"nps watch.src"' : ""} "nps watch.styles" "nps watch.i18n" "nps watch.props"`,
129
- devServer: 'concurrently "nps watch.default" "nps watch.bundle"',
130
- src: 'nps "copy.src --watch --safe --skip-initial-copy"',
131
+ default: `ui5nps-p watch.templates watch.typescript watch.src watch.styles watch.i18n watch.props`, // concurently
132
+ devServer: 'ui5nps-p watch.default watch.bundle', // concurently
133
+ src: options.legacy ? 'ui5nps copySrcWithWatch' : "",
131
134
  typescript: tsWatchCommandStandalone,
132
- props: 'nps "copyProps --watch --safe --skip-initial-copy"',
133
- bundle: `node ${LIB}/dev-server/dev-server.mjs ${viteConfig}`,
135
+ props: 'ui5nps copyPropsWithWatch',
136
+ bundle: `ui5nps-script ${LIB}dev-server/dev-server.mjs ${viteConfig}`,
134
137
  styles: {
135
- default: 'concurrently "nps watch.styles.themes" "nps watch.styles.components"',
136
- themes: 'nps "build.styles.themes -w"',
137
- components: `nps "build.styles.components -w"`,
138
+ default: 'ui5nps-p watch.styles.themes watch.styles.components', // concurently
139
+ themes: 'ui5nps build.styles.themesWithWatch',
140
+ components: `ui5nps build.styles.componentsWithWatch`,
138
141
  },
139
- templates: 'chokidar "src/**/*.hbs" -i "src/generated" -c "nps build.templates"',
140
- i18n: 'chokidar "src/i18n/messagebundle.properties" -c "nps build.i18n.defaultsjs"'
142
+ templates: options.legacy ? `ui5nps-script "${LIB}chokidar/chokidar.js" "src/**/*.hbs" "ui5nps build.templates"` : "",
143
+ i18n: `ui5nps-script "${LIB}chokidar/chokidar.js" "src/i18n/messagebundle.properties" "ui5nps build.i18n.defaultsjs"`
141
144
  },
142
- start: "nps prepare watch.devServer",
143
- test: `node "${LIB}/test-runner/test-runner.js"`,
144
- "test-cy-ci": `${cypressEnvVariables(options)} yarn cypress run --component --browser chrome`,
145
- "test-cy-ci-suite-1": `${cypressEnvVariables(options, ["TEST_SUITE=SUITE1"])} yarn cypress run --component --browser chrome`,
146
- "test-cy-ci-suite-2": `${cypressEnvVariables(options, ["TEST_SUITE=SUITE2"])} yarn cypress run --component --browser chrome`,
147
- "test-cy-open": `${cypressEnvVariables(options)} yarn cypress open --component --browser chrome`,
148
- "test-suite-1": `node "${LIB}/test-runner/test-runner.js" --suite suite1`,
149
- "test-suite-2": `node "${LIB}/test-runner/test-runner.js" --suite suite2`,
150
- startWithScope: "nps scope.prepare scope.watchWithBundle",
145
+ start: "ui5nps prepare watch.devServer",
146
+ test: `ui5nps-script "${LIB}/test-runner/test-runner.js"`,
147
+ "test-cy-ci": `cypress run --component --browser chrome`,
148
+ "test-cy-ci-suite-1": `cypress run --component --browser chrome --spec "**/specs/[A-C]*.cy.{js,jsx,ts,tsx},**/specs/[^D-Z]*.cy.{js,jsx,ts,tsx}"`,
149
+ "test-cy-ci-suite-2": `cypress run --component --browser chrome --spec "**/specs/[D-L]*.cy.{js,jsx,ts,tsx}"`,
150
+ "test-cy-ci-suite-3": `cypress run --component --browser chrome --spec "**/specs/[M-S]*.cy.{js,jsx,ts,tsx}"`,
151
+ "test-cy-ci-suite-4": `cypress run --component --browser chrome --spec "**/specs/[T-Z]*.cy.{js,jsx,ts,tsx}"`,
152
+ "test-cy-open": `cypress open --component --browser chrome`,
153
+ startWithScope: "ui5nps scope.prepare scope.watchWithBundle",
151
154
  scope: {
152
- prepare: "nps scope.lint scope.testPages",
153
- lint: `node "${LIB}/scoping/lint-src.js"`,
155
+ prepare: "ui5nps scope.lint scope.testPages",
156
+ lint: `ui5nps-script "${LIB}scoping/lint-src.js"`,
154
157
  testPages: {
155
- default: "nps scope.testPages.clean scope.testPages.copy scope.testPages.replace",
156
- clean: "rimraf test/pages/scoped",
157
- copy: `node "${LIB}/copy-and-watch/index.js" --silent "test/pages/**/*" test/pages/scoped`,
158
- replace: `node "${LIB}/scoping/scope-test-pages.js" test/pages/scoped demo`,
158
+ default: "ui5nps scope.testPages.clean scope.testPages.copy scope.testPages.replace",
159
+ "clean": `ui5nps-script "${LIB}/rimraf/rimraf.js test/pages/scoped`,
160
+ copy: `ui5nps-script "${LIB}copy-and-watch/index.js" --silent "test/pages/**/*" test/pages/scoped`,
161
+ replace: `ui5nps-script "${LIB}scoping/scope-test-pages.js" test/pages/scoped demo`,
159
162
  },
160
- watchWithBundle: 'concurrently "nps scope.watch" "nps scope.bundle" ',
161
- watch: 'concurrently "nps watch.templates" "nps watch.props" "nps watch.styles"',
162
- bundle: `node ${LIB}/dev-server/dev-server.mjs ${viteConfig}`,
163
+ watchWithBundle: 'ui5nps-p scope.watch scope.bundle', // concurently
164
+ watch: 'ui5nps-p watch.templates watch.props watch.styles', // concurently
165
+ bundle: `ui5nps-script ${LIB}dev-server/dev-server.mjs ${viteConfig}`,
163
166
  },
164
167
  generateAPI: {
165
- default: tsOption ? "nps generateAPI.generateCEM generateAPI.validateCEM" : "",
166
- generateCEM: `${options.dev ? "cross-env UI5_CEM_MODE='dev'" : ""} cem analyze --config "${LIB}/cem/custom-elements-manifest.config.mjs"`,
167
- validateCEM: `${options.dev ? "cross-env UI5_CEM_MODE='dev'" : ""} node "${LIB}/cem/validate.js"`,
168
+ generateCEM: `ui5nps-script "${LIB}cem/cem.js" analyze --config "${LIB}cem/custom-elements-manifest.config.mjs"`,
169
+ validateCEM: `ui5nps-script "${LIB}cem/validate.js"`,
170
+ mergeCEM: `ui5nps-script "${LIB}cem/merge.mjs"`,
168
171
  },
169
172
  };
170
173
 
@@ -403,8 +403,14 @@ exports.config = {
403
403
  * @param {Array.<Object>} capabilities list of capabilities details
404
404
  * @param {<Object>} results object containing test results
405
405
  */
406
- // onComplete: function(exitCode, config, capabilities, results) {
407
- // },
406
+ onComplete: function (exitCode, config, capabilities, results) {
407
+ // The results object looks like: { finished: 0, passed: 0, retries: 0, failed: 0 }.
408
+ // If all values are 0, consider that no tests were found or executed.
409
+ if (exitCode === 1 && Object.values(results).every(result => result === 0)) {
410
+ console.log("✅ No specs were found or executed – treating as success.");
411
+ process.exit(0);
412
+ }
413
+ }
408
414
  /**
409
415
  * Gets executed when a refresh happens.
410
416
  * @param {String} oldSessionId session ID of the old session
@@ -4,35 +4,37 @@ const LIB = path.join(__dirname, `../lib/`);
4
4
 
5
5
  const createIconImportsCommand = (options) => {
6
6
  if (!options.versions) {
7
- return `node "${LIB}/create-icons/index.js" "${options.collectionName}"`;
7
+ return `ui5nps-script "${LIB}/create-icons/index.js" "${options.collectionName}"`;
8
8
  }
9
9
 
10
- const command = { default: "nps" };
10
+ const command = { default: "ui5nps" };
11
11
  options.versions.forEach((v) => {
12
12
  command.default += ` build.icons.create${v}`;
13
- command[`create${v}`] = `node "${LIB}/create-icons/index.js" "${options.collectionName}" "${v}"`;
13
+ command[`create${v}`] = `ui5nps-script "${LIB}/create-icons/index.js" "${options.collectionName}" "${v}"`;
14
14
  });
15
15
 
16
16
  return command;
17
17
  }
18
18
 
19
+ const hashesCheck = cmd => `(node "${LIB}/icons-hash/icons-hash.mjs" check) || (${cmd} && node "${LIB}/icons-hash/icons-hash.mjs" save)`;
20
+
19
21
  const copyIconAssetsCommand = (options) => {
20
22
  if (!options.versions) {
21
- return {
22
- default: "nps copy.json-imports copy.icon-collection",
23
- "json-imports": `node "${LIB}/copy-and-watch/index.js" --silent "src/**/*.js" dist/`,
24
- "icon-collection": `node "${LIB}/copy-and-watch/index.js" --silent "src/*.json" src/generated/assets/`,
23
+ return {
24
+ default: "ui5nps copy.json-imports copy.icon-collection",
25
+ "json-imports": `ui5nps-script "${LIB}/copy-and-watch/index.js" --silent "src/**/*.js" dist/`,
26
+ "icon-collection": `ui5nps-script "${LIB}/copy-and-watch/index.js" --silent "src/*.json" src/generated/assets/`,
25
27
  }
26
28
  }
27
29
 
28
- const command = {
29
- default: "nps copy.json-imports ",
30
- "json-imports": `node "${LIB}/copy-and-watch/index.js" --silent "src/**/*.js" dist/`,
30
+ const command = {
31
+ default: "ui5nps copy.json-imports ",
32
+ "json-imports": `ui5nps-script "${LIB}/copy-and-watch/index.js" --silent "src/**/*.js" dist/`,
31
33
  };
32
34
 
33
35
  options.versions.forEach((v) => {
34
36
  command.default += ` copy.icon-collection${v}`;
35
- command[`icon-collection${v}`] = `node "${LIB}/copy-and-watch/index.js" --silent "src/${v}/*.json" src/generated/assets/${v}/`;
37
+ command[`icon-collection${v}`] = `ui5nps-script "${LIB}/copy-and-watch/index.js" --silent "src/${v}/*.json" src/generated/assets/${v}/`;
36
38
  });
37
39
 
38
40
  return command;
@@ -42,23 +44,30 @@ const getScripts = (options) => {
42
44
  const createJSImportsCmd = createIconImportsCommand(options);
43
45
  const copyAssetsCmd = copyIconAssetsCommand(options);
44
46
  const tsCommand = !options.legacy ? "tsc --build" : "";
45
- const tsCrossEnv = !options.legacy ? "cross-env UI5_TS=true" : "";
47
+ const tsOption = !options.legacy;
46
48
 
47
49
  const scripts = {
48
- clean: "rimraf dist && rimraf src/generated",
50
+ __ui5envs: {
51
+ UI5_TS: `${tsOption}`,
52
+ },
53
+ clean: {
54
+ default: "ui5nps clean.generated clean.dist",
55
+ "generated": `ui5nps-script "${LIB}/rimraf/rimraf.js src/generated`,
56
+ "dist": `ui5nps-script "${LIB}/rimraf/rimraf.js dist`,
57
+ },
49
58
  copy: copyAssetsCmd,
50
- generate: `${tsCrossEnv} nps clean copy build.i18n build.icons build.jsonImports copyjson`,
51
- copyjson: "copy-and-watch \"src/generated/**/*.json\" dist/generated/",
59
+ generate: hashesCheck(`ui5nps clean copy build.i18n build.icons build.jsonImports copyjson`),
60
+ copyjson: `ui5nps-script "${LIB}copy-and-watch/index.js" "src/generated/**/*.json" dist/generated`,
52
61
  build: {
53
- default: `${tsCrossEnv} nps clean copy build.i18n typescript build.icons build.jsonImports`,
62
+ default: hashesCheck(`ui5nps clean copy build.i18n typescript build.icons build.jsonImports`),
54
63
  i18n: {
55
- default: "nps build.i18n.defaultsjs build.i18n.json",
56
- defaultsjs: `mkdirp dist/generated/i18n && node "${LIB}/i18n/defaults.js" src/i18n src/generated/i18n`,
57
- json: `mkdirp src/generated/assets/i18n && node "${LIB}/i18n/toJSON.js" src/i18n src/generated/assets/i18n`,
64
+ default: "ui5nps build.i18n.defaultsjs build.i18n.json",
65
+ defaultsjs: `ui5nps-script "${LIB}/i18n/defaults.js" src/i18n src/generated/i18n`,
66
+ json: `ui5nps-script "${LIB}/i18n/toJSON.js" src/i18n src/generated/assets/i18n`,
58
67
  },
59
68
  jsonImports: {
60
- default: "mkdirp src/generated/json-imports && nps build.jsonImports.i18n",
61
- i18n: `node "${LIB}/generate-json-imports/i18n.js" src/generated/assets/i18n src/generated/json-imports`,
69
+ default: "ui5nps build.jsonImports.i18n",
70
+ i18n: `ui5nps-script "${LIB}/generate-json-imports/i18n.js" src/generated/assets/i18n src/generated/json-imports`,
62
71
  },
63
72
  icons: createJSImportsCmd,
64
73
  },
@@ -1,6 +1,5 @@
1
1
  const fs = require("fs").promises;
2
2
  const path = require("path");
3
- const basePath = process.argv[2];
4
3
  const babelCore = require("@babel/core");
5
4
  const babelParser = require("@babel/parser");
6
5
  const babelGenerator = require("@babel/generator").default;
@@ -21,7 +20,7 @@ const convertAmdToEs6 = async (code) => {
21
20
  })).code;
22
21
  }
23
22
 
24
- const convertAbsImportsToRelative = (filePath, code) => {
23
+ const convertAbsImportsToRelative = (filePath, code, basePath) => {
25
24
  let changed = false;
26
25
  // console.log("File processing started: ", srcPath);
27
26
 
@@ -69,7 +68,7 @@ const convertAbsImportsToRelative = (filePath, code) => {
69
68
  }
70
69
 
71
70
  const replaceGlobalCoreUsage = (filePath, code) => {
72
- if (!filePath.includes("Configuration")) {
71
+ if (!filePath.includes("Configuration")) {
73
72
  const replaced = code.replace(/sap\.ui\.getCore\(\)/g, `Core`);
74
73
  return code !== replaced ? `import Core from 'sap/ui/core/Core';${replaced}` : code;
75
74
  }
@@ -77,7 +76,7 @@ const replaceGlobalCoreUsage = (filePath, code) => {
77
76
  return code;
78
77
  };
79
78
 
80
- const transformAmdToES6Module = async (filePath) => {
79
+ const transformAmdToES6Module = async (filePath, basePath) => {
81
80
  await convertSAPUIDefineToDefine(filePath);
82
81
 
83
82
  let code = (await fs.readFile(filePath)).toString();
@@ -86,17 +85,25 @@ const transformAmdToES6Module = async (filePath) => {
86
85
 
87
86
  code = replaceGlobalCoreUsage(filePath, code);
88
87
 
89
- code = convertAbsImportsToRelative(filePath, code);
88
+ code = convertAbsImportsToRelative(filePath, code, basePath);
90
89
 
91
90
  return fs.writeFile(filePath, code);
92
91
  }
93
92
 
94
- const transformAmdToES6Modules = async () => {
93
+ const transformAmdToES6Modules = async (argv) => {
94
+ const basePath = argv[2];
95
95
  const { globby } = await import("globby");
96
96
  const fileNames = await globby(basePath.replace(/\\/g, "/") + "**/*.js");
97
- return Promise.all(fileNames.map(transformAmdToES6Module).filter(x => !!x));
97
+ return Promise.all(fileNames.map(fileName => transformAmdToES6Module(fileName, basePath)).filter(x => !!x))
98
+ .then(() => {
99
+ if (process.env.UI5_VERBOSE === "true") {
100
+ console.log("Success: all amd modules are transformed to es6!");
101
+ }
102
+ });
98
103
  };
99
104
 
100
- transformAmdToES6Modules().then(() => {
101
- console.log("Success: all amd modules are transformed to es6!");
102
- });
105
+ if (require.main === module) {
106
+ transformAmdToES6Modules(process.argv)
107
+ }
108
+
109
+ exports._ui5mainFn = transformAmdToES6Modules;
package/lib/cem/cem.js ADDED
@@ -0,0 +1,16 @@
1
+ const cemCLI = require("./patch/@custom-elements-manifest/analyzer/cli.js")
2
+
3
+ const main = async argv => {
4
+ const patchedArgv = argv.slice(2);
5
+ // Add --quiet flag unless verbose mode is enabled
6
+ if (process.env.UI5_VERBOSE !== "true" && !patchedArgv.includes("--quiet")) {
7
+ patchedArgv.push("--quiet");
8
+ }
9
+ await cemCLI.cli({ argv: patchedArgv, cwd: process.cwd(), noWrite: false });
10
+ }
11
+
12
+ if (require.main === module) {
13
+ main(process.argv)
14
+ }
15
+
16
+ exports._ui5mainFn = main;
@@ -17,6 +17,7 @@ import {
17
17
  getTypeRefs,
18
18
  normalizeDescription,
19
19
  formatArrays,
20
+ formatSlotTypes,
20
21
  isClass,
21
22
  normalizeTagType,
22
23
  logDocumentationError,
@@ -27,7 +28,44 @@ import { generateCustomData } from "cem-plugin-vs-code-custom-data-generator";
27
28
  import { customElementJetBrainsPlugin } from "custom-element-jet-brains-integration";
28
29
 
29
30
  const packageJSON = JSON.parse(fs.readFileSync("./package.json"));
31
+ let aliasMap = {};
32
+
30
33
  const devMode = process.env.UI5_CEM_MODE === "dev";
34
+ const isVerbose = process.env.UI5_VERBOSE === "true";
35
+
36
+ /**
37
+ * Wraps a CEM plugin to suppress console output in quiet mode.
38
+ * @param {Object} plugin - The plugin to wrap
39
+ * @returns {Object} - Wrapped plugin with silent console during packageLinkPhase
40
+ */
41
+ const wrapPluginForQuietMode = (plugin) => {
42
+ if (isVerbose) return plugin;
43
+
44
+ const originalPackageLinkPhase = plugin.packageLinkPhase;
45
+ if (!originalPackageLinkPhase) return plugin;
46
+
47
+ return {
48
+ ...plugin,
49
+ packageLinkPhase(context) {
50
+ const originalLog = console.log;
51
+ console.log = () => { };
52
+ try {
53
+ return originalPackageLinkPhase.call(plugin, context);
54
+ } finally {
55
+ console.log = originalLog;
56
+ }
57
+ }
58
+ };
59
+ };
60
+
61
+ try {
62
+ aliasMap = JSON.parse(fs.readFileSync("./.ui5-cem-aliases.json"));
63
+ } catch (e) {
64
+ if (devMode && isVerbose) {
65
+ console.warn("No .ui5-cem-aliases.json file found. Continuing without aliases.");
66
+ }
67
+ }
68
+
31
69
 
32
70
  const extractClassNodeJSDoc = node => {
33
71
  const fileContent = node.getFullText();
@@ -97,6 +135,13 @@ function processClass(ts, classNode, moduleDoc) {
97
135
  if (currClass.superclass?.name === "UI5Element") {
98
136
  currClass.customElement = true;
99
137
  }
138
+ } else if (currClass.customElement && classNode?.heritageClauses) {
139
+ // Find the extends clause (not implements)
140
+ const extendsClause = classNode.heritageClauses.find(clause => clause.token === ts.SyntaxKind.ExtendsKeyword);
141
+ if (extendsClause?.types?.[0]?.expression?.text) {
142
+ const extendedClass = extendsClause.types[0].expression.text;
143
+ logDocumentationError(moduleDoc.path, `Class extends ${extendedClass} but @extends tag is missing in JSDoc`);
144
+ }
100
145
  }
101
146
 
102
147
  if (!currClass._ui5implements.length) delete currClass._ui5implements;
@@ -158,6 +203,7 @@ function processClass(ts, classNode, moduleDoc) {
158
203
 
159
204
  if (member.type?.text) {
160
205
  member.type.text = formatArrays(member.type.text);
206
+ member.type.text = formatSlotTypes(member.type.text);
161
207
  }
162
208
 
163
209
  if (member.type && typeRefs.length) {
@@ -378,10 +424,10 @@ const processPublicAPI = object => {
378
424
  return true;
379
425
  }
380
426
  for (const key of keys) {
381
- if ((key === "privacy" && object[key] !== "public") || (key === "_ui5privacy" && object[key] !== "public")) {
427
+ if (((key === "privacy" && object[key] !== "public") || (key === "_ui5privacy" && object[key] !== "public")) && !object.customElement) {
382
428
  return true;
383
429
  } else if (typeof object[key] === "object") {
384
- if (key === "cssParts" || key === "attributes" || key === "_ui5implements") {
430
+ if (key === "cssParts" || key === "cssStates" || key === "attributes" || key === "_ui5implements") {
385
431
  continue;
386
432
  }
387
433
 
@@ -486,6 +532,12 @@ export default {
486
532
  }
487
533
  }
488
534
 
535
+ moduleDoc.declarations.forEach(declaration => {
536
+ if (declaration.superclass?.name && aliasMap[declaration.superclass.name]) {
537
+ declaration.superclass.name = aliasMap[declaration.superclass.name];
538
+ }
539
+ })
540
+
489
541
  const typeReferences = new Set();
490
542
  const registerTypeReference = reference => typeReferences.add(JSON.stringify(reference))
491
543
 
@@ -524,7 +576,7 @@ export default {
524
576
  }
525
577
  }
526
578
  },
527
- generateCustomData({ outdir: "dist", cssFileName: null, cssPropertiesDocs: false }),
528
- customElementJetBrainsPlugin({ outdir: "dist", cssFileName: null, cssPropertiesDocs: false })
579
+ wrapPluginForQuietMode(generateCustomData({ outdir: "dist", cssFileName: null, cssPropertiesDocs: false })),
580
+ wrapPluginForQuietMode(customElementJetBrainsPlugin({ outdir: "dist", cssFileName: null, cssPropertiesDocs: false }))
529
581
  ],
530
582
  };