@ui5/webcomponents-tools 0.0.0-8da65021d → 0.0.0-8e1845415

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 (95) hide show
  1. package/CHANGELOG.md +357 -1
  2. package/README.md +5 -6
  3. package/assets-meta.js +7 -1
  4. package/bin/dev.js +1 -5
  5. package/components-package/eslint.js +28 -0
  6. package/components-package/nps.js +83 -54
  7. package/components-package/postcss.components.js +13 -13
  8. package/components-package/postcss.themes.js +19 -16
  9. package/components-package/vite.config.js +12 -0
  10. package/components-package/wdio.js +78 -29
  11. package/components-package/wdio.sync.js +360 -0
  12. package/icons-collection/nps.js +46 -15
  13. package/lib/copy-and-watch/index.js +24 -1
  14. package/lib/copy-list/index.js +28 -0
  15. package/lib/create-icons/index.js +124 -58
  16. package/lib/create-illustrations/index.js +161 -0
  17. package/lib/create-new-component/index.js +108 -103
  18. package/lib/create-new-component/jsFileContentTemplate.js +77 -0
  19. package/lib/create-new-component/tsFileContentTemplate.js +84 -0
  20. package/lib/dev-server/dev-server.js +66 -0
  21. package/lib/dev-server/virtual-index-html-plugin.js +53 -0
  22. package/lib/esm-abs-to-rel/index.js +58 -0
  23. package/lib/generate-custom-elements-manifest/index.js +327 -0
  24. package/lib/generate-js-imports/illustrations.js +72 -0
  25. package/lib/generate-json-imports/i18n.js +38 -31
  26. package/lib/generate-json-imports/themes.js +31 -24
  27. package/lib/hbs2lit/src/compiler.js +20 -3
  28. package/lib/hbs2lit/src/includesReplacer.js +5 -5
  29. package/lib/hbs2lit/src/litVisitor2.js +77 -14
  30. package/lib/hbs2lit/src/svgProcessor.js +3 -3
  31. package/lib/hbs2ui5/RenderTemplates/LitRenderer.js +4 -11
  32. package/lib/hbs2ui5/index.js +37 -21
  33. package/lib/i18n/defaults.js +65 -57
  34. package/lib/i18n/toJSON.js +12 -11
  35. package/lib/jsdoc/configTypescript.json +29 -0
  36. package/lib/jsdoc/plugin.js +41 -0
  37. package/lib/jsdoc/preprocess.js +146 -0
  38. package/lib/jsdoc/template/publish.js +21 -2
  39. package/lib/postcss-combine-duplicated-selectors/index.js +178 -0
  40. package/lib/postcss-css-to-esm/index.js +53 -8
  41. package/lib/postcss-css-to-json/index.js +18 -2
  42. package/lib/postcss-p/postcss-p.mjs +14 -0
  43. package/lib/replace-global-core/index.js +25 -0
  44. package/lib/scoping/get-all-tags.js +1 -8
  45. package/lib/scoping/lint-src.js +1 -1
  46. package/lib/scoping/missing-dependencies.js +65 -0
  47. package/lib/scoping/report-tags-usage.js +28 -0
  48. package/lib/scoping/scope-test-pages.js +1 -1
  49. package/lib/test-runner/test-runner.js +63 -0
  50. package/package.json +28 -39
  51. package/bin/init-ui5-package.js +0 -3
  52. package/components-package/rollup.js +0 -195
  53. package/lib/documentation/index.js +0 -165
  54. package/lib/documentation/templates/api-component-since.js +0 -3
  55. package/lib/documentation/templates/api-css-variables-section.js +0 -24
  56. package/lib/documentation/templates/api-events-section.js +0 -35
  57. package/lib/documentation/templates/api-methods-section.js +0 -26
  58. package/lib/documentation/templates/api-properties-section.js +0 -40
  59. package/lib/documentation/templates/api-slots-section.js +0 -28
  60. package/lib/documentation/templates/template.js +0 -38
  61. package/lib/hash/config.js +0 -10
  62. package/lib/hash/generate.js +0 -19
  63. package/lib/hash/upToDate.js +0 -31
  64. package/lib/init-package/index.js +0 -123
  65. package/lib/init-package/resources/.eslintignore +0 -3
  66. package/lib/init-package/resources/bundle.es5.js +0 -25
  67. package/lib/init-package/resources/bundle.esm.js +0 -31
  68. package/lib/init-package/resources/config/.eslintrc.js +0 -1
  69. package/lib/init-package/resources/config/postcss.components/postcss.config.js +0 -1
  70. package/lib/init-package/resources/config/postcss.themes/postcss.config.js +0 -1
  71. package/lib/init-package/resources/config/rollup.config.js +0 -1
  72. package/lib/init-package/resources/config/wdio.conf.js +0 -1
  73. package/lib/init-package/resources/package-scripts.js +0 -11
  74. package/lib/init-package/resources/src/Assets.js +0 -5
  75. package/lib/init-package/resources/src/MyFirstComponent.hbs +0 -1
  76. package/lib/init-package/resources/src/MyFirstComponent.js +0 -56
  77. package/lib/init-package/resources/src/i18n/messagebundle.properties +0 -2
  78. package/lib/init-package/resources/src/i18n/messagebundle_de.properties +0 -1
  79. package/lib/init-package/resources/src/i18n/messagebundle_en.properties +0 -1
  80. package/lib/init-package/resources/src/i18n/messagebundle_es.properties +0 -1
  81. package/lib/init-package/resources/src/i18n/messagebundle_fr.properties +0 -1
  82. package/lib/init-package/resources/src/themes/MyFirstComponent.css +0 -11
  83. package/lib/init-package/resources/src/themes/sap_belize/parameters-bundle.css +0 -3
  84. package/lib/init-package/resources/src/themes/sap_belize_hcb/parameters-bundle.css +0 -3
  85. package/lib/init-package/resources/src/themes/sap_belize_hcw/parameters-bundle.css +0 -3
  86. package/lib/init-package/resources/src/themes/sap_fiori_3/parameters-bundle.css +0 -3
  87. package/lib/init-package/resources/src/themes/sap_fiori_3_dark/parameters-bundle.css +0 -3
  88. package/lib/init-package/resources/src/themes/sap_fiori_3_hcb/parameters-bundle.css +0 -3
  89. package/lib/init-package/resources/src/themes/sap_fiori_3_hcw/parameters-bundle.css +0 -3
  90. package/lib/init-package/resources/test/pages/index.html +0 -56
  91. package/lib/init-package/resources/test/specs/Demo.spec.js +0 -12
  92. package/lib/polyfill-placeholder/index.js +0 -5
  93. package/lib/serve/index.js +0 -46
  94. package/lib/serve/serve.json +0 -3
  95. package/package-lock.json +0 -48
@@ -1,80 +1,7 @@
1
1
  const fs = require("fs");
2
-
3
- const jsFileContentTemplate = componentName => {
4
- return `import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
5
- import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
6
- import ${componentName}Template from "./generated/templates/${componentName}Template.lit.js";
7
-
8
- // Styles
9
- import ${componentName}Css from "./generated/themes/${componentName}.css.js";
10
-
11
- /**
12
- * @public
13
- */
14
- const metadata = {
15
- tag: "${tagName}",
16
- properties: /** @lends sap.ui.webcomponents.${library}.${componentName}.prototype */ {
17
- //
18
- },
19
- slots: /** @lends sap.ui.webcomponents.${library}.${componentName}.prototype */ {
20
- //
21
- },
22
- events: /** @lends sap.ui.webcomponents.${library}.${componentName}.prototype */ {
23
- //
24
- },
25
- };
26
-
27
- /**
28
- * @class
29
- *
30
- * <h3 class="comment-api-title">Overview</h3>
31
- *
32
- *
33
- * <h3>Usage</h3>
34
- *
35
- * For the <code>${tagName}</code>
36
- * <h3>ES6 Module Import</h3>
37
- *
38
- * <code>import ${packageName}/dist/${componentName}.js";</code>
39
- *
40
- * @constructor
41
- * @author SAP SE
42
- * @alias sap.ui.webcomponents.${library}.${componentName}
43
- * @extends UI5Element
44
- * @tagname ${tagName}
45
- * @public
46
- */
47
- class ${componentName} extends UI5Element {
48
- static get metadata() {
49
- return metadata;
50
- }
51
-
52
- static get render() {
53
- return litRender;
54
- }
55
-
56
- static get styles() {
57
- return ${componentName}Css;
58
- }
59
-
60
- static get template() {
61
- return ${componentName}Template;
62
- }
63
-
64
- static get dependencies() {
65
- return [];
66
- }
67
-
68
- static async onDefine() {
69
-
70
- }
71
- }
72
-
73
- ${componentName}.define();
74
-
75
- export default ${componentName};
76
- `;
77
- };
2
+ const prompts = require("prompts");
3
+ const jsFileContentTemplate = require("./jsFileContentTemplate.js");
4
+ const tsFileContentTemplate = require("./tsFileContentTemplate.js");
78
5
 
79
6
  const getPackageName = () => {
80
7
  if (!fs.existsSync("./package.json")) {
@@ -108,39 +35,117 @@ const getLibraryName = packageName => {
108
35
  return packageName.substr("webcomponents-".length);
109
36
  };
110
37
 
111
- const camelToKebabCase = string => string.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
38
+ // String manipulation
39
+ const capitalizeFirstLetter = string => string.charAt(0).toUpperCase() + string.slice(1);
40
+
41
+ // Validation of user input
42
+ const isNameValid = name => typeof name === "string" && name.match(/^[a-zA-Z][a-zA-Z0-9_-]*$/);
43
+ const isTagNameValid = tagName => tagName.match(/^([a-z][a-z0-9]*-)([a-z0-9]+(-[a-z0-9]+)*)$/);
44
+
45
+ const generateFiles = (componentName, tagName, library, packageName, isTypeScript) => {
46
+ componentName = capitalizeFirstLetter(componentName);
47
+ const filePaths = {
48
+ "main": isTypeScript
49
+ ? `./src/${componentName}.ts`
50
+ : `./src/${componentName}.js`,
51
+ "css": `./src/themes/${componentName}.css`,
52
+ "template": `./src/${componentName}.hbs`,
53
+ };
54
+
55
+ const FileContentTemplate = isTypeScript
56
+ ? tsFileContentTemplate(componentName, tagName, library, packageName)
57
+ : jsFileContentTemplate(componentName, tagName, library, packageName);
58
+
59
+ fs.writeFileSync(filePaths.main, FileContentTemplate, { flag: "wx+" });
60
+ fs.writeFileSync(filePaths.css, "", { flag: "wx+" });
61
+ fs.writeFileSync(filePaths.template, "<div>Hello World</div>", { flag: "wx+" });
62
+
63
+ console.log(`Successfully generated ${filePaths.main}`);
64
+ console.log(`Successfully generated ${filePaths.css}`);
65
+ console.log(`Successfully generated ${filePaths.template}`);
66
+
67
+ // Change the color of the output
68
+ console.warn('\x1b[33m%s\x1b[0m', `
69
+ Make sure to import the component in your bundle by using:
70
+ import ${componentName} from "./dist/${componentName}.js";`);
71
+ }
112
72
 
113
- const packageName = getPackageName();
114
- const library = getLibraryName(packageName);
73
+ // Main function
74
+ const createWebComponent = async () => {
75
+ const packageName = getPackageName();
76
+ const library = getLibraryName(packageName);
115
77
 
116
- const consoleArguments = process.argv.slice(2);
117
- const componentName = consoleArguments[0];
78
+ const consoleArguments = process.argv.slice(2);
79
+ let componentName = consoleArguments[0];
80
+ let tagName = consoleArguments[1];
81
+ let language = consoleArguments[2];
82
+ let isTypeScript;
118
83
 
119
- if (!componentName){
120
- console.error("Please enter component name.");
121
- return;
122
- }
123
84
 
124
- const tagName = `ui5-${camelToKebabCase(componentName)}`;
85
+ if (componentName && !isNameValid(componentName)) {
86
+ throw new Error("Invalid component name. Please use only letters, numbers, dashes and underscores. The first character must be a letter.");
87
+ }
125
88
 
126
- const filePaths = {
127
- "js": `./src/${componentName}.js`,
128
- "css": `./src/themes/${componentName}.css`,
129
- "hbs": `./src/${componentName}.hbs`,
130
- };
131
- const sJsFileContentTemplate = jsFileContentTemplate(componentName);
89
+ if (tagName && !isTagNameValid(tagName)) {
90
+ throw new Error("Invalid tag name. The tag name should only contain lowercase letters, numbers, dashes, and underscores. The first character must be a letter, and it should follow the pattern 'tag-name'.");
91
+ }
132
92
 
133
- fs.writeFileSync(filePaths.js, sJsFileContentTemplate, { flag: "wx+" });
134
- fs.writeFileSync(filePaths.css, "", { flag: "wx+" });
135
- fs.writeFileSync(filePaths.hbs, "<div>Hello World</div>", { flag: "wx+" });
93
+ if (language && language !== "typescript" && language !== "ts" && language !== "javascript" && language !== "js") {
94
+ throw new Error("Invalid language. Please use 'typescript','javascript' or their respective 'ts','js'.");
95
+ }
96
+
97
+ if (!componentName) {
98
+ const response = await prompts({
99
+ type: "text",
100
+ name: "componentName",
101
+ message: "Please enter a component name:",
102
+ validate: (value) => isNameValid(value),
103
+ });
104
+ componentName = response.componentName;
105
+
106
+ if (!componentName) {
107
+ process.exit();
108
+ }
109
+ }
136
110
 
111
+ if (!tagName) {
112
+ const response = await prompts({
113
+ type: "text",
114
+ name: "tagName",
115
+ message: "Please enter a tag name:",
116
+ validate: (value) => isTagNameValid(value),
117
+ });
118
+ tagName = response.tagName;
119
+
120
+ if (!tagName) {
121
+ process.exit();
122
+ }
123
+ }
137
124
 
138
- console.log(`Successfully generated ${componentName}.js`);
139
- console.log(`Successfully generated ${componentName}.css`);
140
- console.log(`Successfully generated ${componentName}.hbs`);
125
+ if (!language) {
126
+ const response = await prompts({
127
+ type: "select",
128
+ name: "isTypeScript",
129
+ message: "Please select a language:",
130
+ choices: [
131
+ {
132
+ title: "TypeScript (recommended)",
133
+ value: true,
134
+ },
135
+ {
136
+ title: "JavaScript",
137
+ value: false,
138
+ },
139
+ ],
140
+ });
141
+ isTypeScript = response.isTypeScript;
142
+ } else if (language === "typescript" || language === "ts") {
143
+ isTypeScript = true;
144
+ } else {
145
+ isTypeScript = false;
146
+ }
147
+
148
+ generateFiles(componentName, tagName, library, packageName, isTypeScript);
149
+ };
141
150
 
142
- // Change the color of the output
143
- console.warn('\x1b[33m%s\x1b[0m', `
144
- Please import the generated component in bundle.esm.js:
145
- import ${componentName} from "./dist/${componentName}.js";
146
- `);
151
+ createWebComponent();
@@ -0,0 +1,77 @@
1
+ const jsFileContentTemplate = (componentName, tagName, library, packageName) => {
2
+ return `import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
3
+ import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
4
+ import ${componentName}Template from "./generated/templates/${componentName}Template.lit.js";
5
+
6
+ // Styles
7
+ import ${componentName}Css from "./generated/themes/${componentName}.css.js";
8
+
9
+ /**
10
+ * @public
11
+ */
12
+ const metadata = {
13
+ tag: "${tagName}",
14
+ properties: /** @lends sap.ui.webc.${library}.${componentName}.prototype */ {
15
+ //
16
+ },
17
+ slots: /** @lends sap.ui.webc.${library}.${componentName}.prototype */ {
18
+ //
19
+ },
20
+ events: /** @lends sap.ui.webc.${library}.${componentName}.prototype */ {
21
+ //
22
+ },
23
+ };
24
+
25
+ /**
26
+ * @class
27
+ *
28
+ * <h3 class="comment-api-title">Overview</h3>
29
+ *
30
+ *
31
+ * <h3>Usage</h3>
32
+ *
33
+ * For the <code>${tagName}</code>
34
+ * <h3>ES6 Module Import</h3>
35
+ *
36
+ * <code>import ${packageName}/dist/${componentName}.js";</code>
37
+ *
38
+ * @constructor
39
+ * @author SAP SE
40
+ * @alias sap.ui.webc.${library}.${componentName}
41
+ * @extends sap.ui.webc.base.UI5Element
42
+ * @tagname ${tagName}
43
+ * @public
44
+ */
45
+ class ${componentName} extends UI5Element {
46
+ static get metadata() {
47
+ return metadata;
48
+ }
49
+
50
+ static get render() {
51
+ return litRender;
52
+ }
53
+
54
+ static get styles() {
55
+ return ${componentName}Css;
56
+ }
57
+
58
+ static get template() {
59
+ return ${componentName}Template;
60
+ }
61
+
62
+ static get dependencies() {
63
+ return [];
64
+ }
65
+
66
+ static async onDefine() {
67
+
68
+ }
69
+ }
70
+
71
+ ${componentName}.define();
72
+
73
+ export default ${componentName};
74
+ `;
75
+ };
76
+
77
+ module.exports = jsFileContentTemplate;
@@ -0,0 +1,84 @@
1
+ const tsFileContentTemplate = (componentName, tagName, library, packageName) => {
2
+ return `import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
3
+ import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js";
4
+ import property from "@ui5/webcomponents-base/dist/decorators/property.js";
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";
8
+
9
+ import ${componentName}Template from "./generated/templates/${componentName}Template.lit.js";
10
+
11
+ // Styles
12
+ import ${componentName}Css from "./generated/themes/${componentName}.css.js";
13
+
14
+ /**
15
+ * @class
16
+ *
17
+ * <h3 class="comment-api-title">Overview</h3>
18
+ *
19
+ *
20
+ * <h3>Usage</h3>
21
+ *
22
+ * For the <code>${tagName}</code>
23
+ * <h3>ES6 Module Import</h3>
24
+ *
25
+ * <code>import ${packageName}/dist/${componentName}.js";</code>
26
+ *
27
+ * @constructor
28
+ * @author SAP SE
29
+ * @alias sap.ui.webc.${library}.${componentName}
30
+ * @extends sap.ui.webc.base.UI5Element
31
+ * @tagname ${tagName}
32
+ * @public
33
+ */
34
+ @customElement({
35
+ tag: "${tagName}",
36
+ renderer: litRender,
37
+ styles: ${componentName}Css,
38
+ template: ${componentName}Template,
39
+ dependencies: [],
40
+ })
41
+
42
+ /**
43
+ * Example custom event.
44
+ * Please keep in mind that all public events should be documented in the API Reference as shown below.
45
+ *
46
+ * @event sap.ui.webc.${library}.${componentName}#interact
47
+ * @public
48
+ */
49
+ @event("interact", { detail: { /* event payload ( optional ) */ } })
50
+ class ${componentName} extends UI5Element {
51
+ /**
52
+ * Defines the value of the component.
53
+ *
54
+ * @type {string}
55
+ * @name sap.ui.webc.${library}.${componentName}.prototype.value
56
+ * @defaultvalue ""
57
+ * @public
58
+ */
59
+ @property()
60
+ value!: string;
61
+
62
+ /**
63
+ * Defines the text of the component.
64
+ *
65
+ * @type {Node[]}
66
+ * @name sap.ui.webc.${library}.${componentName}.prototype.default
67
+ * @slot
68
+ * @public
69
+ */
70
+ @slot({ type: Node, "default": true })
71
+ text!: Array<Node>;
72
+
73
+ static async onDefine() {
74
+
75
+ }
76
+ }
77
+
78
+ ${componentName}.define();
79
+
80
+ export default ${componentName};
81
+ `;
82
+ };
83
+
84
+ module.exports = tsFileContentTemplate;
@@ -0,0 +1,66 @@
1
+ const fs = require("fs/promises");
2
+ const { createServer } = require('vite');
3
+ const yargs = require('yargs/yargs')
4
+ const { hideBin } = require('yargs/helpers')
5
+
6
+ const argv = yargs(hideBin(process.argv))
7
+ .alias("c", "config")
8
+ .argv;
9
+
10
+ const startVite = async (port) => {
11
+ const server = await createServer({
12
+ configFile: argv.config,
13
+ server: {
14
+ port: port,
15
+ strictPort: true,
16
+ open: true,
17
+ host: true,
18
+ },
19
+ logLevel: 'info',
20
+ clearScreen: false,
21
+ })
22
+ await server.listen()
23
+ server.printUrls()
24
+ return server;
25
+ };
26
+
27
+ const rmPortFile = async () => {
28
+ // exit handler must be sync
29
+ try {
30
+ await fs.rm(".dev-server-port");
31
+ } catch (e) {}
32
+ process.exit();
33
+ }
34
+
35
+ ["exit", "SIGINT", "SIGUSR1", "SIGUSR2", "uncaughtException", "SIGTERM"].forEach((eventType) => {
36
+ process.on(eventType, rmPortFile);
37
+ });
38
+
39
+ (async () => {
40
+ let retries = 10;
41
+ let port = 8080;
42
+ while (retries--) {
43
+ console.log(`taking port ${port}`);
44
+ await fs.writeFile(".dev-server-port", `${port}`);
45
+ try {
46
+ // execSync(command, {stdio: 'pipe'});
47
+ const server = await startVite(port);
48
+ if (server) {
49
+ // server started, don't try other ports
50
+ break;
51
+ }
52
+ } catch (e) {
53
+ // uncomment for debug
54
+ // console.log(e.toString());
55
+ if (e.toString().includes("already in use")) {
56
+ console.log(`Port ${port} already in use`)
57
+ port++;
58
+ continue;
59
+ }
60
+ // other error or CTRL-C
61
+ process.exit();
62
+ }
63
+ // no error normal exit
64
+ // process.exit();
65
+ }
66
+ })();
@@ -0,0 +1,53 @@
1
+ let path = require("path");
2
+
3
+ const virtualIndexPlugin = async () => {
4
+ const { globby } = await import("globby");
5
+ const files = await globby(["test/pages/**/*.html", "packages/*/test/pages/**/*.html"]);
6
+
7
+ const pagesPerFolder = {};
8
+ files.forEach(file => {
9
+ let folder = pagesPerFolder[path.dirname(file)] = pagesPerFolder[path.dirname(file)] || [];
10
+ folder.push(path.basename(file));
11
+ });
12
+
13
+ const rollupInput = {};
14
+
15
+ files.forEach(file => {
16
+ rollupInput[file] = path.resolve(process.cwd(), file);
17
+ })
18
+
19
+ return {
20
+ name: 'virtual-index-html',
21
+ config() {
22
+ return {
23
+ build: {
24
+ rollupOptions: {
25
+ input: rollupInput
26
+ }
27
+ }
28
+ }
29
+ },
30
+ configureServer(server) {
31
+ server.middlewares.use((req, res, next) => {
32
+ if (req.url === "/") {
33
+ const folders = Object.keys(pagesPerFolder);
34
+
35
+ res.statusCode = 200;
36
+ res.setHeader("Content-Type", "text/html; charset=utf-8");
37
+ res.end(`${folders.map(folder => {
38
+ const pages = pagesPerFolder[folder];
39
+ return `<h1>${folder}</h1>
40
+ ${pages.map(page => {
41
+ return `<li><a href='${folder}/${page}'>${page}</a></li>`
42
+ }).join("")}
43
+ `
44
+ }).join("")}`);
45
+ } else {
46
+ next();
47
+ }
48
+ })
49
+ },
50
+ }
51
+ };
52
+
53
+ module.exports = virtualIndexPlugin;
@@ -0,0 +1,58 @@
1
+ const esprima = require("esprima");
2
+ const escodegen = require("escodegen");
3
+
4
+ const fs = require("fs").promises;
5
+ const path = require("path");
6
+ const basePath = process.argv[2];
7
+
8
+ const convertImports = async (srcPath) => {
9
+ let changed = false;
10
+ // console.log("scanning imports of", srcPath);
11
+ let code = (await fs.readFile(srcPath)).toString();
12
+ const tree = esprima.parseModule(code);
13
+ const importer = srcPath.replace(basePath, "");
14
+ const importerDir = path.dirname(importer);
15
+ // console.log("-> ", importer);
16
+ tree.body.forEach(node => {
17
+ if (node.type === "ImportDeclaration") {
18
+ let importee = node.source.value;
19
+ if (importee.startsWith(".")) {
20
+ // add .js extension if missing
21
+ if (!importee.endsWith(".js")) {
22
+ node.source.value += ".js"
23
+ changed = true;
24
+ }
25
+ return;
26
+ }
27
+ let importeeDir = path.dirname(importee);
28
+ let importeeFile = path.basename(importee);
29
+ let relativePath = path.relative(importerDir, importeeDir);
30
+ if (relativePath.length === 0) {
31
+ relativePath = "."
32
+ }
33
+ if (!relativePath.startsWith(".")) {
34
+ relativePath = "./" + relativePath;
35
+ }
36
+
37
+ relativePath = relativePath.replace(/\\/g, "/"); // the browser expects unix paths
38
+ let relativeImport = `${relativePath}/${importeeFile}.js`;
39
+ // console.log(importee + " --> " + relativeImport);
40
+ node.source.value = relativeImport;
41
+ changed = true;
42
+ }
43
+ });
44
+
45
+ if (changed) {
46
+ return fs.writeFile(srcPath, escodegen.generate(tree));
47
+ }
48
+ }
49
+
50
+ const generate = async () => {
51
+ const { globby } = await import("globby");
52
+ const fileNames = await globby(basePath + "**/*.js");
53
+ return Promise.all(fileNames.map(convertImports).filter(x => !!x));
54
+ };
55
+
56
+ generate().then(() => {
57
+ console.log("Success: Converted absolute imports to relative for files in:", basePath);
58
+ });