Skip to content

Commit

Permalink
fix(@schematics/angular): add less dependency in application migratio…
Browse files Browse the repository at this point in the history
…n 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.
  • Loading branch information
clydin committed Apr 29, 2024
1 parent b0ec254 commit 3dae3c0
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -245,17 +245,58 @@ function updateProjects(tree: Tree, context: SchematicContext) {
rules.push(
addDependency('@angular/build', latestVersions.DevkitBuildAngular, {
type: DependencyType.Dev,
// Always is set here since removePackageJsonDependency below does not automatically
// trigger the package manager execution.
install: InstallBehavior.Always,
existing: ExistingBehavior.Replace,
}),
);
removePackageJsonDependency(tree, '@angular-devkit/build-angular');

// Add less dependency if any projects contain a Less stylesheet file.
// This check does not consider Node.js packages due to the performance
// cost of searching such a large directory structure. A build time error
// will provide instructions to install the package in this case.
if (hasLessStylesheets(tree)) {
rules.push(
addDependency('less', latestVersions['less'], {
type: DependencyType.Dev,
existing: ExistingBehavior.Skip,
}),
);
}
}

return chain(rules);
});
}

/**
* Searches the schematic tree for files that have a `.less` extension.
*
* @param tree A Schematics tree instance to search
* @returns true if Less stylesheet files are found; otherwise, false
*/
function hasLessStylesheets(tree: Tree) {
const directories = [tree.getDir('/')];

let current;
while ((current = directories.pop())) {
for (const path of current.subfiles) {
if (path.endsWith('.less')) {
return true;
}
}

for (const path of current.subdirs) {
if (path === 'node_modules' || path.startsWith('.')) {
continue;
}
directories.push(current.dir(path));
}
}
}

function* visit(
directory: DirEntry,
): IterableIterator<[fileName: string, contents: string, sass: boolean]> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,4 +267,22 @@ describe(`Migration to use the application builder`, () => {
const { stylePreprocessorOptions } = app.architect['build'].options;
expect(stylePreprocessorOptions).toEqual({ includePaths: ['.'] });
});

it('should add "less" dependency when converting to "@angular/build" and a ".less" file is present', async () => {
tree.create('/project/app/src/styles.less', '');

const newTree = await schematicRunner.runSchematic(schematicName, {}, tree);

const { devDependencies } = JSON.parse(newTree.readContent('/package.json'));

expect(devDependencies['less']).toBeDefined();
});

it('should not add "less" dependency when converting to "@angular/build" and a ".less" file is present', async () => {
const newTree = await schematicRunner.runSchematic(schematicName, {}, tree);

const { devDependencies } = JSON.parse(newTree.readContent('/package.json'));

expect(devDependencies['less']).toBeUndefined();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"karma-jasmine-html-reporter": "~2.1.0",
"karma-jasmine": "~5.1.0",
"karma": "~6.4.0",
"less": "^4.2.0",
"ng-packagr": "^18.0.0-next.0",
"protractor": "~7.0.0",
"rxjs": "~7.8.0",
Expand Down

0 comments on commit 3dae3c0

Please sign in to comment.