@ui5/webcomponents-tools 2.0.0-rc.5 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,35 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [2.0.0](https://github.com/SAP/ui5-webcomponents/compare/v2.0.0-rc.6...v2.0.0) (2024-07-03)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * template result comparison ([#9279](https://github.com/SAP/ui5-webcomponents/issues/9279)) ([3a02e3e](https://github.com/SAP/ui5-webcomponents/commit/3a02e3ec51ade59a9bdd27784a7be5a1229ef24f))
12
+
13
+
14
+ ### Features
15
+
16
+ * add property initializers ([#8846](https://github.com/SAP/ui5-webcomponents/issues/8846)) ([eef0cc9](https://github.com/SAP/ui5-webcomponents/commit/eef0cc9b663fda6268b98e516ed46439435fa2b0))
17
+
18
+
19
+ ### BREAKING CHANGES
20
+
21
+ * @property decorator must be adapted according to new type parameter
22
+
23
+
24
+
25
+
26
+
27
+ # [2.0.0-rc.6](https://github.com/SAP/ui5-webcomponents/compare/v2.0.0-rc.5...v2.0.0-rc.6) (2024-06-17)
28
+
29
+ **Note:** Version bump only for package @ui5/webcomponents-tools
30
+
31
+
32
+
33
+
34
+
6
35
  # [2.0.0-rc.5](https://github.com/SAP/ui5-webcomponents/compare/v2.0.0-rc.4...v2.0.0-rc.5) (2024-06-06)
7
36
 
8
37
  **Note:** Version bump only for package @ui5/webcomponents-tools
package/README.md CHANGED
@@ -1,7 +1,4 @@
1
- ![UI5 icon](https://raw.githubusercontent.com/SAP/ui5-webcomponents/main/docs/images/UI5_logo_wide.png)
2
-
3
-
4
- # UI5 Web Components - Tools
1
+ # ![UI5 icon](https://raw.githubusercontent.com/SAP/ui5-webcomponents/main/docs/images/UI5_logo_water.png)UI5 Web Components - Tools
5
2
 
6
3
  [![npm Package Version](https://badge.fury.io/js/%40ui5%2Fwebcomponents.svg)](https://www.npmjs.com/package/@ui5/webcomponents)
7
4
 
@@ -0,0 +1,39 @@
1
+ /// <reference types="cypress" />
2
+ // ***********************************************
3
+ // This example commands.ts shows you how to
4
+ // create various custom commands and overwrite
5
+ // existing commands.
6
+ //
7
+ // For more comprehensive examples of custom
8
+ // commands please read more here:
9
+ // https://on.cypress.io/custom-commands
10
+ // ***********************************************
11
+ //
12
+ //
13
+ // -- This is a parent command --
14
+ // Cypress.Commands.add('login', (email, password) => { ... })
15
+ //
16
+ //
17
+ // -- This is a child command --
18
+ // Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
19
+ //
20
+ //
21
+ // -- This is a dual command --
22
+ // Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
23
+ //
24
+ //
25
+ // -- This will overwrite an existing command --
26
+ // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
27
+ //
28
+ // declare global {
29
+ // namespace Cypress {
30
+ // interface Chainable {
31
+ // login(email: string, password: string): Chainable<void>
32
+ // drag(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
33
+ // dismiss(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
34
+ // visit(originalFn: CommandOriginalFn, url: string, options: Partial<VisitOptions>): Chainable<Element>
35
+ // }
36
+ // }
37
+ // }
38
+
39
+ import "cypress-real-events";
@@ -0,0 +1,16 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+
4
+ <head>
5
+ <meta charset="utf-8">
6
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
7
+ <meta name="viewport" content="width=device-width,initial-scale=1.0">
8
+ <title>Components App</title>
9
+ <script data-ui5-config type="application/json">{}</script>
10
+ </head>
11
+
12
+ <body>
13
+ <div data-cy-root></div>
14
+ </body>
15
+
16
+ </html>
@@ -0,0 +1,4 @@
1
+ import { mount } from 'cypress-ct-lit'
2
+ import "./commands.js";
3
+
4
+ Cypress.Commands.add('mount', mount)
@@ -0,0 +1,19 @@
1
+ const { defineConfig } = require('cypress')
2
+ const path = require("path");
3
+ const rootConfig = require("../../../vite.config.js");
4
+
5
+ module.exports = defineConfig({
6
+ component: {
7
+ supportFile: path.join(__dirname, "cypress/support/component.js"),
8
+ indexHtmlFile: path.join(__dirname, "cypress/support/component-index.html"),
9
+ specPattern: "test/specs/*.cy.js",
10
+ devServer: {
11
+ framework: 'cypress-ct-lit',
12
+ bundler: 'vite',
13
+ viteConfig: rootConfig,
14
+ }
15
+ },
16
+ video: false,
17
+ screenshotOnRunFailure: false,
18
+ scrollBehavior: false
19
+ })
@@ -19,6 +19,7 @@ const overrides = tsMode ? [{
19
19
  },
20
20
  rules: {
21
21
  "no-shadow": "off",
22
+ "@typescript-eslint/consistent-type-imports": "error",
22
23
  "@typescript-eslint/no-shadow": ["error"],
23
24
  "@typescript-eslint/no-unsafe-member-access": "off",
24
25
  "@typescript-eslint/no-floating-promises": "off",
@@ -77,10 +77,9 @@ const getScripts = (options) => {
77
77
  default: "nps prepare lint build.bundle", // build.bundle2
78
78
  templates: `mkdirp src/generated/templates && ${tsCrossEnv} node "${LIB}/hbs2ui5/index.js" -d src/ -o src/generated/templates`,
79
79
  styles: {
80
- default: `concurrently "nps build.styles.themes" "nps build.styles.components" "nps build.styles.componentStyles"`,
80
+ default: `concurrently "nps build.styles.themes" "nps build.styles.components"`,
81
81
  themes: `node "${LIB}/css-processors/css-processor-themes.mjs"`,
82
82
  components: `node "${LIB}/css-processors/css-processor-components.mjs"`,
83
- componentStyles: `node "${LIB}/css-processors/css-processor-component-styles.mjs"`,
84
83
  },
85
84
  i18n: {
86
85
  default: "nps build.i18n.defaultsjs build.i18n.json",
@@ -114,16 +113,17 @@ const getScripts = (options) => {
114
113
  props: 'nps "copy.props --watch --safe --skip-initial-copy"',
115
114
  bundle: `node ${LIB}/dev-server/dev-server.js ${viteConfig}`,
116
115
  styles: {
117
- default: 'concurrently "nps watch.styles.themes" "nps watch.styles.components" "nps watch.styles.componentStyles" ',
116
+ default: 'concurrently "nps watch.styles.themes" "nps watch.styles.components"',
118
117
  themes: 'nps "build.styles.themes -w"',
119
118
  components: `nps "build.styles.components -w"`,
120
- componentStyles: `nps "build.styles.componentStyles -w"`,
121
119
  },
122
120
  templates: 'chokidar "src/**/*.hbs" -c "nps build.templates"',
123
121
  i18n: 'chokidar "src/i18n/messagebundle.properties" -c "nps build.i18n.defaultsjs"'
124
122
  },
125
123
  start: "nps prepare watch.devServer",
126
124
  test: `node "${LIB}/test-runner/test-runner.js"`,
125
+ "test-cy-ci": `yarn cypress run --component --browser chrome --config-file config/cypress.config.js`,
126
+ "test-cy-open": `yarn cypress open --component --browser chrome --config-file config/cypress.config.js`,
127
127
  "test-suite-1": `node "${LIB}/test-runner/test-runner.js" --suite suite1`,
128
128
  "test-suite-2": `node "${LIB}/test-runner/test-runner.js" --suite suite2`,
129
129
  startWithScope: "nps scope.prepare scope.watchWithBundle",
@@ -4,6 +4,7 @@ import path from "path";
4
4
  import fs from 'fs';
5
5
  import {
6
6
  getDeprecatedStatus,
7
+ getExperimentalStatus,
7
8
  getSinceStatus,
8
9
  getPrivacyStatus,
9
10
  getReference,
@@ -64,12 +65,23 @@ function processClass(ts, classNode, moduleDoc) {
64
65
  currClass.customElement = !!customElementDecorator || className === "UI5Element" || undefined;
65
66
  currClass.kind = "class";
66
67
  currClass.deprecated = getDeprecatedStatus(classParsedJsDoc);
68
+ currClass._ui5experimental = getExperimentalStatus(classParsedJsDoc);
67
69
  currClass._ui5since = getSinceStatus(classParsedJsDoc);
68
70
  currClass._ui5privacy = getPrivacyStatus(classParsedJsDoc);
69
71
  currClass._ui5abstract = hasTag(classParsedJsDoc, "abstract") ? true : undefined;
70
72
  currClass.description = normalizeDescription(classParsedJsDoc.description || findTag(classParsedJsDoc, "class")?.description);
71
73
  currClass._ui5implements = findAllTags(classParsedJsDoc, "implements")
72
- .map(tag => getReference(ts, normalizeTagType(tag.type), classNode, moduleDoc.path))
74
+ .map(tag => {
75
+ const correctInterfaceDescription = classNode?.heritageClauses?.some(heritageClause => {
76
+ return heritageClause?.types?.some(type => type.expression?.text === normalizeTagType(tag.type));
77
+ });
78
+
79
+ if (!correctInterfaceDescription) {
80
+ logDocumentationError(moduleDoc.path, `@interface {${tag.type}} tag is used, but the class doesn't implement the corresponding interface`)
81
+ }
82
+
83
+ return getReference(ts, normalizeTagType(tag.type), classNode, moduleDoc.path)
84
+ })
73
85
  .filter(Boolean);
74
86
 
75
87
 
@@ -77,6 +89,10 @@ function processClass(ts, classNode, moduleDoc) {
77
89
  const superclassTag = findTag(classParsedJsDoc, "extends");
78
90
  currClass.superclass = getReference(ts, superclassTag.name, classNode, moduleDoc.path);
79
91
 
92
+ if (classNode?.heritageClauses?.[0]?.types?.[0]?.expression?.text !== superclassTag.name) {
93
+ logDocumentationError(moduleDoc.path, `@extends ${superclassTag.name} is used, but the class doesn't extend the corresponding superclass`)
94
+ }
95
+
80
96
  if (currClass.superclass?.name === "UI5Element") {
81
97
  currClass.customElement = true;
82
98
  }
@@ -179,6 +195,9 @@ function processClass(ts, classNode, moduleDoc) {
179
195
  const tsProgramMember = tsProgramClassNode.members.find(m => ts.isPropertyDeclaration(m) && m.name?.text === member.name);
180
196
  const attributeValue = typeChecker.typeToString(typeChecker.getTypeAtLocation(tsProgramMember), tsProgramMember);
181
197
 
198
+ if (attributeValue === "boolean" && member.default === "true") {
199
+ logDocumentationError(moduleDoc.path, `Boolean properties must be initialzed to false. [${member.name}] property of class [${className}] is intialized to \`true\``)
200
+ }
182
201
  currClass.attributes.push({
183
202
  description: member.description,
184
203
  name: toKebabCase(member.name),
@@ -293,6 +312,7 @@ function processInterface(ts, interfaceNode, moduleDoc) {
293
312
  kind: "interface",
294
313
  name: interfaceName,
295
314
  description: normalizeDescription(interfaceParsedJsDoc?.description),
315
+ _ui5experimental: getExperimentalStatus(interfaceParsedJsDoc),
296
316
  _ui5privacy: getPrivacyStatus(interfaceParsedJsDoc),
297
317
  _ui5since: getSinceStatus(interfaceParsedJsDoc),
298
318
  deprecated: getDeprecatedStatus(interfaceParsedJsDoc),
@@ -313,6 +333,7 @@ function processEnum(ts, enumNode, moduleDoc) {
313
333
  kind: "enum",
314
334
  name: enumName,
315
335
  description: normalizeDescription(enumJSdoc?.comment),
336
+ _ui5experimental: getExperimentalStatus(enumParsedJsDoc),
316
337
  _ui5privacy: getPrivacyStatus(enumParsedJsDoc),
317
338
  _ui5since: getSinceStatus(enumParsedJsDoc),
318
339
  deprecated: getDeprecatedStatus(enumParsedJsDoc) || undefined,
@@ -46,6 +46,12 @@
46
46
  "ClassDeclaration": {
47
47
  "additionalProperties": false,
48
48
  "properties": {
49
+ "_ui5experimental": {
50
+ "type": [
51
+ "string",
52
+ "boolean"
53
+ ]
54
+ },
49
55
  "_ui5package": {
50
56
  "type": "string"
51
57
  },
@@ -123,6 +129,12 @@
123
129
  "EnumDeclaration": {
124
130
  "additionalProperties": false,
125
131
  "properties": {
132
+ "_ui5experimental": {
133
+ "type": [
134
+ "string",
135
+ "boolean"
136
+ ]
137
+ },
126
138
  "_ui5package": {
127
139
  "type": "string"
128
140
  },
@@ -187,6 +199,12 @@
187
199
  "InterfaceDeclaration": {
188
200
  "additionalProperties": false,
189
201
  "properties": {
202
+ "_ui5experimental": {
203
+ "type": [
204
+ "string",
205
+ "boolean"
206
+ ]
207
+ },
190
208
  "_ui5package": {
191
209
  "type": "string"
192
210
  },
@@ -453,6 +471,12 @@
453
471
  "additionalProperties": false,
454
472
  "description": "A description of a custom element class.\n\nCustom elements are JavaScript classes, so this extends from\n`ClassDeclaration` and adds custom-element-specific features like\nattributes, events, and slots.\n\nNote that `tagName` in this interface is optional. Tag names are not\nneccessarily part of a custom element class, but belong to the definition\n(often called the \"registration\") or the `customElements.define()` call.\n\nBecause classes and tag names can only be registered once, there's a\none-to-one relationship between classes and tag names. For ease of use,\nwe allow the tag name here.\n\nSome packages define and register custom elements in separate modules. In\nthese cases one `Module` should contain the `CustomElement` without a\ntagName, and another `Module` should contain the\n`CustomElementExport`.",
455
473
  "properties": {
474
+ "_ui5experimental": {
475
+ "type": [
476
+ "string",
477
+ "boolean"
478
+ ]
479
+ },
456
480
  "_ui5package": {
457
481
  "type": "string"
458
482
  },
@@ -618,6 +642,12 @@
618
642
  "additionalProperties": false,
619
643
  "description": "A class mixin that also adds custom element related properties.",
620
644
  "properties": {
645
+ "_ui5experimental": {
646
+ "type": [
647
+ "string",
648
+ "boolean"
649
+ ]
650
+ },
621
651
  "_ui5package": {
622
652
  "type": "string"
623
653
  },
@@ -827,6 +857,12 @@
827
857
  "FunctionDeclaration": {
828
858
  "additionalProperties": false,
829
859
  "properties": {
860
+ "_ui5experimental": {
861
+ "type": [
862
+ "string",
863
+ "boolean"
864
+ ]
865
+ },
830
866
  "_ui5package": {
831
867
  "type": "string"
832
868
  },
@@ -1007,6 +1043,12 @@
1007
1043
  "additionalProperties": false,
1008
1044
  "description": "A description of a class mixin.\n\nMixins are functions which generate a new subclass of a given superclass.\nThis interfaces describes the class and custom element features that\nare added by the mixin. As such, it extends the CustomElement interface and\nClassLike interface.\n\nSince mixins are functions, it also extends the FunctionLike interface. This\nmeans a mixin is callable, and has parameters and a return type.\n\nThe return type is often hard or impossible to accurately describe in type\nsystems like TypeScript. It requires generics and an `extends` operator\nthat TypeScript lacks. Therefore it's recommended that the return type is\nleft empty. The most common form of a mixin function takes a single\nargument, so consumers of this interface should assume that the return type\nis the single argument subclassed by this declaration.\n\nA mixin should not have a superclass. If a mixins composes other mixins,\nthey should be listed in the `mixins` field.\n\nSee [this article]{@link https://justinfagnani.com/2015/12/21/real-mixins-with-javascript-classes/}\nfor more information on the classmixin pattern in JavaScript.",
1009
1045
  "properties": {
1046
+ "_ui5experimental": {
1047
+ "type": [
1048
+ "string",
1049
+ "boolean"
1050
+ ]
1051
+ },
1010
1052
  "_ui5package": {
1011
1053
  "type": "string"
1012
1054
  },
@@ -1275,6 +1317,12 @@
1275
1317
  "VariableDeclaration": {
1276
1318
  "additionalProperties": false,
1277
1319
  "properties": {
1320
+ "_ui5experimental": {
1321
+ "type": [
1322
+ "string",
1323
+ "boolean"
1324
+ ]
1325
+ },
1278
1326
  "_ui5package": {
1279
1327
  "type": "string"
1280
1328
  },
@@ -484,6 +484,7 @@ export interface TypeReference extends Reference {
484
484
  * The common interface of classes and mixins.
485
485
  */
486
486
  export interface ClassLike {
487
+ _ui5experimental?: boolean | string
487
488
  _ui5implements?: Reference[]
488
489
  _ui5privacy?: Privacy
489
490
  /**
package/lib/cem/utils.mjs CHANGED
@@ -14,6 +14,17 @@ const getDeprecatedStatus = (jsdocComment) => {
14
14
  : undefined;
15
15
  };
16
16
 
17
+ const getExperimentalStatus = (jsdocComment) => {
18
+ const experimentalTag = findTag(jsdocComment, "experimental");
19
+ return experimentalTag?.name
20
+ ? experimentalTag.description
21
+ ? `${experimentalTag.name} ${experimentalTag.description}`
22
+ : experimentalTag.name
23
+ : experimentalTag
24
+ ? true
25
+ : undefined;
26
+ };
27
+
17
28
  const toKebabCase = str => {
18
29
  return str.replaceAll(/[A-Z]+(?![a-z])|[A-Z]/g, ($, ofs) => (ofs ? "-" : "") + $.toLowerCase())
19
30
  }
@@ -214,10 +225,10 @@ const allowedTags = {
214
225
  event: [...commonTags, "param", "allowPreventDefault", "native"],
215
226
  eventParam: [...commonTags],
216
227
  method: [...commonTags, "param", "returns", "override"],
217
- class: [...commonTags, "constructor", "class", "abstract", "implements", "extends", "slot", "csspart"],
228
+ class: [...commonTags, "constructor", "class", "abstract", "experimental", "implements", "extends", "slot", "csspart"],
218
229
  enum: [...commonTags],
219
- enumMember: [...commonTags],
220
- interface: [...commonTags],
230
+ enumMember: [...commonTags, "experimental",],
231
+ interface: [...commonTags, "experimental",],
221
232
  };
222
233
  allowedTags.getter = [...allowedTags.field, "override"]
223
234
 
@@ -284,6 +295,8 @@ const validateJSDocTag = (tag) => {
284
295
  return !tag.name && !tag.type && !tag.description;
285
296
  case "deprecated":
286
297
  return !tag.type;
298
+ case "experimental":
299
+ return !tag.type;
287
300
  case "extends":
288
301
  return !tag.type && tag.name && !tag.description;
289
302
  case "implements":
@@ -365,6 +378,7 @@ export {
365
378
  getPrivacyStatus,
366
379
  getSinceStatus,
367
380
  getDeprecatedStatus,
381
+ getExperimentalStatus,
368
382
  getType,
369
383
  getReference,
370
384
  validateJSDocComment,
@@ -1,7 +1,5 @@
1
1
  const fs = require("fs");
2
- const path = require("path");
3
2
  const prompts = require("prompts");
4
- const jsFileContentTemplate = require("./jsFileContentTemplate.js");
5
3
  const tsFileContentTemplate = require("./tsFileContentTemplate.js");
6
4
 
7
5
  /**
@@ -51,7 +51,7 @@ class ${componentName} extends UI5Element {
51
51
  * @public
52
52
  */
53
53
  @property()
54
- value!: string;
54
+ value?: string;
55
55
 
56
56
  /**
57
57
  * Defines the text of the component.
@@ -36,7 +36,7 @@ const processFile = async (file, outputDir) => {
36
36
  const componentNameMatcher = /(\w+)(\.hbs)/gim;
37
37
  const componentName = componentNameMatcher.exec(file)[1];
38
38
  const componentHasTypes = hasTypes(file, componentName);
39
- if (!componentHasTypes) {
39
+ if (!componentHasTypes) {
40
40
  if (!missingTypesReported) {
41
41
  console.warn("[Warn] The following templates do not have a corresponging .ts or .d.ts file and won't be type checked:")
42
42
  missingTypesReported = true;
@@ -98,7 +98,7 @@ const writeRenderers = async (outputDir, controlName, fileContent) => {
98
98
 
99
99
  let existingFileContent = "";
100
100
  try {
101
- existingFileContent = await fs.readFile(compiledFilePath);
101
+ existingFileContent = (await fs.readFile(compiledFilePath)).toString();
102
102
  } catch (e) {}
103
103
 
104
104
  if (existingFileContent !== fileContentUnix) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ui5/webcomponents-tools",
3
- "version": "2.0.0-rc.5",
3
+ "version": "2.0.0",
4
4
  "description": "UI5 Web Components: webcomponents.tools",
5
5
  "author": "SAP SE (https://www.sap.com)",
6
6
  "license": "Apache-2.0",
@@ -34,13 +34,15 @@
34
34
  "cem-plugin-vs-code-custom-data-generator": "^1.4.2",
35
35
  "chai": "^4.3.4",
36
36
  "child_process": "^1.0.2",
37
- "chokidar": "^3.5.1",
37
+ "chokidar": "^3.6.0",
38
38
  "chokidar-cli": "^3.0.0",
39
39
  "command-line-args": "^5.1.1",
40
40
  "comment-parser": "^1.4.0",
41
41
  "concurrently": "^6.0.0",
42
42
  "cross-env": "^7.0.3",
43
43
  "custom-element-jet-brains-integration": "^1.4.4",
44
+ "cypress": "^13.11.0",
45
+ "cypress-real-events": "^1.12.0",
44
46
  "escodegen": "^2.0.0",
45
47
  "eslint": "^7.22.0",
46
48
  "eslint-config-airbnb-base": "^14.2.1",
@@ -69,7 +71,7 @@
69
71
  },
70
72
  "peerDependencies": {
71
73
  "chromedriver": "*",
72
- "typescript": "^4.9.4"
74
+ "typescript": "^5.2.2"
73
75
  },
74
76
  "peerDependenciesMeta": {
75
77
  "typescript": {
@@ -77,8 +79,10 @@
77
79
  }
78
80
  },
79
81
  "devDependencies": {
82
+ "cypress-ct-lit": "^0.4.0",
83
+ "cypress-real-events": "^1.12.0",
80
84
  "esbuild": "^0.19.9",
81
85
  "yargs": "^17.5.1"
82
86
  },
83
- "gitHead": "791653e253faae4847f026d022d0ddcd47a96666"
87
+ "gitHead": "2960694d66c4b62d4240e3d45e1401dd94f61aec"
84
88
  }
@@ -1,48 +0,0 @@
1
- import { globby } from "globby";
2
- import * as esbuild from 'esbuild'
3
- import * as fs from "fs";
4
- import * as path from "path";
5
- import { writeFile, mkdir } from "fs/promises";
6
- import scopeVariables from "./scope-variables.mjs";
7
-
8
- const packageJSON = JSON.parse(fs.readFileSync("./package.json"))
9
- const inputFiles = await globby("src/styles/*.module.css");
10
- const restArgs = process.argv.slice(2);
11
-
12
- let componentStylesPlugin = {
13
- name: 'component-styles',
14
- setup(build) {
15
- build.initialOptions.write = false;
16
-
17
- build.onEnd(result => {
18
- result.outputFiles.forEach(async f => {
19
- // scoping
20
- const newText = scopeVariables(f.text, packageJSON);
21
- await mkdir(path.dirname(f.path), {recursive: true});
22
- writeFile(f.path, newText);
23
- writeFile(f.path.replace(".module.css", ".css"), newText);
24
- });
25
- })
26
- },
27
- }
28
-
29
- const config = {
30
- entryPoints: inputFiles,
31
- outdir: 'dist',
32
- bundle: true,
33
- outbase: 'src',
34
- loader: {
35
- ".module.css": "global-css"
36
- },
37
- plugins: [
38
- componentStylesPlugin,
39
- ]
40
- };
41
-
42
- if (restArgs.includes("-w")) {
43
- let ctx = await esbuild.context(config);
44
- await ctx.watch()
45
- console.log('watching...')
46
- } else {
47
- await esbuild.build(config);
48
- }