@schematics/angular 20.2.0-next.2 → 20.2.0-rc.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.
Files changed (32) hide show
  1. package/ai-config/files/__rulesName__.template +49 -0
  2. package/ai-config/index.d.ts +10 -0
  3. package/ai-config/index.js +55 -0
  4. package/ai-config/schema.d.ts +21 -0
  5. package/ai-config/schema.js +15 -0
  6. package/ai-config/schema.json +39 -0
  7. package/application/index.js +26 -39
  8. package/collection.json +5 -0
  9. package/library/index.js +25 -40
  10. package/migrations/karma/karma-config-analyzer.d.ts +27 -0
  11. package/migrations/karma/karma-config-analyzer.js +131 -0
  12. package/migrations/karma/karma-config-comparer.d.ts +63 -0
  13. package/migrations/karma/karma-config-comparer.js +89 -0
  14. package/migrations/karma/migration.d.ts +9 -0
  15. package/migrations/karma/migration.js +62 -0
  16. package/migrations/migration-collection.json +5 -0
  17. package/migrations/replace-provide-server-rendering-import/migration.js +13 -48
  18. package/migrations/use-application-builder/migration.js +5 -142
  19. package/migrations/use-application-builder/stylesheet-updates.d.ts +36 -0
  20. package/migrations/use-application-builder/stylesheet-updates.js +219 -0
  21. package/ng-new/index.js +3 -0
  22. package/ng-new/schema.d.ts +14 -0
  23. package/ng-new/schema.js +11 -1
  24. package/ng-new/schema.json +10 -3
  25. package/package.json +4 -4
  26. package/service-worker/index.js +2 -2
  27. package/third_party/github.com/Microsoft/TypeScript/lib/typescript.js +1 -1
  28. package/utility/dependency.d.ts +47 -1
  29. package/utility/dependency.js +55 -0
  30. package/utility/latest-versions/package.json +1 -1
  31. package/utility/latest-versions.js +3 -3
  32. package/workspace/files/package.json.template +2 -0
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ /**
3
+ * @license
4
+ * Copyright Google LLC All Rights Reserved.
5
+ *
6
+ * Use of this source code is governed by an MIT-style license that can be
7
+ * found in the LICENSE file at https://angular.dev/license
8
+ */
9
+ var __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.generateDefaultKarmaConfig = generateDefaultKarmaConfig;
14
+ exports.compareKarmaConfigs = compareKarmaConfigs;
15
+ exports.hasDifferences = hasDifferences;
16
+ exports.compareKarmaConfigToDefault = compareKarmaConfigToDefault;
17
+ const promises_1 = require("node:fs/promises");
18
+ const posix_1 = __importDefault(require("node:path/posix"));
19
+ const node_util_1 = require("node:util");
20
+ const paths_1 = require("../../utility/paths");
21
+ const karma_config_analyzer_1 = require("./karma-config-analyzer");
22
+ /**
23
+ * Generates the default Karma configuration file content as a string.
24
+ * @param relativePathToWorkspaceRoot The relative path from the Karma config file to the workspace root.
25
+ * @param projectName The name of the project.
26
+ * @param needDevkitPlugin A boolean indicating if the devkit plugin is needed.
27
+ * @returns The content of the default `karma.conf.js` file.
28
+ */
29
+ async function generateDefaultKarmaConfig(relativePathToWorkspaceRoot, projectName, needDevkitPlugin) {
30
+ const templatePath = posix_1.default.join(__dirname, '../../config/files/karma.conf.js.template');
31
+ let template = await (0, promises_1.readFile)(templatePath, 'utf-8');
32
+ // TODO: Replace this with the actual schematic templating logic.
33
+ template = template
34
+ .replace(/<%= relativePathToWorkspaceRoot %>/g, posix_1.default.normalize(relativePathToWorkspaceRoot).replace(/\\/g, '/'))
35
+ .replace(/<%= folderName %>/g, projectName);
36
+ const devkitPluginRegex = /<% if \(needDevkitPlugin\) { %>(.*?)<% } %>/gs;
37
+ const replacement = needDevkitPlugin ? '$1' : '';
38
+ template = template.replace(devkitPluginRegex, replacement);
39
+ return template;
40
+ }
41
+ /**
42
+ * Compares two Karma configuration analyses and returns the difference.
43
+ * @param projectAnalysis The analysis of the project's configuration.
44
+ * @param defaultAnalysis The analysis of the default configuration to compare against.
45
+ * @returns A diff object representing the changes between the two configurations.
46
+ */
47
+ function compareKarmaConfigs(projectAnalysis, defaultAnalysis) {
48
+ const added = new Map();
49
+ const removed = new Map();
50
+ const modified = new Map();
51
+ const allKeys = new Set([...projectAnalysis.settings.keys(), ...defaultAnalysis.settings.keys()]);
52
+ for (const key of allKeys) {
53
+ const projectValue = projectAnalysis.settings.get(key);
54
+ const defaultValue = defaultAnalysis.settings.get(key);
55
+ if (projectValue !== undefined && defaultValue === undefined) {
56
+ added.set(key, projectValue);
57
+ }
58
+ else if (projectValue === undefined && defaultValue !== undefined) {
59
+ removed.set(key, defaultValue);
60
+ }
61
+ else if (projectValue !== undefined && defaultValue !== undefined) {
62
+ if (!(0, node_util_1.isDeepStrictEqual)(projectValue, defaultValue)) {
63
+ modified.set(key, { projectValue, defaultValue });
64
+ }
65
+ }
66
+ }
67
+ return {
68
+ added,
69
+ removed,
70
+ modified,
71
+ isReliable: !projectAnalysis.hasUnsupportedValues && !defaultAnalysis.hasUnsupportedValues,
72
+ };
73
+ }
74
+ /**
75
+ * Checks if there are any differences in the provided Karma configuration diff.
76
+ * @param diff The Karma configuration diff object to check.
77
+ * @returns True if there are any differences; false otherwise.
78
+ */
79
+ function hasDifferences(diff) {
80
+ return diff.added.size > 0 || diff.removed.size > 0 || diff.modified.size > 0;
81
+ }
82
+ async function compareKarmaConfigToDefault(projectConfigOrAnalysis, projectName, karmaConfigPath, needDevkitPlugin) {
83
+ const projectAnalysis = typeof projectConfigOrAnalysis === 'string'
84
+ ? (0, karma_config_analyzer_1.analyzeKarmaConfig)(projectConfigOrAnalysis)
85
+ : projectConfigOrAnalysis;
86
+ const defaultContent = await generateDefaultKarmaConfig((0, paths_1.relativePathToWorkspaceRoot)(posix_1.default.dirname(karmaConfigPath)), projectName, needDevkitPlugin);
87
+ const defaultAnalysis = (0, karma_config_analyzer_1.analyzeKarmaConfig)(defaultContent);
88
+ return compareKarmaConfigs(projectAnalysis, defaultAnalysis);
89
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @license
3
+ * Copyright Google LLC All Rights Reserved.
4
+ *
5
+ * Use of this source code is governed by an MIT-style license that can be
6
+ * found in the LICENSE file at https://angular.dev/license
7
+ */
8
+ import type { Rule } from '@angular-devkit/schematics';
9
+ export default function (): Rule;
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ /**
3
+ * @license
4
+ * Copyright Google LLC All Rights Reserved.
5
+ *
6
+ * Use of this source code is governed by an MIT-style license that can be
7
+ * found in the LICENSE file at https://angular.dev/license
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.default = default_1;
11
+ const workspace_1 = require("../../utility/workspace");
12
+ const workspace_models_1 = require("../../utility/workspace-models");
13
+ const karma_config_analyzer_1 = require("./karma-config-analyzer");
14
+ const karma_config_comparer_1 = require("./karma-config-comparer");
15
+ function updateProjects(tree) {
16
+ return (0, workspace_1.updateWorkspace)(async (workspace) => {
17
+ const removableKarmaConfigs = new Map();
18
+ for (const [projectName, project] of workspace.projects) {
19
+ for (const [, target] of project.targets) {
20
+ let needDevkitPlugin = false;
21
+ switch (target.builder) {
22
+ case workspace_models_1.Builders.Karma:
23
+ needDevkitPlugin = true;
24
+ break;
25
+ case workspace_models_1.Builders.BuildKarma:
26
+ break;
27
+ default:
28
+ continue;
29
+ }
30
+ for (const [, options] of (0, workspace_1.allTargetOptions)(target, false)) {
31
+ const karmaConfig = options['karmaConfig'];
32
+ if (typeof karmaConfig !== 'string') {
33
+ continue;
34
+ }
35
+ let isRemovable = removableKarmaConfigs.get(karmaConfig);
36
+ if (isRemovable === undefined && tree.exists(karmaConfig)) {
37
+ const content = tree.readText(karmaConfig);
38
+ const analysis = (0, karma_config_analyzer_1.analyzeKarmaConfig)(content);
39
+ if (analysis.hasUnsupportedValues) {
40
+ // Cannot safely determine if the file is removable.
41
+ isRemovable = false;
42
+ }
43
+ else {
44
+ const diff = await (0, karma_config_comparer_1.compareKarmaConfigToDefault)(analysis, projectName, karmaConfig, needDevkitPlugin);
45
+ isRemovable = !(0, karma_config_comparer_1.hasDifferences)(diff) && diff.isReliable;
46
+ }
47
+ removableKarmaConfigs.set(karmaConfig, isRemovable);
48
+ if (isRemovable) {
49
+ tree.delete(karmaConfig);
50
+ }
51
+ }
52
+ if (isRemovable) {
53
+ delete options['karmaConfig'];
54
+ }
55
+ }
56
+ }
57
+ }
58
+ });
59
+ }
60
+ function default_1() {
61
+ return updateProjects;
62
+ }
@@ -27,6 +27,11 @@
27
27
  "optional": true,
28
28
  "recommended": true,
29
29
  "documentation": "tools/cli/build-system-migration"
30
+ },
31
+ "remove-default-karma-config": {
32
+ "version": "20.2.0",
33
+ "factory": "./karma/migration",
34
+ "description": "Remove any karma configuration files that only contain the default content. The default configuration is automatically available without a specific project file."
30
35
  }
31
36
  }
32
37
  }
@@ -6,43 +6,13 @@
6
6
  * Use of this source code is governed by an MIT-style license that can be
7
7
  * found in the LICENSE file at https://angular.dev/license
8
8
  */
9
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- var desc = Object.getOwnPropertyDescriptor(m, k);
12
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
- desc = { enumerable: true, get: function() { return m[k]; } };
14
- }
15
- Object.defineProperty(o, k2, desc);
16
- }) : (function(o, m, k, k2) {
17
- if (k2 === undefined) k2 = k;
18
- o[k2] = m[k];
19
- }));
20
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21
- Object.defineProperty(o, "default", { enumerable: true, value: v });
22
- }) : function(o, v) {
23
- o["default"] = v;
24
- });
25
- var __importStar = (this && this.__importStar) || (function () {
26
- var ownKeys = function(o) {
27
- ownKeys = Object.getOwnPropertyNames || function (o) {
28
- var ar = [];
29
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
30
- return ar;
31
- };
32
- return ownKeys(o);
33
- };
34
- return function (mod) {
35
- if (mod && mod.__esModule) return mod;
36
- var result = {};
37
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
38
- __setModuleDefault(result, mod);
39
- return result;
40
- };
41
- })();
9
+ var __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
11
+ };
42
12
  Object.defineProperty(exports, "__esModule", { value: true });
43
13
  exports.default = default_1;
44
- const ts = __importStar(require("../../third_party/github.com/Microsoft/TypeScript/lib/typescript"));
45
- const dependencies_1 = require("../../utility/dependencies");
14
+ const typescript_1 = __importDefault(require("../../third_party/github.com/Microsoft/TypeScript/lib/typescript"));
15
+ const dependency_1 = require("../../utility/dependency");
46
16
  const latest_versions_1 = require("../../utility/latest-versions");
47
17
  function* visit(directory) {
48
18
  for (const path of directory.subfiles) {
@@ -67,20 +37,20 @@ function* visit(directory) {
67
37
  }
68
38
  function default_1() {
69
39
  return async (tree) => {
70
- let angularSSRAdded = false;
40
+ let rule;
71
41
  for (const [filePath, content] of visit(tree.root)) {
72
42
  let updatedContent = content;
73
43
  const ssrImports = new Set();
74
44
  const platformServerImports = new Set();
75
- const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
45
+ const sourceFile = typescript_1.default.createSourceFile(filePath, content, typescript_1.default.ScriptTarget.Latest, true);
76
46
  sourceFile.forEachChild((node) => {
77
- if (ts.isImportDeclaration(node)) {
47
+ if (typescript_1.default.isImportDeclaration(node)) {
78
48
  const moduleSpecifier = node.moduleSpecifier.getText(sourceFile);
79
49
  if (moduleSpecifier.includes('@angular/platform-server')) {
80
50
  const importClause = node.importClause;
81
51
  if (importClause &&
82
52
  importClause.namedBindings &&
83
- ts.isNamedImports(importClause.namedBindings)) {
53
+ typescript_1.default.isNamedImports(importClause.namedBindings)) {
84
54
  const namedImports = importClause.namedBindings.elements.map((e) => e.getText(sourceFile));
85
55
  namedImports.forEach((importName) => {
86
56
  if (importName === 'provideServerRendering') {
@@ -97,7 +67,7 @@ function default_1() {
97
67
  const importClause = node.importClause;
98
68
  if (importClause &&
99
69
  importClause.namedBindings &&
100
- ts.isNamedImports(importClause.namedBindings)) {
70
+ typescript_1.default.isNamedImports(importClause.namedBindings)) {
101
71
  importClause.namedBindings.elements.forEach((e) => {
102
72
  ssrImports.add(e.getText(sourceFile));
103
73
  });
@@ -118,16 +88,11 @@ function default_1() {
118
88
  }
119
89
  if (content !== updatedContent) {
120
90
  tree.overwrite(filePath, updatedContent);
121
- if (!angularSSRAdded) {
122
- (0, dependencies_1.addPackageJsonDependency)(tree, {
123
- name: '@angular/ssr',
124
- version: latest_versions_1.latestVersions.AngularSSR,
125
- type: dependencies_1.NodeDependencyType.Default,
126
- overwrite: false,
127
- });
128
- angularSSRAdded = true;
91
+ if (rule === undefined) {
92
+ rule = (0, dependency_1.addDependency)('@angular/ssr', latest_versions_1.latestVersions.AngularSSR);
129
93
  }
130
94
  }
131
95
  }
96
+ return rule;
132
97
  };
133
98
  }
@@ -10,13 +10,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.default = default_1;
11
11
  const schematics_1 = require("@angular-devkit/schematics");
12
12
  const posix_1 = require("node:path/posix");
13
- const dependencies_1 = require("../../utility/dependencies");
14
13
  const dependency_1 = require("../../utility/dependency");
15
14
  const json_file_1 = require("../../utility/json-file");
16
15
  const latest_versions_1 = require("../../utility/latest-versions");
17
16
  const workspace_1 = require("../../utility/workspace");
18
17
  const workspace_models_1 = require("../../utility/workspace-models");
19
- const css_import_lexer_1 = require("./css-import-lexer");
18
+ const stylesheet_updates_1 = require("./stylesheet-updates");
20
19
  function* updateBuildTarget(projectName, buildTarget, serverTarget, tree, context) {
21
20
  // Update builder target and options
22
21
  buildTarget.builder = workspace_models_1.Builders.Application;
@@ -141,7 +140,7 @@ function updateProjects(tree, context) {
141
140
  }
142
141
  // Update CSS/Sass import specifiers
143
142
  const projectSourceRoot = (0, posix_1.join)(project.root, project.sourceRoot ?? 'src');
144
- updateStyleImports(tree, projectSourceRoot, buildTarget);
143
+ (0, stylesheet_updates_1.updateStyleImports)(tree, projectSourceRoot, buildTarget);
145
144
  }
146
145
  // Check for @angular-devkit/build-angular Webpack usage
147
146
  let hasAngularDevkitUsage = false;
@@ -195,17 +194,13 @@ function updateProjects(tree, context) {
195
194
  // Add direct @angular/build dependencies and remove @angular-devkit/build-angular
196
195
  rules.push((0, dependency_1.addDependency)('@angular/build', latest_versions_1.latestVersions.DevkitBuildAngular, {
197
196
  type: dependency_1.DependencyType.Dev,
198
- // Always is set here since removePackageJsonDependency below does not automatically
199
- // trigger the package manager execution.
200
- install: dependency_1.InstallBehavior.Always,
201
197
  existing: dependency_1.ExistingBehavior.Replace,
202
- }));
203
- (0, dependencies_1.removePackageJsonDependency)(tree, '@angular-devkit/build-angular');
198
+ }), (0, dependency_1.removeDependency)('@angular-devkit/build-angular'));
204
199
  // Add less dependency if any projects contain a Less stylesheet file.
205
200
  // This check does not consider Node.js packages due to the performance
206
201
  // cost of searching such a large directory structure. A build time error
207
202
  // will provide instructions to install the package in this case.
208
- if (hasLessStylesheets(tree)) {
203
+ if ((0, stylesheet_updates_1.hasLessStylesheets)(tree)) {
209
204
  rules.push((0, dependency_1.addDependency)('less', latest_versions_1.latestVersions['less'], {
210
205
  type: dependency_1.DependencyType.Dev,
211
206
  existing: dependency_1.ExistingBehavior.Skip,
@@ -214,7 +209,7 @@ function updateProjects(tree, context) {
214
209
  // Add postcss dependency if any projects have a custom postcss configuration file.
215
210
  // The build system only supports files in a project root or workspace root with
216
211
  // names of either 'postcss.config.json' or '.postcssrc.json'.
217
- if (hasPostcssConfiguration(tree, workspace)) {
212
+ if ((0, stylesheet_updates_1.hasPostcssConfiguration)(tree, workspace)) {
218
213
  rules.push((0, dependency_1.addDependency)('postcss', latest_versions_1.latestVersions['postcss'], {
219
214
  type: dependency_1.DependencyType.Dev,
220
215
  existing: dependency_1.ExistingBehavior.Replace,
@@ -247,138 +242,6 @@ function updateProjects(tree, context) {
247
242
  return (0, schematics_1.chain)(rules);
248
243
  });
249
244
  }
250
- /**
251
- * Searches the schematic tree for files that have a `.less` extension.
252
- *
253
- * @param tree A Schematics tree instance to search
254
- * @returns true if Less stylesheet files are found; otherwise, false
255
- */
256
- function hasLessStylesheets(tree) {
257
- const directories = [tree.getDir('/')];
258
- let current;
259
- while ((current = directories.pop())) {
260
- for (const path of current.subfiles) {
261
- if (path.endsWith('.less')) {
262
- return true;
263
- }
264
- }
265
- for (const path of current.subdirs) {
266
- if (path === 'node_modules' || path.startsWith('.')) {
267
- continue;
268
- }
269
- directories.push(current.dir(path));
270
- }
271
- }
272
- }
273
- /**
274
- * Searches for a Postcss configuration file within the workspace root
275
- * or any of the project roots.
276
- *
277
- * @param tree A Schematics tree instance to search
278
- * @param workspace A Workspace to check for projects
279
- * @returns true, if a Postcss configuration file is found; otherwise, false
280
- */
281
- function hasPostcssConfiguration(tree, workspace) {
282
- // Add workspace root
283
- const searchDirectories = [''];
284
- // Add each project root
285
- for (const { root } of workspace.projects.values()) {
286
- if (root) {
287
- searchDirectories.push(root);
288
- }
289
- }
290
- return searchDirectories.some((dir) => tree.exists((0, posix_1.join)(dir, 'postcss.config.json')) || tree.exists((0, posix_1.join)(dir, '.postcssrc.json')));
291
- }
292
- function* visit(directory) {
293
- for (const path of directory.subfiles) {
294
- const sass = path.endsWith('.scss');
295
- if (path.endsWith('.css') || sass) {
296
- const entry = directory.file(path);
297
- if (entry) {
298
- const content = entry.content;
299
- yield [entry.path, content.toString(), sass];
300
- }
301
- }
302
- }
303
- for (const path of directory.subdirs) {
304
- if (path === 'node_modules' || path.startsWith('.')) {
305
- continue;
306
- }
307
- yield* visit(directory.dir(path));
308
- }
309
- }
310
- // Based on https://github.com/sass/dart-sass/blob/44d6bb6ac72fe6b93f5bfec371a1fffb18e6b76d/lib/src/importer/utils.dart
311
- function* potentialSassImports(specifier, base, fromImport) {
312
- const directory = (0, posix_1.join)(base, (0, posix_1.dirname)(specifier));
313
- const extension = (0, posix_1.extname)(specifier);
314
- const hasStyleExtension = extension === '.scss' || extension === '.sass' || extension === '.css';
315
- // Remove the style extension if present to allow adding the `.import` suffix
316
- const filename = (0, posix_1.basename)(specifier, hasStyleExtension ? extension : undefined);
317
- if (hasStyleExtension) {
318
- if (fromImport) {
319
- yield (0, posix_1.join)(directory, filename + '.import' + extension);
320
- yield (0, posix_1.join)(directory, '_' + filename + '.import' + extension);
321
- }
322
- yield (0, posix_1.join)(directory, filename + extension);
323
- yield (0, posix_1.join)(directory, '_' + filename + extension);
324
- }
325
- else {
326
- if (fromImport) {
327
- yield (0, posix_1.join)(directory, filename + '.import.scss');
328
- yield (0, posix_1.join)(directory, filename + '.import.sass');
329
- yield (0, posix_1.join)(directory, filename + '.import.css');
330
- yield (0, posix_1.join)(directory, '_' + filename + '.import.scss');
331
- yield (0, posix_1.join)(directory, '_' + filename + '.import.sass');
332
- yield (0, posix_1.join)(directory, '_' + filename + '.import.css');
333
- }
334
- yield (0, posix_1.join)(directory, filename + '.scss');
335
- yield (0, posix_1.join)(directory, filename + '.sass');
336
- yield (0, posix_1.join)(directory, filename + '.css');
337
- yield (0, posix_1.join)(directory, '_' + filename + '.scss');
338
- yield (0, posix_1.join)(directory, '_' + filename + '.sass');
339
- yield (0, posix_1.join)(directory, '_' + filename + '.css');
340
- }
341
- }
342
- function updateStyleImports(tree, projectSourceRoot, buildTarget) {
343
- const external = new Set();
344
- let needWorkspaceIncludePath = false;
345
- for (const file of visit(tree.getDir(projectSourceRoot))) {
346
- const [path, content, sass] = file;
347
- const relativeBase = (0, posix_1.dirname)(path);
348
- let updater;
349
- for (const { start, specifier, fromUse } of (0, css_import_lexer_1.findImports)(content, sass)) {
350
- if (specifier[0] === '~') {
351
- updater ??= tree.beginUpdate(path);
352
- // start position includes the opening quote
353
- updater.remove(start + 1, 1);
354
- }
355
- else if (specifier[0] === '^') {
356
- updater ??= tree.beginUpdate(path);
357
- // start position includes the opening quote
358
- updater.remove(start + 1, 1);
359
- // Add to externalDependencies
360
- external.add(specifier.slice(1));
361
- }
362
- else if (sass &&
363
- [...potentialSassImports(specifier, relativeBase, !fromUse)].every((v) => !tree.exists(v)) &&
364
- [...potentialSassImports(specifier, '/', !fromUse)].some((v) => tree.exists(v))) {
365
- needWorkspaceIncludePath = true;
366
- }
367
- }
368
- if (updater) {
369
- tree.commitUpdate(updater);
370
- }
371
- }
372
- if (needWorkspaceIncludePath) {
373
- buildTarget.options ??= {};
374
- buildTarget.options['stylePreprocessorOptions'] ??= {};
375
- (buildTarget.options['stylePreprocessorOptions']['includePaths'] ??= []).push('.');
376
- }
377
- if (external.size > 0) {
378
- buildTarget.options ??= {};
379
- (buildTarget.options['externalDependencies'] ??= []).push(...external);
380
- }
381
- }
382
245
  function deleteFile(path) {
383
246
  return (tree) => {
384
247
  tree.delete(path);
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @license
3
+ * Copyright Google LLC All Rights Reserved.
4
+ *
5
+ * Use of this source code is governed by an MIT-style license that can be
6
+ * found in the LICENSE file at https://angular.dev/license
7
+ */
8
+ import { Tree } from '@angular-devkit/schematics';
9
+ import { TargetDefinition, WorkspaceDefinition } from '../../utility/workspace';
10
+ /**
11
+ * Searches the schematic tree for files that have a `.less` extension.
12
+ * This is used to determine if the `less` package should be added as a dependency.
13
+ *
14
+ * @param tree A Schematics tree instance to search.
15
+ * @returns `true` if Less stylesheet files are found; otherwise, `false`.
16
+ */
17
+ export declare function hasLessStylesheets(tree: Tree): boolean;
18
+ /**
19
+ * Searches for a PostCSS configuration file within the workspace root or any of the project roots.
20
+ * This is used to determine if the `postcss` package should be added as a dependency.
21
+ *
22
+ * @param tree A Schematics tree instance to search.
23
+ * @param workspace A Workspace to check for projects.
24
+ * @returns `true` if a PostCSS configuration file is found; otherwise, `false`.
25
+ */
26
+ export declare function hasPostcssConfiguration(tree: Tree, workspace: WorkspaceDefinition): boolean;
27
+ /**
28
+ * The main orchestrator function for updating stylesheets.
29
+ * It iterates through all stylesheets in a project, analyzes them, and applies the necessary
30
+ * changes to the files and the build configuration.
31
+ *
32
+ * @param tree A Schematics tree instance.
33
+ * @param projectSourceRoot The source root of the project being updated.
34
+ * @param buildTarget The build target of the project being updated.
35
+ */
36
+ export declare function updateStyleImports(tree: Tree, projectSourceRoot: string, buildTarget: TargetDefinition): void;