@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.
- package/ai-config/files/__rulesName__.template +49 -0
- package/ai-config/index.d.ts +10 -0
- package/ai-config/index.js +55 -0
- package/ai-config/schema.d.ts +21 -0
- package/ai-config/schema.js +15 -0
- package/ai-config/schema.json +39 -0
- package/application/index.js +26 -39
- package/collection.json +5 -0
- package/library/index.js +25 -40
- package/migrations/karma/karma-config-analyzer.d.ts +27 -0
- package/migrations/karma/karma-config-analyzer.js +131 -0
- package/migrations/karma/karma-config-comparer.d.ts +63 -0
- package/migrations/karma/karma-config-comparer.js +89 -0
- package/migrations/karma/migration.d.ts +9 -0
- package/migrations/karma/migration.js +62 -0
- package/migrations/migration-collection.json +5 -0
- package/migrations/replace-provide-server-rendering-import/migration.js +13 -48
- package/migrations/use-application-builder/migration.js +5 -142
- package/migrations/use-application-builder/stylesheet-updates.d.ts +36 -0
- package/migrations/use-application-builder/stylesheet-updates.js +219 -0
- package/ng-new/index.js +3 -0
- package/ng-new/schema.d.ts +14 -0
- package/ng-new/schema.js +11 -1
- package/ng-new/schema.json +10 -3
- package/package.json +4 -4
- package/service-worker/index.js +2 -2
- package/third_party/github.com/Microsoft/TypeScript/lib/typescript.js +1 -1
- package/utility/dependency.d.ts +47 -1
- package/utility/dependency.js +55 -0
- package/utility/latest-versions/package.json +1 -1
- package/utility/latest-versions.js +3 -3
- 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
|
|
10
|
-
|
|
11
|
-
|
|
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
|
|
45
|
-
const
|
|
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
|
|
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 =
|
|
45
|
+
const sourceFile = typescript_1.default.createSourceFile(filePath, content, typescript_1.default.ScriptTarget.Latest, true);
|
|
76
46
|
sourceFile.forEachChild((node) => {
|
|
77
|
-
if (
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
122
|
-
(0,
|
|
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
|
|
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;
|