Skip to content

Commit 8b8fe39

Browse files
committed
refactor(@schematics/angular): organize use-application-builder migration
Reorganizes the `use-application-builder` migration by extracting the stylesheet-related logic into a separate, more focused file. The key changes include: - Moving stylesheet-related functions (`hasLessStylesheets`, `hasPostcssConfiguration`, `updateStyleImports`, and their helpers) from `migration.ts` into a new `stylesheet-updates.ts` file. - Updating the main `migration.ts` file to import these functions from the new module.
1 parent 37589b6 commit 8b8fe39

File tree

2 files changed

+288
-166
lines changed

2 files changed

+288
-166
lines changed

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

Lines changed: 6 additions & 166 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,14 @@
77
*/
88

99
import {
10-
DirEntry,
1110
Rule,
1211
SchematicContext,
1312
SchematicsException,
1413
Tree,
1514
chain,
1615
externalSchematic,
1716
} from '@angular-devkit/schematics';
18-
import { basename, dirname, extname, join } from 'node:path/posix';
17+
import { dirname, join } from 'node:path/posix';
1918
import { removePackageJsonDependency } from '../../utility/dependencies';
2019
import {
2120
DependencyType,
@@ -27,13 +26,16 @@ import { JSONFile } from '../../utility/json-file';
2726
import { latestVersions } from '../../utility/latest-versions';
2827
import {
2928
TargetDefinition,
30-
WorkspaceDefinition,
3129
allTargetOptions,
3230
allWorkspaceTargets,
3331
updateWorkspace,
3432
} from '../../utility/workspace';
3533
import { Builders, ProjectType } from '../../utility/workspace-models';
36-
import { findImports } from './css-import-lexer';
34+
import {
35+
hasLessStylesheets,
36+
hasPostcssConfiguration,
37+
updateStyleImports,
38+
} from './stylesheet-updates';
3739

3840
function* updateBuildTarget(
3941
projectName: string,
@@ -334,168 +336,6 @@ function updateProjects(tree: Tree, context: SchematicContext) {
334336
});
335337
}
336338

337-
/**
338-
* Searches the schematic tree for files that have a `.less` extension.
339-
*
340-
* @param tree A Schematics tree instance to search
341-
* @returns true if Less stylesheet files are found; otherwise, false
342-
*/
343-
function hasLessStylesheets(tree: Tree) {
344-
const directories = [tree.getDir('/')];
345-
346-
let current;
347-
while ((current = directories.pop())) {
348-
for (const path of current.subfiles) {
349-
if (path.endsWith('.less')) {
350-
return true;
351-
}
352-
}
353-
354-
for (const path of current.subdirs) {
355-
if (path === 'node_modules' || path.startsWith('.')) {
356-
continue;
357-
}
358-
directories.push(current.dir(path));
359-
}
360-
}
361-
}
362-
363-
/**
364-
* Searches for a Postcss configuration file within the workspace root
365-
* or any of the project roots.
366-
*
367-
* @param tree A Schematics tree instance to search
368-
* @param workspace A Workspace to check for projects
369-
* @returns true, if a Postcss configuration file is found; otherwise, false
370-
*/
371-
function hasPostcssConfiguration(tree: Tree, workspace: WorkspaceDefinition) {
372-
// Add workspace root
373-
const searchDirectories = [''];
374-
375-
// Add each project root
376-
for (const { root } of workspace.projects.values()) {
377-
if (root) {
378-
searchDirectories.push(root);
379-
}
380-
}
381-
382-
return searchDirectories.some(
383-
(dir) =>
384-
tree.exists(join(dir, 'postcss.config.json')) || tree.exists(join(dir, '.postcssrc.json')),
385-
);
386-
}
387-
388-
function* visit(
389-
directory: DirEntry,
390-
): IterableIterator<[fileName: string, contents: string, sass: boolean]> {
391-
for (const path of directory.subfiles) {
392-
const sass = path.endsWith('.scss');
393-
if (path.endsWith('.css') || sass) {
394-
const entry = directory.file(path);
395-
if (entry) {
396-
const content = entry.content;
397-
398-
yield [entry.path, content.toString(), sass];
399-
}
400-
}
401-
}
402-
403-
for (const path of directory.subdirs) {
404-
if (path === 'node_modules' || path.startsWith('.')) {
405-
continue;
406-
}
407-
408-
yield* visit(directory.dir(path));
409-
}
410-
}
411-
412-
// Based on https://github.com/sass/dart-sass/blob/44d6bb6ac72fe6b93f5bfec371a1fffb18e6b76d/lib/src/importer/utils.dart
413-
function* potentialSassImports(
414-
specifier: string,
415-
base: string,
416-
fromImport: boolean,
417-
): Iterable<string> {
418-
const directory = join(base, dirname(specifier));
419-
const extension = extname(specifier);
420-
const hasStyleExtension = extension === '.scss' || extension === '.sass' || extension === '.css';
421-
// Remove the style extension if present to allow adding the `.import` suffix
422-
const filename = basename(specifier, hasStyleExtension ? extension : undefined);
423-
424-
if (hasStyleExtension) {
425-
if (fromImport) {
426-
yield join(directory, filename + '.import' + extension);
427-
yield join(directory, '_' + filename + '.import' + extension);
428-
}
429-
yield join(directory, filename + extension);
430-
yield join(directory, '_' + filename + extension);
431-
} else {
432-
if (fromImport) {
433-
yield join(directory, filename + '.import.scss');
434-
yield join(directory, filename + '.import.sass');
435-
yield join(directory, filename + '.import.css');
436-
yield join(directory, '_' + filename + '.import.scss');
437-
yield join(directory, '_' + filename + '.import.sass');
438-
yield join(directory, '_' + filename + '.import.css');
439-
}
440-
yield join(directory, filename + '.scss');
441-
yield join(directory, filename + '.sass');
442-
yield join(directory, filename + '.css');
443-
yield join(directory, '_' + filename + '.scss');
444-
yield join(directory, '_' + filename + '.sass');
445-
yield join(directory, '_' + filename + '.css');
446-
}
447-
}
448-
449-
function updateStyleImports(tree: Tree, projectSourceRoot: string, buildTarget: TargetDefinition) {
450-
const external = new Set<string>();
451-
let needWorkspaceIncludePath = false;
452-
for (const file of visit(tree.getDir(projectSourceRoot))) {
453-
const [path, content, sass] = file;
454-
const relativeBase = dirname(path);
455-
456-
let updater;
457-
for (const { start, specifier, fromUse } of findImports(content, sass)) {
458-
if (specifier[0] === '~') {
459-
updater ??= tree.beginUpdate(path);
460-
// start position includes the opening quote
461-
updater.remove(start + 1, 1);
462-
} else if (specifier[0] === '^') {
463-
updater ??= tree.beginUpdate(path);
464-
// start position includes the opening quote
465-
updater.remove(start + 1, 1);
466-
// Add to externalDependencies
467-
external.add(specifier.slice(1));
468-
} else if (
469-
sass &&
470-
[...potentialSassImports(specifier, relativeBase, !fromUse)].every(
471-
(v) => !tree.exists(v),
472-
) &&
473-
[...potentialSassImports(specifier, '/', !fromUse)].some((v) => tree.exists(v))
474-
) {
475-
needWorkspaceIncludePath = true;
476-
}
477-
}
478-
if (updater) {
479-
tree.commitUpdate(updater);
480-
}
481-
}
482-
483-
if (needWorkspaceIncludePath) {
484-
buildTarget.options ??= {};
485-
buildTarget.options['stylePreprocessorOptions'] ??= {};
486-
((buildTarget.options['stylePreprocessorOptions'] as { includePaths?: string[] })[
487-
'includePaths'
488-
] ??= []).push('.');
489-
}
490-
491-
if (external.size > 0) {
492-
buildTarget.options ??= {};
493-
((buildTarget.options['externalDependencies'] as string[] | undefined) ??= []).push(
494-
...external,
495-
);
496-
}
497-
}
498-
499339
function deleteFile(path: string): Rule {
500340
return (tree) => {
501341
tree.delete(path);

0 commit comments

Comments
 (0)