Skip to content

Commit 95a4d6e

Browse files
committedApr 29, 2024·
fix(@schematics/angular): add less dependency in application migration if needed
The application migration schematic will now attempt to detect the usage of Less stylesheets within a workspace and install the `less` dependency if required. This will only occur if the migration analysis allows for the conversion to use the `@angular/build` package instead of the `@angular-devkit/build-angular` package. The Less usage detection may not detect Less stylesheets within Node.js packages and currently does not handle the case where a project only has inline Less stylesheets. More complex analysis may be added in the future. However, a build time error message will be presented with instructions to install `less` in these cases if the stylesheet preprocessor is required and not present. (cherry picked from commit 3dae3c0)
1 parent d2617a0 commit 95a4d6e

File tree

3 files changed

+60
-0
lines changed

3 files changed

+60
-0
lines changed
 

‎packages/schematics/angular/migrations/use-application-builder/migration.ts

+41
Original file line numberDiff line numberDiff line change
@@ -245,17 +245,58 @@ function updateProjects(tree: Tree, context: SchematicContext) {
245245
rules.push(
246246
addDependency('@angular/build', latestVersions.DevkitBuildAngular, {
247247
type: DependencyType.Dev,
248+
// Always is set here since removePackageJsonDependency below does not automatically
249+
// trigger the package manager execution.
248250
install: InstallBehavior.Always,
249251
existing: ExistingBehavior.Replace,
250252
}),
251253
);
252254
removePackageJsonDependency(tree, '@angular-devkit/build-angular');
255+
256+
// Add less dependency if any projects contain a Less stylesheet file.
257+
// This check does not consider Node.js packages due to the performance
258+
// cost of searching such a large directory structure. A build time error
259+
// will provide instructions to install the package in this case.
260+
if (hasLessStylesheets(tree)) {
261+
rules.push(
262+
addDependency('less', latestVersions['less'], {
263+
type: DependencyType.Dev,
264+
existing: ExistingBehavior.Skip,
265+
}),
266+
);
267+
}
253268
}
254269

255270
return chain(rules);
256271
});
257272
}
258273

274+
/**
275+
* Searches the schematic tree for files that have a `.less` extension.
276+
*
277+
* @param tree A Schematics tree instance to search
278+
* @returns true if Less stylesheet files are found; otherwise, false
279+
*/
280+
function hasLessStylesheets(tree: Tree) {
281+
const directories = [tree.getDir('/')];
282+
283+
let current;
284+
while ((current = directories.pop())) {
285+
for (const path of current.subfiles) {
286+
if (path.endsWith('.less')) {
287+
return true;
288+
}
289+
}
290+
291+
for (const path of current.subdirs) {
292+
if (path === 'node_modules' || path.startsWith('.')) {
293+
continue;
294+
}
295+
directories.push(current.dir(path));
296+
}
297+
}
298+
}
299+
259300
function* visit(
260301
directory: DirEntry,
261302
): IterableIterator<[fileName: string, contents: string, sass: boolean]> {

‎packages/schematics/angular/migrations/use-application-builder/migration_spec.ts

+18
Original file line numberDiff line numberDiff line change
@@ -267,4 +267,22 @@ describe(`Migration to use the application builder`, () => {
267267
const { stylePreprocessorOptions } = app.architect['build'].options;
268268
expect(stylePreprocessorOptions).toEqual({ includePaths: ['.'] });
269269
});
270+
271+
it('should add "less" dependency when converting to "@angular/build" and a ".less" file is present', async () => {
272+
tree.create('/project/app/src/styles.less', '');
273+
274+
const newTree = await schematicRunner.runSchematic(schematicName, {}, tree);
275+
276+
const { devDependencies } = JSON.parse(newTree.readContent('/package.json'));
277+
278+
expect(devDependencies['less']).toBeDefined();
279+
});
280+
281+
it('should not add "less" dependency when converting to "@angular/build" and a ".less" file is present', async () => {
282+
const newTree = await schematicRunner.runSchematic(schematicName, {}, tree);
283+
284+
const { devDependencies } = JSON.parse(newTree.readContent('/package.json'));
285+
286+
expect(devDependencies['less']).toBeUndefined();
287+
});
270288
});

‎packages/schematics/angular/utility/latest-versions/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"karma-jasmine-html-reporter": "~2.1.0",
1717
"karma-jasmine": "~5.1.0",
1818
"karma": "~6.4.0",
19+
"less": "^4.2.0",
1920
"ng-packagr": "^18.0.0-next.0",
2021
"protractor": "~7.0.0",
2122
"rxjs": "~7.8.0",

0 commit comments

Comments
 (0)
Please sign in to comment.