Skip to content

Commit 4f6bf3a

Browse files
crisbetowagnermaciel
authored andcommitted
fix(material/schematics): replace removed variables with their values in sass api migration (#22505)
The new Sass API removes some variables that had been previously exported by accident. These changes expand the migration so that usages of those variables are replaced with the values. The replacement doesn't cover variable assignments, because migrating them is impossible. (cherry picked from commit 04d2f77)
1 parent aae47b7 commit 4f6bf3a

File tree

3 files changed

+277
-89
lines changed

3 files changed

+277
-89
lines changed
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
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.io/license
7+
*/
8+
9+
/** Mapping of Material mixins that should be renamed. */
10+
export const materialMixins: Record<string, string> = {
11+
'mat-core': 'core',
12+
'mat-core-color': 'core-color',
13+
'mat-core-theme': 'core-theme',
14+
'angular-material-theme': 'all-component-themes',
15+
'angular-material-typography': 'all-component-typographies',
16+
'angular-material-color': 'all-component-colors',
17+
'mat-base-typography': 'typography-hierarchy',
18+
'mat-typography-level-to-styles': 'typography-level',
19+
'mat-elevation': 'elevation',
20+
'mat-overridable-elevation': 'overridable-elevation',
21+
'mat-elevation-transition': 'elevation-transition',
22+
'mat-ripple': 'ripple',
23+
'mat-ripple-color': 'ripple-color',
24+
'mat-ripple-theme': 'ripple-theme',
25+
'mat-strong-focus-indicators': 'strong-focus-indicators',
26+
'mat-strong-focus-indicators-color': 'strong-focus-indicators-color',
27+
'mat-strong-focus-indicators-theme': 'strong-focus-indicators-theme',
28+
'mat-font-shorthand': 'font-shorthand',
29+
// The expansion panel is a special case, because the package is called `expansion`, but the
30+
// mixins were prefixed with `expansion-panel`. This was corrected by the Sass module migration.
31+
'mat-expansion-panel-theme': 'expansion-theme',
32+
'mat-expansion-panel-color': 'expansion-color',
33+
'mat-expansion-panel-typography': 'expansion-typography',
34+
};
35+
36+
// The component themes all follow the same pattern so we can spare ourselves some typing.
37+
[
38+
'option', 'optgroup', 'pseudo-checkbox', 'autocomplete', 'badge', 'bottom-sheet', 'button',
39+
'button-toggle', 'card', 'checkbox', 'chips', 'divider', 'table', 'datepicker', 'dialog',
40+
'grid-list', 'icon', 'input', 'list', 'menu', 'paginator', 'progress-bar', 'progress-spinner',
41+
'radio', 'select', 'sidenav', 'slide-toggle', 'slider', 'stepper', 'sort', 'tabs', 'toolbar',
42+
'tooltip', 'snack-bar', 'form-field', 'tree'
43+
].forEach(name => {
44+
materialMixins[`mat-${name}-theme`] = `${name}-theme`;
45+
materialMixins[`mat-${name}-color`] = `${name}-color`;
46+
materialMixins[`mat-${name}-typography`] = `${name}-typography`;
47+
});
48+
49+
/** Mapping of Material functions that should be renamed. */
50+
export const materialFunctions: Record<string, string> = {
51+
'mat-color': 'get-color-from-palette',
52+
'mat-contrast': 'get-contrast-color-from-palette',
53+
'mat-palette': 'define-palette',
54+
'mat-dark-theme': 'define-dark-theme',
55+
'mat-light-theme': 'define-light-theme',
56+
'mat-typography-level': 'define-typography-level',
57+
'mat-typography-config': 'define-typography-config',
58+
'mat-font-size': 'font-size',
59+
'mat-line-height': 'line-height',
60+
'mat-font-weight': 'font-weight',
61+
'mat-letter-spacing': 'letter-spacing',
62+
'mat-font-family': 'font-family',
63+
};
64+
65+
/** Mapping of Material variables that should be renamed. */
66+
export const materialVariables: Record<string, string> = {
67+
'mat-light-theme-background': 'light-theme-background-palette',
68+
'mat-dark-theme-background': 'dark-theme-background-palette',
69+
'mat-light-theme-foreground': 'light-theme-foreground-palette',
70+
'mat-dark-theme-foreground': 'dark-theme-foreground-palette',
71+
};
72+
73+
// The palettes all follow the same pattern.
74+
[
75+
'red', 'pink', 'indigo', 'purple', 'deep-purple', 'blue', 'light-blue', 'cyan', 'teal', 'green',
76+
'light-green', 'lime', 'yellow', 'amber', 'orange', 'deep-orange', 'brown', 'grey', 'gray',
77+
'blue-grey', 'blue-gray'
78+
].forEach(name => materialVariables[`mat-${name}`] = `${name}-palette`);
79+
80+
/** Mapping of CDK variables that should be renamed. */
81+
export const cdkVariables: Record<string, string> = {
82+
'cdk-z-index-overlay-container': 'overlay-container-z-index',
83+
'cdk-z-index-overlay': 'overlay-z-index',
84+
'cdk-z-index-overlay-backdrop': 'overlay-backdrop-z-index',
85+
'cdk-overlay-dark-backdrop-background': 'overlay-backdrop-color',
86+
};
87+
88+
/** Mapping of CDK mixins that should be renamed. */
89+
export const cdkMixins: Record<string, string> = {
90+
'cdk-overlay': 'overlay',
91+
'cdk-a11y': 'a11y-visually-hidden',
92+
'cdk-high-contrast': 'high-contrast',
93+
'cdk-text-field-autofill-color': 'text-field-autofill-color',
94+
// This one was split up into two mixins which is trickier to
95+
// migrate so for now we forward to the deprecated variant.
96+
'cdk-text-field': 'text-field',
97+
};
98+
99+
/**
100+
* Material variables that have been removed from the public API
101+
* and which should be replaced with their values.
102+
*/
103+
export const removedMaterialVariables: Record<string, string> = {
104+
// Note: there's also a usage of a variable called `$pi`, but the name is short enough that
105+
// 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'`,
108+
'mat-toggle-padding': '8px',
109+
'mat-toggle-size': '20px',
110+
'mat-linear-out-slow-in-timing-function': 'cubic-bezier(0, 0, 0.2, 0.1)',
111+
'mat-fast-out-slow-in-timing-function': 'cubic-bezier(0.4, 0, 0.2, 1)',
112+
'mat-fast-out-linear-in-timing-function': 'cubic-bezier(0.4, 0, 1, 1)',
113+
'mat-elevation-transition-duration': '280ms',
114+
'mat-elevation-transition-timing-function': 'cubic-bezier(0.4, 0, 0.2, 1)',
115+
'mat-elevation-color': '#000',
116+
'mat-elevation-opacity': '1',
117+
'mat-elevation-prefix': `'mat-elevation-z'`,
118+
'mat-ripple-color-opacity': '0.1',
119+
'mat-badge-font-size': '12px',
120+
'mat-badge-font-weight': '600',
121+
'mat-badge-default-size': '22px',
122+
'mat-badge-small-size': '16px',
123+
'mat-badge-large-size': '28px',
124+
'mat-button-toggle-standard-height': '48px',
125+
'mat-button-toggle-standard-minimum-height': '24px',
126+
'mat-button-toggle-standard-maximum-height': '48px',
127+
'mat-chip-remove-font-size': '18px',
128+
'mat-datepicker-selected-today-box-shadow-width': '1px',
129+
'mat-datepicker-selected-fade-amount': '0.6',
130+
'mat-datepicker-range-fade-amount': '0.2',
131+
'mat-datepicker-today-fade-amount': '0.2',
132+
'mat-calendar-body-font-size': '13px',
133+
'mat-calendar-weekday-table-font-size': '11px',
134+
'mat-expansion-panel-header-collapsed-height': '48px',
135+
'mat-expansion-panel-header-collapsed-minimum-height': '36px',
136+
'mat-expansion-panel-header-collapsed-maximum-height': '48px',
137+
'mat-expansion-panel-header-expanded-height': '64px',
138+
'mat-expansion-panel-header-expanded-minimum-height': '48px',
139+
'mat-expansion-panel-header-expanded-maximum-height': '64px',
140+
'mat-expansion-panel-header-transition': '225ms cubic-bezier(0.4, 0, 0.2, 1)',
141+
'mat-paginator-height': '56px',
142+
'mat-paginator-minimum-height': '40px',
143+
'mat-paginator-maximum-height': '56px',
144+
'mat-stepper-header-height': '72px',
145+
'mat-stepper-header-minimum-height': '42px',
146+
'mat-stepper-header-maximum-height': '72px',
147+
'mat-stepper-label-header-height': '24px',
148+
'mat-stepper-label-position-bottom-top-gap': '16px',
149+
'mat-stepper-label-min-width': '50px',
150+
'mat-vertical-stepper-content-margin': '36px',
151+
'mat-stepper-side-gap': '24px',
152+
'mat-stepper-line-width': '1px',
153+
'mat-stepper-line-gap': '8px',
154+
'mat-step-sub-label-font-size': '12px',
155+
'mat-step-header-icon-size': '16px',
156+
'mat-toolbar-minimum-height': '44px',
157+
'mat-toolbar-height-desktop': '64px',
158+
'mat-toolbar-maximum-height-desktop': '64px',
159+
'mat-toolbar-minimum-height-desktop': '44px',
160+
'mat-toolbar-height-mobile': '56px',
161+
'mat-toolbar-maximum-height-mobile': '56px',
162+
'mat-toolbar-minimum-height-mobile': '44px',
163+
'mat-tooltip-target-height': '22px',
164+
'mat-tooltip-font-size': '10px',
165+
'mat-tooltip-vertical-padding': '6px',
166+
'mat-tooltip-handset-target-height': '30px',
167+
'mat-tooltip-handset-font-size': '14px',
168+
'mat-tooltip-handset-vertical-padding': '8px',
169+
'mat-tree-node-height': '48px',
170+
'mat-tree-node-minimum-height': '24px',
171+
'mat-tree-node-maximum-height': '48px',
172+
'z-index-fab': '20',
173+
'z-index-drawer': '100',
174+
'ease-in-out-curve-function': 'cubic-bezier(0.35, 0, 0.25, 1)',
175+
'swift-ease-out-duration': '400ms',
176+
'swift-ease-out-timing-function': 'cubic-bezier(0.25, 0.8, 0.25, 1)',
177+
'swift-ease-out': 'all 400ms cubic-bezier(0.25, 0.8, 0.25, 1)',
178+
'swift-ease-in-duration': '300ms',
179+
'swift-ease-in-timing-function': 'cubic-bezier(0.55, 0, 0.55, 0.2)',
180+
'swift-ease-in': 'all 300ms cubic-bezier(0.55, 0, 0.55, 0.2)',
181+
'swift-ease-in-out-duration': '500ms',
182+
'swift-ease-in-out-timing-function': 'cubic-bezier(0.35, 0, 0.25, 1)',
183+
'swift-ease-in-out': 'all 500ms cubic-bezier(0.35, 0, 0.25, 1)',
184+
'swift-linear-duration': '80ms',
185+
'swift-linear-timing-function': 'linear',
186+
'swift-linear': 'all 80ms linear'
187+
};

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

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,5 +505,70 @@ describe('Material theming API schematic', () => {
505505
]);
506506
});
507507

508+
it('should replace removed variables with their values', async () => {
509+
const app = await createTestApp(runner);
510+
app.create('/theme.scss', [
511+
`@import '~@angular/material/theming';`,
512+
``,
513+
`@include mat-button-toggle-theme();`,
514+
``,
515+
516+
`.my-button-toggle {`,
517+
`height: $mat-button-toggle-standard-height + 10px;`,
518+
`transition: $swift-ease-out;`,
519+
`}`,
520+
``,
521+
`@media ($mat-small) {`,
522+
`.my-button-toggle {`,
523+
`height: $mat-button-toggle-standard-minimum-height;`,
524+
`}`,
525+
`}`
526+
].join('\n'));
527+
528+
const tree = await runner.runSchematicAsync('theming-api', options, app).toPromise();
529+
expect(getFileContent(tree, '/theme.scss').split('\n')).toEqual([
530+
`@use '~@angular/material' as mat;`,
531+
``,
532+
`@include mat.button-toggle-theme();`,
533+
``,
534+
535+
`.my-button-toggle {`,
536+
`height: 48px + 10px;`,
537+
`transition: all 400ms cubic-bezier(0.25, 0.8, 0.25, 1);`,
538+
`}`,
539+
``,
540+
`@media ('max-width: 959px') {`,
541+
`.my-button-toggle {`,
542+
`height: 24px;`,
543+
`}`,
544+
`}`
545+
]);
546+
});
547+
548+
it('should not replace assignments to removed variables', async () => {
549+
const app = await createTestApp(runner);
550+
app.create('/theme.scss', [
551+
`@import '~@angular/material/theming';`,
552+
``,
553+
`$mat-button-toggle-standard-height: 50px;`,
554+
`$mat-button-toggle-standard-minimum-height : 12px;`,
555+
`$mat-toggle-padding:10px;`,
556+
`$mat-toggle-size: 11px;`,
557+
``,
558+
`@include mat-button-toggle-theme();`,
559+
].join('\n'));
560+
561+
const tree = await runner.runSchematicAsync('theming-api', options, app).toPromise();
562+
expect(getFileContent(tree, '/theme.scss').split('\n')).toEqual([
563+
`@use '~@angular/material' as mat;`,
564+
``,
565+
`$mat-button-toggle-standard-height: 50px;`,
566+
`$mat-button-toggle-standard-minimum-height : 12px;`,
567+
`$mat-toggle-padding:10px;`,
568+
`$mat-toggle-size: 11px;`,
569+
``,
570+
`@include mat.button-toggle-theme();`,
571+
]);
572+
});
508573

509574
});

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

Lines changed: 25 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -6,95 +6,14 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
/** Mapping of Material mixins that should be renamed. */
10-
const materialMixins: Record<string, string> = {
11-
'mat-core': 'core',
12-
'mat-core-color': 'core-color',
13-
'mat-core-theme': 'core-theme',
14-
'angular-material-theme': 'all-component-themes',
15-
'angular-material-typography': 'all-component-typographies',
16-
'angular-material-color': 'all-component-colors',
17-
'mat-base-typography': 'typography-hierarchy',
18-
'mat-typography-level-to-styles': 'typography-level',
19-
'mat-elevation': 'elevation',
20-
'mat-overridable-elevation': 'overridable-elevation',
21-
'mat-elevation-transition': 'elevation-transition',
22-
'mat-ripple': 'ripple',
23-
'mat-ripple-color': 'ripple-color',
24-
'mat-ripple-theme': 'ripple-theme',
25-
'mat-strong-focus-indicators': 'strong-focus-indicators',
26-
'mat-strong-focus-indicators-color': 'strong-focus-indicators-color',
27-
'mat-strong-focus-indicators-theme': 'strong-focus-indicators-theme',
28-
'mat-font-shorthand': 'font-shorthand',
29-
// The expansion panel is a special case, because the package is called `expansion`, but the
30-
// mixins were prefixed with `expansion-panel`. This was corrected by the Sass module migration.
31-
'mat-expansion-panel-theme': 'expansion-theme',
32-
'mat-expansion-panel-color': 'expansion-color',
33-
'mat-expansion-panel-typography': 'expansion-typography',
34-
};
35-
36-
// The component themes all follow the same pattern so we can spare ourselves some typing.
37-
[
38-
'option', 'optgroup', 'pseudo-checkbox', 'autocomplete', 'badge', 'bottom-sheet', 'button',
39-
'button-toggle', 'card', 'checkbox', 'chips', 'divider', 'table', 'datepicker', 'dialog',
40-
'grid-list', 'icon', 'input', 'list', 'menu', 'paginator', 'progress-bar', 'progress-spinner',
41-
'radio', 'select', 'sidenav', 'slide-toggle', 'slider', 'stepper', 'sort', 'tabs', 'toolbar',
42-
'tooltip', 'snack-bar', 'form-field', 'tree'
43-
].forEach(name => {
44-
materialMixins[`mat-${name}-theme`] = `${name}-theme`;
45-
materialMixins[`mat-${name}-color`] = `${name}-color`;
46-
materialMixins[`mat-${name}-typography`] = `${name}-typography`;
47-
});
48-
49-
/** Mapping of Material functions that should be renamed. */
50-
const materialFunctions: Record<string, string> = {
51-
'mat-color': 'get-color-from-palette',
52-
'mat-contrast': 'get-contrast-color-from-palette',
53-
'mat-palette': 'define-palette',
54-
'mat-dark-theme': 'define-dark-theme',
55-
'mat-light-theme': 'define-light-theme',
56-
'mat-typography-level': 'define-typography-level',
57-
'mat-typography-config': 'define-typography-config',
58-
'mat-font-size': 'font-size',
59-
'mat-line-height': 'line-height',
60-
'mat-font-weight': 'font-weight',
61-
'mat-letter-spacing': 'letter-spacing',
62-
'mat-font-family': 'font-family',
63-
};
64-
65-
/** Mapping of Material variables that should be renamed. */
66-
const materialVariables: Record<string, string> = {
67-
'mat-light-theme-background': 'light-theme-background-palette',
68-
'mat-dark-theme-background': 'dark-theme-background-palette',
69-
'mat-light-theme-foreground': 'light-theme-foreground-palette',
70-
'mat-dark-theme-foreground': 'dark-theme-foreground-palette',
71-
};
72-
73-
// The palettes all follow the same pattern.
74-
[
75-
'red', 'pink', 'indigo', 'purple', 'deep-purple', 'blue', 'light-blue', 'cyan', 'teal', 'green',
76-
'light-green', 'lime', 'yellow', 'amber', 'orange', 'deep-orange', 'brown', 'grey', 'gray',
77-
'blue-grey', 'blue-gray'
78-
].forEach(name => materialVariables[`mat-${name}`] = `${name}-palette`);
79-
80-
/** Mapping of CDK variables that should be renamed. */
81-
const cdkVariables: Record<string, string> = {
82-
'cdk-z-index-overlay-container': 'overlay-container-z-index',
83-
'cdk-z-index-overlay': 'overlay-z-index',
84-
'cdk-z-index-overlay-backdrop': 'overlay-backdrop-z-index',
85-
'cdk-overlay-dark-backdrop-background': 'overlay-backdrop-color',
86-
};
87-
88-
/** Mapping of CDK mixins that should be renamed. */
89-
const cdkMixins: Record<string, string> = {
90-
'cdk-overlay': 'overlay',
91-
'cdk-a11y': 'a11y-visually-hidden',
92-
'cdk-high-contrast': 'high-contrast',
93-
'cdk-text-field-autofill-color': 'text-field-autofill-color',
94-
// This one was split up into two mixins which is trickier to
95-
// migrate so for now we forward to the deprecated variant.
96-
'cdk-text-field': 'text-field',
97-
};
9+
import {
10+
materialMixins,
11+
materialFunctions,
12+
materialVariables,
13+
cdkMixins,
14+
cdkVariables,
15+
removedMaterialVariables
16+
} from './config';
9817

9918
/**
10019
* Migrates the content of a file to the new theming API. Note that this migration is using plain
@@ -129,6 +48,7 @@ export function migrateFileContent(content: string,
12948
content = removeStrings(content, materialResults.imports);
13049
content = removeStrings(content, cdkResults.imports);
13150
content = content.replace(/^\s+/, '');
51+
content = replaceRemovedVariables(content, removedMaterialVariables);
13252
}
13353
}
13454

@@ -346,3 +266,19 @@ function extractNamespaceFromUseStatement(fullImport: string): string {
346266

347267
throw Error(`Could not extract namespace from import "${fullImport}".`);
348268
}
269+
270+
/**
271+
* Replaces variables that have been removed with their values.
272+
* @param content Content of the file to be migrated.
273+
* @param variables Mapping between variable names and their values.
274+
*/
275+
function replaceRemovedVariables(content: string, variables: Record<string, string>): string {
276+
Object.keys(variables).sort(sortLengthDescending).forEach(variableName => {
277+
// Note that the pattern uses a negative lookahead to exclude
278+
// variable assignments, because they can't be migrated.
279+
const regex = new RegExp(`\\$${escapeRegExp(variableName)}(?!\\s+:|:)`, 'g');
280+
content = content.replace(regex, variables[variableName]);
281+
});
282+
283+
return content;
284+
}

0 commit comments

Comments
 (0)