ember-scoped-css 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/declarations/lib/css/rewrite.d.ts +2 -0
- package/declarations/lib/css/rewrite.d.ts.map +1 -0
- package/declarations/lib/css/rewrite.test.d.ts +2 -0
- package/declarations/lib/css/rewrite.test.d.ts.map +1 -0
- package/declarations/lib/css/utils.d.ts +29 -0
- package/declarations/lib/css/utils.d.ts.map +1 -0
- package/dist/cjs/index.cjs +80 -5
- package/dist/cjs/template-plugin.cjs +79 -4
- package/package.json +3 -3
- package/src/lib/css/rewrite.js +138 -55
- package/src/lib/css/rewrite.test.ts +648 -0
- package/src/lib/request.js +1 -1
package/src/lib/css/rewrite.js
CHANGED
|
@@ -1,14 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Important docs:
|
|
3
|
+
* - https://developer.mozilla.org/en-US/docs/Web/CSS/
|
|
4
|
+
*/
|
|
1
5
|
import postcss from 'postcss';
|
|
2
6
|
import parser from 'postcss-selector-parser';
|
|
3
7
|
|
|
4
8
|
import { isInsideGlobal } from './utils.js';
|
|
5
9
|
|
|
10
|
+
const SEP = '__';
|
|
11
|
+
|
|
12
|
+
function isRule(node) {
|
|
13
|
+
return node.type === 'rule';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function isDeclaration(node) {
|
|
17
|
+
return node.type === 'decl';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* NOTE: "keyframes" is a singular definition, in that it's a block containing keyframes
|
|
22
|
+
* using `@keyframes {}` with only one thing on the inside doesn't make sense.
|
|
23
|
+
*/
|
|
24
|
+
function rewriteReferencable(node, postfix) {
|
|
25
|
+
let originalName = node.params;
|
|
26
|
+
let postfixedName = node.params + SEP + postfix;
|
|
27
|
+
|
|
28
|
+
node.params = postfixedName;
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
originalName,
|
|
32
|
+
postfixedName,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
6
36
|
function rewriteSelector(sel, postfix) {
|
|
7
37
|
const transform = (selectors) => {
|
|
8
38
|
selectors.walk((selector) => {
|
|
9
|
-
if (
|
|
39
|
+
if (isInsideGlobal(selector)) return;
|
|
40
|
+
|
|
41
|
+
// We never want to touch psuedo selectors since we and the user doesn't own them.
|
|
42
|
+
if (selector.type === 'psuedo') return;
|
|
43
|
+
|
|
44
|
+
// :nth-of-type has special syntax where the values passed to nth-of-type()
|
|
45
|
+
// must either be exactly "odd", "even", or a simple formula
|
|
46
|
+
//
|
|
47
|
+
// https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-of-type
|
|
48
|
+
if (isNthOfType(selector)) return;
|
|
49
|
+
|
|
50
|
+
if (selector.type === 'class') {
|
|
10
51
|
selector.value += '_' + postfix;
|
|
11
|
-
} else if (selector.type === 'tag'
|
|
52
|
+
} else if (selector.type === 'tag') {
|
|
12
53
|
selector.replaceWith(
|
|
13
54
|
parser.tag({ value: selector.value }),
|
|
14
55
|
parser.className({ value: postfix }),
|
|
@@ -28,6 +69,12 @@ function rewriteSelector(sel, postfix) {
|
|
|
28
69
|
return transformed;
|
|
29
70
|
}
|
|
30
71
|
|
|
72
|
+
function isNthOfType(node) {
|
|
73
|
+
if (!node) return false;
|
|
74
|
+
|
|
75
|
+
return node.parent?.value === ':nth-of-type' || isNthOfType(node.parent);
|
|
76
|
+
}
|
|
77
|
+
|
|
31
78
|
function isInsideKeyframes(node) {
|
|
32
79
|
const parent = node.parent;
|
|
33
80
|
|
|
@@ -40,75 +87,111 @@ function isInsideKeyframes(node) {
|
|
|
40
87
|
export function rewriteCss(css, postfix, fileName, layerName) {
|
|
41
88
|
const layerNameWithDefault = layerName ?? 'components';
|
|
42
89
|
const ast = postcss.parse(css);
|
|
90
|
+
/**
|
|
91
|
+
* kind => originalName => postfixedName
|
|
92
|
+
* @type {{ [kind: string]: { [originalName: string]: string }}}
|
|
93
|
+
*/
|
|
94
|
+
const referencables = {
|
|
95
|
+
keyframes: {},
|
|
96
|
+
'counter-style': {},
|
|
97
|
+
'position-try': {},
|
|
98
|
+
property: {},
|
|
99
|
+
};
|
|
43
100
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
101
|
+
const availableReferencables = new Set(Object.keys(referencables));
|
|
102
|
+
|
|
103
|
+
function isReferencable(node) {
|
|
104
|
+
if (node.type !== 'atrule') return;
|
|
105
|
+
|
|
106
|
+
return availableReferencables.has(node.name);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function updateDirectReferences(node) {
|
|
110
|
+
if (!node.value) return;
|
|
111
|
+
|
|
112
|
+
for (let [, map] of Object.entries(referencables)) {
|
|
113
|
+
if (map[node.value]) {
|
|
114
|
+
node.value = map[node.value];
|
|
115
|
+
}
|
|
47
116
|
}
|
|
48
|
-
}
|
|
117
|
+
}
|
|
49
118
|
|
|
50
|
-
|
|
119
|
+
function updateShorthandContents(node) {
|
|
120
|
+
if (node.prop === 'animation') {
|
|
121
|
+
let parts = node.value.split(' ');
|
|
122
|
+
let match = parts.filter((x) => referencables.keyframes[x]);
|
|
51
123
|
|
|
52
|
-
|
|
53
|
-
|
|
124
|
+
if (match.length) {
|
|
125
|
+
match.forEach((x) => {
|
|
126
|
+
let replacement = referencables.keyframes[x];
|
|
127
|
+
|
|
128
|
+
if (!replacement) return;
|
|
129
|
+
|
|
130
|
+
node.value = node.value.replace(x, replacement);
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
for (let [lookFor, replaceWith] of Object.entries(referencables.property)) {
|
|
136
|
+
let lookForVar = `var(${lookFor})`;
|
|
137
|
+
let replaceWithVar = `var(${replaceWith})`;
|
|
138
|
+
|
|
139
|
+
node.value = node.value.replace(lookForVar, replaceWithVar);
|
|
140
|
+
}
|
|
54
141
|
}
|
|
55
142
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
143
|
+
/**
|
|
144
|
+
* We have to do two passes:
|
|
145
|
+
* 1. postfix all the referencable syntax
|
|
146
|
+
* 2. postfix as normal, but also checking values of CSS properties
|
|
147
|
+
* that could match postfixed referencables from step 1
|
|
148
|
+
*/
|
|
62
149
|
|
|
63
|
-
|
|
64
|
-
|
|
150
|
+
// Step 1: find referencables
|
|
151
|
+
ast.walk((node) => {
|
|
152
|
+
/**
|
|
153
|
+
* @keyframes, @counter-style, etc
|
|
154
|
+
*/
|
|
155
|
+
if (isReferencable(node)) {
|
|
156
|
+
let name = node.name;
|
|
157
|
+
let { originalName, postfixedName } = rewriteReferencable(node, postfix);
|
|
65
158
|
|
|
66
|
-
|
|
67
|
-
const css = '.foo { color: red; }';
|
|
68
|
-
const postfix = 'postfix';
|
|
69
|
-
const fileName = 'foo.css';
|
|
70
|
-
const rewritten = rewriteCss(css, postfix, fileName, false);
|
|
159
|
+
referencables[name][originalName] = postfixedName;
|
|
71
160
|
|
|
72
|
-
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
73
163
|
});
|
|
74
164
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
165
|
+
// Step 2: postfix and update refenced referencables
|
|
166
|
+
ast.walk((node) => {
|
|
167
|
+
if (isDeclaration(node)) {
|
|
168
|
+
updateDirectReferences(node);
|
|
169
|
+
updateShorthandContents(node);
|
|
80
170
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (isRule(node)) {
|
|
175
|
+
/**
|
|
176
|
+
* The inner-contents of a keyframe are percentages, rather than selectors
|
|
177
|
+
*/
|
|
178
|
+
if (isInsideKeyframes(node)) return;
|
|
85
179
|
|
|
86
|
-
|
|
87
|
-
const css = '.baz :global(.foo p) .bar { color: red; }';
|
|
88
|
-
const postfix = 'postfix';
|
|
89
|
-
const fileName = 'foo.css';
|
|
90
|
-
const rewritten = rewriteCss(css, postfix, fileName);
|
|
180
|
+
node.selector = rewriteSelector(node.selector, postfix);
|
|
91
181
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
95
184
|
});
|
|
96
185
|
|
|
97
|
-
|
|
98
|
-
const css = `
|
|
99
|
-
@keyframes luna-view-navigation {
|
|
100
|
-
100% {
|
|
101
|
-
padding-top: 1rem;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
`;
|
|
186
|
+
const rewrittenCss = ast.toString();
|
|
105
187
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
188
|
+
if (!layerNameWithDefault) {
|
|
189
|
+
return `/* ${fileName} */\n${rewrittenCss}\n`;
|
|
190
|
+
}
|
|
109
191
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
192
|
+
return (
|
|
193
|
+
`/* ${fileName} */\n@layer ${layerNameWithDefault} {\n\n` +
|
|
194
|
+
rewrittenCss +
|
|
195
|
+
'\n}\n'
|
|
196
|
+
);
|
|
114
197
|
}
|