@angular-devkit/build-angular 15.0.0 → 15.0.2

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/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@angular-devkit/build-angular",
3
- "version": "15.0.0",
3
+ "version": "15.0.2",
4
4
  "description": "Angular Webpack Build Facade",
5
5
  "main": "src/index.js",
6
6
  "typings": "src/index.d.ts",
7
7
  "builders": "builders.json",
8
8
  "dependencies": {
9
9
  "@ampproject/remapping": "2.2.0",
10
- "@angular-devkit/architect": "0.1500.0",
11
- "@angular-devkit/build-webpack": "0.1500.0",
12
- "@angular-devkit/core": "15.0.0",
10
+ "@angular-devkit/architect": "0.1500.2",
11
+ "@angular-devkit/build-webpack": "0.1500.2",
12
+ "@angular-devkit/core": "15.0.2",
13
13
  "@babel/core": "7.20.2",
14
14
  "@babel/generator": "7.20.4",
15
15
  "@babel/helper-annotate-as-pure": "7.18.6",
@@ -20,7 +20,7 @@
20
20
  "@babel/runtime": "7.20.1",
21
21
  "@babel/template": "7.18.10",
22
22
  "@discoveryjs/json-ext": "0.5.7",
23
- "@ngtools/webpack": "15.0.0",
23
+ "@ngtools/webpack": "15.0.2",
24
24
  "ansi-colors": "4.1.3",
25
25
  "autoprefixer": "10.4.13",
26
26
  "babel-loader": "9.1.0",
@@ -49,7 +49,6 @@
49
49
  "piscina": "3.2.0",
50
50
  "postcss": "8.4.19",
51
51
  "postcss-loader": "7.0.1",
52
- "regenerator-runtime": "0.13.10",
53
52
  "resolve-url-loader": "5.0.0",
54
53
  "rxjs": "6.6.7",
55
54
  "sass": "1.56.1",
@@ -25,6 +25,27 @@ function createSassPlugin(options) {
25
25
  return {
26
26
  name: 'angular-sass',
27
27
  setup(build) {
28
+ const resolveUrl = async (url, previousResolvedModules) => {
29
+ let result = await build.resolve(url, {
30
+ kind: 'import-rule',
31
+ // This should ideally be the directory of the importer file from Sass
32
+ // but that is not currently available from the Sass importer API.
33
+ resolveDir: build.initialOptions.absWorkingDir,
34
+ });
35
+ // Workaround to support Yarn PnP without access to the importer file from Sass
36
+ if (!result.path && (previousResolvedModules === null || previousResolvedModules === void 0 ? void 0 : previousResolvedModules.size)) {
37
+ for (const previous of previousResolvedModules) {
38
+ result = await build.resolve(url, {
39
+ kind: 'import-rule',
40
+ resolveDir: previous,
41
+ });
42
+ if (result.path) {
43
+ break;
44
+ }
45
+ }
46
+ }
47
+ return result;
48
+ };
28
49
  build.onLoad({ filter: /\.s[ac]ss$/ }, async (args) => {
29
50
  // Lazily load Sass when a Sass file is found
30
51
  sassWorkerPool !== null && sassWorkerPool !== void 0 ? sassWorkerPool : (sassWorkerPool = new sass_service_1.SassWorkerImplementation(true));
@@ -41,39 +62,18 @@ function createSassPlugin(options) {
41
62
  importers: [
42
63
  {
43
64
  findFileUrl: async (url, { previousResolvedModules }) => {
44
- let result = await build.resolve(url, {
45
- kind: 'import-rule',
46
- // This should ideally be the directory of the importer file from Sass
47
- // but that is not currently available from the Sass importer API.
48
- resolveDir: build.initialOptions.absWorkingDir,
49
- });
50
- // Workaround to support Yarn PnP without access to the importer file from Sass
51
- if (!result.path && (previousResolvedModules === null || previousResolvedModules === void 0 ? void 0 : previousResolvedModules.size)) {
52
- for (const previous of previousResolvedModules) {
53
- result = await build.resolve(url, {
54
- kind: 'import-rule',
55
- resolveDir: previous,
56
- });
57
- }
58
- }
65
+ const result = await resolveUrl(url, previousResolvedModules);
59
66
  // Check for package deep imports
60
67
  if (!result.path) {
61
68
  const parts = url.split('/');
62
- const hasScope = parts.length > 2 && parts[0].startsWith('@');
63
- if (hasScope || parts.length > 1) {
64
- const [nameOrScope, nameOrFirstPath, ...pathPart] = parts;
65
- const packageName = hasScope
66
- ? `${nameOrScope}/${nameOrFirstPath}`
67
- : nameOrScope;
68
- const packageResult = await build.resolve(packageName + '/package.json', {
69
- kind: 'import-rule',
70
- // This should ideally be the directory of the importer file from Sass
71
- // but that is not currently available from the Sass importer API.
72
- resolveDir: build.initialOptions.absWorkingDir,
73
- });
74
- if (packageResult.path) {
75
- return (0, node_url_1.pathToFileURL)((0, node_path_1.join)((0, node_path_1.dirname)(packageResult.path), !hasScope ? nameOrFirstPath : '', ...pathPart));
76
- }
69
+ const hasScope = parts.length >= 2 && parts[0].startsWith('@');
70
+ const [nameOrScope, nameOrFirstPath, ...pathPart] = parts;
71
+ const packageName = hasScope
72
+ ? `${nameOrScope}/${nameOrFirstPath}`
73
+ : nameOrScope;
74
+ const packageResult = await resolveUrl(packageName + '/package.json', previousResolvedModules);
75
+ if (packageResult.path) {
76
+ return (0, node_url_1.pathToFileURL)((0, node_path_1.join)((0, node_path_1.dirname)(packageResult.path), !hasScope ? nameOrFirstPath : '', ...pathPart));
77
77
  }
78
78
  }
79
79
  return result.path ? (0, node_url_1.pathToFileURL)(result.path) : null;
@@ -15,11 +15,6 @@ const magic_string_1 = __importDefault(require("magic-string"));
15
15
  const node_fs_1 = require("node:fs");
16
16
  const node_path_1 = require("node:path");
17
17
  const node_url_1 = require("node:url");
18
- /**
19
- * A Regular expression used to find all `url()` functions within a stylesheet.
20
- * From packages/angular_devkit/build_angular/src/webpack/plugins/postcss-cli-resources.ts
21
- */
22
- const URL_REGEXP = /url(?:\(\s*(['"]?))(.*?)(?:\1\s*\))/g;
23
18
  /**
24
19
  * A Sass Importer base class that provides the load logic to rebase all `url()` functions
25
20
  * within a stylesheet. The rebasing will ensure that the URLs in the output of the Sass compiler
@@ -43,37 +38,36 @@ class UrlRebasingImporter {
43
38
  }
44
39
  load(canonicalUrl) {
45
40
  const stylesheetPath = (0, node_url_1.fileURLToPath)(canonicalUrl);
41
+ const stylesheetDirectory = (0, node_path_1.dirname)(stylesheetPath);
46
42
  let contents = (0, node_fs_1.readFileSync)(stylesheetPath, 'utf-8');
47
43
  // Rebase any URLs that are found
48
- if (contents.includes('url(')) {
49
- const stylesheetDirectory = (0, node_path_1.dirname)(stylesheetPath);
50
- let match;
51
- URL_REGEXP.lastIndex = 0;
52
- let updatedContents;
53
- while ((match = URL_REGEXP.exec(contents))) {
54
- const originalUrl = match[2];
55
- // If root-relative, absolute or protocol relative url, leave as-is
56
- if (/^((?:\w+:)?\/\/|data:|chrome:|#|\/)/.test(originalUrl)) {
57
- continue;
58
- }
59
- const rebasedPath = (0, node_path_1.relative)(this.entryDirectory, (0, node_path_1.join)(stylesheetDirectory, originalUrl));
60
- // Normalize path separators and escape characters
61
- // https://developer.mozilla.org/en-US/docs/Web/CSS/url#syntax
62
- const rebasedUrl = './' + rebasedPath.replace(/\\/g, '/').replace(/[()\s'"]/g, '\\$&');
63
- updatedContents !== null && updatedContents !== void 0 ? updatedContents : (updatedContents = new magic_string_1.default(contents));
64
- updatedContents.update(match.index, match.index + match[0].length, `url(${rebasedUrl})`);
44
+ let updatedContents;
45
+ for (const { start, end, value } of findUrls(contents)) {
46
+ // Skip if value is empty or a Sass variable
47
+ if (value.length === 0 || value.startsWith('$')) {
48
+ continue;
65
49
  }
66
- if (updatedContents) {
67
- contents = updatedContents.toString();
68
- if (this.rebaseSourceMaps) {
69
- // Generate an intermediate source map for the rebasing changes
70
- const map = updatedContents.generateMap({
71
- hires: true,
72
- includeContent: true,
73
- source: canonicalUrl.href,
74
- });
75
- this.rebaseSourceMaps.set(canonicalUrl.href, map);
76
- }
50
+ // Skip if root-relative, absolute or protocol relative url
51
+ if (/^((?:\w+:)?\/\/|data:|chrome:|#|\/)/.test(value)) {
52
+ continue;
53
+ }
54
+ const rebasedPath = (0, node_path_1.relative)(this.entryDirectory, (0, node_path_1.join)(stylesheetDirectory, value));
55
+ // Normalize path separators and escape characters
56
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/url#syntax
57
+ const rebasedUrl = './' + rebasedPath.replace(/\\/g, '/').replace(/[()\s'"]/g, '\\$&');
58
+ updatedContents !== null && updatedContents !== void 0 ? updatedContents : (updatedContents = new magic_string_1.default(contents));
59
+ updatedContents.update(start, end, rebasedUrl);
60
+ }
61
+ if (updatedContents) {
62
+ contents = updatedContents.toString();
63
+ if (this.rebaseSourceMaps) {
64
+ // Generate an intermediate source map for the rebasing changes
65
+ const map = updatedContents.generateMap({
66
+ hires: true,
67
+ includeContent: true,
68
+ source: canonicalUrl.href,
69
+ });
70
+ this.rebaseSourceMaps.set(canonicalUrl.href, map);
77
71
  }
78
72
  }
79
73
  let syntax;
@@ -95,6 +89,156 @@ class UrlRebasingImporter {
95
89
  };
96
90
  }
97
91
  }
92
+ /**
93
+ * Determines if a unicode code point is a CSS whitespace character.
94
+ * @param code The unicode code point to test.
95
+ * @returns true, if the code point is CSS whitespace; false, otherwise.
96
+ */
97
+ function isWhitespace(code) {
98
+ // Based on https://www.w3.org/TR/css-syntax-3/#whitespace
99
+ switch (code) {
100
+ case 0x0009: // tab
101
+ case 0x0020: // space
102
+ case 0x000a: // line feed
103
+ case 0x000c: // form feed
104
+ case 0x000d: // carriage return
105
+ return true;
106
+ default:
107
+ return false;
108
+ }
109
+ }
110
+ /**
111
+ * Scans a CSS or Sass file and locates all valid url function values as defined by the CSS
112
+ * syntax specification.
113
+ * @param contents A string containing a CSS or Sass file to scan.
114
+ * @returns An iterable that yields each CSS url function value found.
115
+ */
116
+ function* findUrls(contents) {
117
+ let pos = 0;
118
+ let width = 1;
119
+ let current = -1;
120
+ const next = () => {
121
+ var _a;
122
+ pos += width;
123
+ current = (_a = contents.codePointAt(pos)) !== null && _a !== void 0 ? _a : -1;
124
+ width = current > 0xffff ? 2 : 1;
125
+ return current;
126
+ };
127
+ // Based on https://www.w3.org/TR/css-syntax-3/#consume-ident-like-token
128
+ while ((pos = contents.indexOf('url(', pos)) !== -1) {
129
+ // Set to position of the (
130
+ pos += 3;
131
+ width = 1;
132
+ // Consume all leading whitespace
133
+ while (isWhitespace(next())) {
134
+ /* empty */
135
+ }
136
+ // Initialize URL state
137
+ const url = { start: pos, end: -1, value: '' };
138
+ let complete = false;
139
+ // If " or ', then consume the value as a string
140
+ if (current === 0x0022 || current === 0x0027) {
141
+ const ending = current;
142
+ // Based on https://www.w3.org/TR/css-syntax-3/#consume-string-token
143
+ while (!complete) {
144
+ switch (next()) {
145
+ case -1: // EOF
146
+ return;
147
+ case 0x000a: // line feed
148
+ case 0x000c: // form feed
149
+ case 0x000d: // carriage return
150
+ // Invalid
151
+ complete = true;
152
+ break;
153
+ case 0x005c: // \ -- character escape
154
+ // If not EOF or newline, add the character after the escape
155
+ switch (next()) {
156
+ case -1:
157
+ return;
158
+ case 0x000a: // line feed
159
+ case 0x000c: // form feed
160
+ case 0x000d: // carriage return
161
+ // Skip when inside a string
162
+ break;
163
+ default:
164
+ // TODO: Handle hex escape codes
165
+ url.value += String.fromCodePoint(current);
166
+ break;
167
+ }
168
+ break;
169
+ case ending:
170
+ // Full string position should include the quotes for replacement
171
+ url.end = pos + 1;
172
+ complete = true;
173
+ yield url;
174
+ break;
175
+ default:
176
+ url.value += String.fromCodePoint(current);
177
+ break;
178
+ }
179
+ }
180
+ next();
181
+ continue;
182
+ }
183
+ // Based on https://www.w3.org/TR/css-syntax-3/#consume-url-token
184
+ while (!complete) {
185
+ switch (current) {
186
+ case -1: // EOF
187
+ return;
188
+ case 0x0022: // "
189
+ case 0x0027: // '
190
+ case 0x0028: // (
191
+ // Invalid
192
+ complete = true;
193
+ break;
194
+ case 0x0029: // )
195
+ // URL is valid and complete
196
+ url.end = pos;
197
+ complete = true;
198
+ break;
199
+ case 0x005c: // \ -- character escape
200
+ // If not EOF or newline, add the character after the escape
201
+ switch (next()) {
202
+ case -1: // EOF
203
+ return;
204
+ case 0x000a: // line feed
205
+ case 0x000c: // form feed
206
+ case 0x000d: // carriage return
207
+ // Invalid
208
+ complete = true;
209
+ break;
210
+ default:
211
+ // TODO: Handle hex escape codes
212
+ url.value += String.fromCodePoint(current);
213
+ break;
214
+ }
215
+ break;
216
+ default:
217
+ if (isWhitespace(current)) {
218
+ while (isWhitespace(next())) {
219
+ /* empty */
220
+ }
221
+ // Unescaped whitespace is only valid before the closing )
222
+ if (current === 0x0029) {
223
+ // URL is valid
224
+ url.end = pos;
225
+ }
226
+ complete = true;
227
+ }
228
+ else {
229
+ // Add the character to the url value
230
+ url.value += String.fromCodePoint(current);
231
+ }
232
+ break;
233
+ }
234
+ next();
235
+ }
236
+ // An end position indicates a URL was found
237
+ if (url.end !== -1) {
238
+ yield url;
239
+ }
240
+ }
241
+ }
98
242
  /**
99
243
  * Provides the Sass importer logic to resolve relative stylesheet imports via both import and use rules
100
244
  * and also rebase any `url()` function usage within those stylesheets. The rebasing will ensure that
@@ -211,7 +211,7 @@ function getStylesConfig(wco) {
211
211
  },
212
212
  {
213
213
  loader: require.resolve('sass-loader'),
214
- options: getSassLoaderOptions(root, sassImplementation, includePaths, false, !buildOptions.verbose, !!buildOptions.preserveSymlinks),
214
+ options: getSassLoaderOptions(root, sassImplementation, includePaths, false, !!buildOptions.verbose, !!buildOptions.preserveSymlinks),
215
215
  },
216
216
  ],
217
217
  },
@@ -226,7 +226,7 @@ function getStylesConfig(wco) {
226
226
  },
227
227
  {
228
228
  loader: require.resolve('sass-loader'),
229
- options: getSassLoaderOptions(root, sassImplementation, includePaths, true, !buildOptions.verbose, !!buildOptions.preserveSymlinks),
229
+ options: getSassLoaderOptions(root, sassImplementation, includePaths, true, !!buildOptions.verbose, !!buildOptions.preserveSymlinks),
230
230
  },
231
231
  ],
232
232
  },
@@ -279,7 +279,16 @@ function statsWarningsToString(json, statsConfig) {
279
279
  output += yb(`Warning: ${warning}\n\n`);
280
280
  }
281
281
  else {
282
- const file = warning.file || warning.moduleName;
282
+ let file = warning.file || warning.moduleName;
283
+ // Clean up warning paths
284
+ // Ex: ./src/app/styles.scss.webpack[javascript/auto]!=!./node_modules/css-loader/dist/cjs.js....
285
+ // to ./src/app/styles.scss.webpack
286
+ if (file && !statsConfig.errorDetails) {
287
+ const webpackPathIndex = file.indexOf('.webpack[');
288
+ if (webpackPathIndex !== -1) {
289
+ file = file.substring(0, webpackPathIndex);
290
+ }
291
+ }
283
292
  if (file) {
284
293
  output += c(file);
285
294
  if (warning.loc) {