-
Notifications
You must be signed in to change notification settings - Fork 6.7k
/
theming-styles.ts
99 lines (87 loc) · 3.13 KB
/
theming-styles.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Migration, ResolvedResource} from '@angular/cdk/schematics';
import {SchematicContext} from '@angular-devkit/schematics';
import * as postcss from 'postcss';
import * as scss from 'postcss-scss';
import {ComponentMigrator} from '.';
export class ThemingStylesMigration extends Migration<ComponentMigrator[], SchematicContext> {
enabled = true;
namespace: string;
override visitStylesheet(stylesheet: ResolvedResource) {
this.fileSystem
.edit(stylesheet.filePath)
.remove(stylesheet.start, stylesheet.content.length)
.insertRight(stylesheet.start, this.migrate(stylesheet.content));
}
migrate(styles: string): string {
const processor = new postcss.Processor([
{
postcssPlugin: 'theming-styles-migration-plugin',
AtRule: {
use: this.atUseHandler.bind(this),
include: this.atIncludeHandler.bind(this),
},
Rule: this.ruleHandler.bind(this),
},
]);
return processor.process(styles, {syntax: scss}).toString();
}
atUseHandler(atRule: postcss.AtRule) {
if (isAngularMaterialImport(atRule)) {
this.namespace = parseNamespace(atRule);
}
}
atIncludeHandler(atRule: postcss.AtRule) {
const migrator = this.upgradeData.find(m => {
return m.styles.isLegacyMixin(this.namespace, atRule);
});
if (migrator) {
migrator.styles.replaceMixin(this.namespace, atRule);
} else if (atRule.params.includes('all-legacy-component-themes') && atRule.parent) {
// We use an arbitrary migrator because searching for the right one
// doesn't matter since the all-component-theme mixin affects all
// components and it only needs to be replaced once.
this.upgradeData[0]?.styles.replaceAllComponentThemeMixin(atRule);
}
}
ruleHandler(rule: postcss.Rule) {
let isLegacySelector;
let isDeprecatedSelector;
const migrator = this.upgradeData.find(m => {
isLegacySelector = m.styles.isLegacySelector(rule);
isDeprecatedSelector = m.styles.isDeprecatedSelector(rule);
return isLegacySelector || isDeprecatedSelector;
});
if (isLegacySelector) {
migrator?.styles.replaceLegacySelector(rule);
} else if (isDeprecatedSelector) {
migrator?.styles.addDeprecatedSelectorComment(rule);
}
}
}
/**
* Returns whether the given AtRule is an import for @angular/material styles.
*
* @param atRule a postcss AtRule node.
* @returns true if the given AtRule is an import for @angular/material styles.
*/
function isAngularMaterialImport(atRule: postcss.AtRule): boolean {
const params = postcss.list.space(atRule.params);
return params[0] === "'@angular/material'";
}
/**
* Parses the given @use AtRule and returns the namespace being used.
*
* @param atRule a postcss @use AtRule.
* @returns the namespace being used.
*/
function parseNamespace(atRule: postcss.AtRule): string {
const params = postcss.list.space(atRule.params);
return params[params.length - 1];
}