Skip to content

Commit 94bb518

Browse files
authored
fix(material/schematics): migrate more cases in the theming API schematic (#22604)
Includes the following improvements to the `themingApi` schematic: 1. No longer runs against files in the `node_modules`. This was happening by accident. 2. Remove the quotes around the values of `$mat-small` and `$mat-xsmall` since they were causing Sass syntax errors. 3. Migrates Material/CDK symbols, even if there are no imports for the old theming bundle. This allows us to handle symbols that were imported transitively. 4. Reverts the logic from #22438 that doesn't drop imports if there are no Material/CDK symbol usages within the file. I think that we want to do this after all, because the old import could slow down build times and we can be relatively certain that any usages have been migrated. Fixes #22599.
1 parent 5f1f4a1 commit 94bb518

File tree

4 files changed

+58
-21
lines changed

4 files changed

+58
-21
lines changed

src/material/schematics/ng-generate/theming-api/config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,8 @@ export const cdkMixins: Record<string, string> = {
103103
export const removedMaterialVariables: Record<string, string> = {
104104
// Note: there's also a usage of a variable called `$pi`, but the name is short enough that
105105
// it matches things like `$mat-pink`. Don't migrate it since it's unlikely to be used.
106-
'mat-xsmall': `'max-width: 599px'`,
107-
'mat-small': `'max-width: 959px'`,
106+
'mat-xsmall': 'max-width: 599px',
107+
'mat-small': 'max-width: 959px',
108108
'mat-toggle-padding': '8px',
109109
'mat-toggle-size': '20px',
110110
'mat-linear-out-slow-in-timing-function': 'cubic-bezier(0, 0, 0.2, 0.1)',

src/material/schematics/ng-generate/theming-api/index.spec.ts

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,23 @@ describe('Material theming API schematic', () => {
195195
]);
196196
});
197197

198+
it('should migrate files that import the Material APIs transitively', async () => {
199+
const app = await createTestApp(runner);
200+
app.create('/theme.scss', [
201+
`@import 're-exports-material-symbols';`,
202+
`@include mat-core();`,
203+
`@include mat-button-theme();`,
204+
].join('\n'));
205+
206+
const tree = await runner.runSchematicAsync('theming-api', options, app).toPromise();
207+
expect(getFileContent(tree, '/theme.scss').split('\n')).toEqual([
208+
`@use '~@angular/material' as mat;`,
209+
`@import 're-exports-material-symbols';`,
210+
`@include mat.core();`,
211+
`@include mat.button-theme();`,
212+
]);
213+
});
214+
198215
it('should allow an arbitrary number of spaces after @include and @import', async () => {
199216
const app = await createTestApp(runner);
200217
app.create('/theme.scss', [
@@ -485,7 +502,7 @@ describe('Material theming API schematic', () => {
485502
]);
486503
});
487504

488-
it('should not change files if they have an import, but do not use any symbols', async () => {
505+
it('should drop the old import path even if the file is not using any symbols', async () => {
489506
const app = await createTestApp(runner);
490507
app.create('/theme.scss', [
491508
`@import '~@angular/material/theming';`,
@@ -497,8 +514,6 @@ describe('Material theming API schematic', () => {
497514

498515
const tree = await runner.runSchematicAsync('theming-api', options, app).toPromise();
499516
expect(getFileContent(tree, '/theme.scss').split('\n')).toEqual([
500-
`@import '~@angular/material/theming';`,
501-
``,
502517
`.my-dialog {`,
503518
`color: red;`,
504519
`}`,
@@ -537,7 +552,7 @@ describe('Material theming API schematic', () => {
537552
`transition: all 400ms cubic-bezier(0.25, 0.8, 0.25, 1);`,
538553
`}`,
539554
``,
540-
`@media ('max-width: 959px') {`,
555+
`@media (max-width: 959px) {`,
541556
`.my-button-toggle {`,
542557
`height: 24px;`,
543558
`}`,
@@ -571,4 +586,22 @@ describe('Material theming API schematic', () => {
571586
]);
572587
});
573588

589+
it('should not migrate files in the node_modules', async () => {
590+
const app = await createTestApp(runner);
591+
app.create('/node_modules/theme.scss', [
592+
`@import '~@angular/material/theming';`,
593+
``,
594+
`@include mat-button-toggle-theme();`,
595+
``,
596+
].join('\n'));
597+
598+
const tree = await runner.runSchematicAsync('theming-api', options, app).toPromise();
599+
expect(getFileContent(tree, '/node_modules/theme.scss').split('\n')).toEqual([
600+
`@import '~@angular/material/theming';`,
601+
``,
602+
`@include mat-button-toggle-theme();`,
603+
``,
604+
]);
605+
});
606+
574607
});

src/material/schematics/ng-generate/theming-api/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {migrateFileContent} from './migration';
1414
export default function(_options: Schema): Rule {
1515
return (tree: Tree) => {
1616
tree.visit((path, entry) => {
17-
if (extname(path) === '.scss') {
17+
if (extname(path) === '.scss' && path.indexOf('node_modules') === -1) {
1818
const content = entry?.content.toString();
1919
const migratedContent = content ? migrateFileContent(content,
2020
'~@angular/material/', '~@angular/cdk/', '~@angular/material', '~@angular/cdk') : content;

src/material/schematics/ng-generate/theming-api/migration.ts

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,21 @@ export function migrateFileContent(content: string,
3737
const materialResults = detectImports(content, oldMaterialPrefix);
3838
const cdkResults = detectImports(content, oldCdkPrefix);
3939

40-
// If there are no imports, we don't need to go further.
41-
if (materialResults.imports.length > 0 || cdkResults.imports.length > 0) {
42-
const initialContent = content;
43-
content = migrateMaterialSymbols(content, newMaterialImportPath, materialResults.namespaces);
44-
content = migrateCdkSymbols(content, newCdkImportPath, cdkResults.namespaces);
45-
46-
// Only drop the imports if any of the symbols were used within the file.
47-
if (content !== initialContent) {
48-
content = removeStrings(content, materialResults.imports);
49-
content = removeStrings(content, cdkResults.imports);
50-
content = content.replace(/^\s+/, '');
51-
content = replaceRemovedVariables(content, removedMaterialVariables);
52-
}
40+
// Try to migrate the symbols even if there are no imports. This is used
41+
// to cover the case where the Components symbols were used transitively.
42+
content = migrateMaterialSymbols(content, newMaterialImportPath, materialResults.namespaces);
43+
content = migrateCdkSymbols(content, newCdkImportPath, cdkResults.namespaces);
44+
content = replaceRemovedVariables(content, removedMaterialVariables);
45+
46+
// We can assume that the migration has taken care of any Components symbols that were
47+
// imported transitively so we can always drop the old imports. We also assume that imports
48+
// to the new entry points have been added already.
49+
if (materialResults.imports.length) {
50+
content = removeStrings(content, materialResults.imports);
51+
}
52+
53+
if (cdkResults.imports.length) {
54+
content = removeStrings(content, cdkResults.imports);
5355
}
5456

5557
return content;
@@ -227,7 +229,9 @@ function sortLengthDescending(a: string, b: string) {
227229

228230
/** Removes all strings from another string. */
229231
function removeStrings(content: string, toRemove: string[]): string {
230-
return toRemove.reduce((accumulator, current) => accumulator.replace(current, ''), content);
232+
return toRemove
233+
.reduce((accumulator, current) => accumulator.replace(current, ''), content)
234+
.replace(/^\s+/, '');
231235
}
232236

233237
/** Parses out the namespace from a Sass `@use` statement. */

0 commit comments

Comments
 (0)