postcss-nested 5.0.6 → 6.0.0
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 -111
- package/index.d.ts +9 -2
- package/index.js +231 -87
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -81,118 +81,10 @@ Alternatives:
|
|
|
81
81
|
[`postcss-current-selector`]: https://github.com/komlev/postcss-current-selector
|
|
82
82
|
[`postcss-nested-ancestors`]: https://github.com/toomuchdesign/postcss-nested-ancestors
|
|
83
83
|
[`postcss-nested-props`]: https://github.com/jedmao/postcss-nested-props
|
|
84
|
-
[`postcss-nesting`]: https://github.com/
|
|
84
|
+
[`postcss-nesting`]: https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-nesting
|
|
85
85
|
[CSSWG draft]: https://drafts.csswg.org/css-nesting-1/
|
|
86
86
|
[PostCSS]: https://github.com/postcss/postcss
|
|
87
87
|
|
|
88
88
|
|
|
89
|
-
##
|
|
90
|
-
|
|
91
|
-
**Step 1:** Install plugin:
|
|
92
|
-
|
|
93
|
-
```sh
|
|
94
|
-
npm install --save-dev postcss postcss-nested
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
**Step 2:** Check your project for existing PostCSS config: `postcss.config.js`
|
|
98
|
-
in the project root, `"postcss"` section in `package.json`
|
|
99
|
-
or `postcss` in bundle config.
|
|
100
|
-
|
|
101
|
-
If you do not use PostCSS, add it according to [official docs]
|
|
102
|
-
and set this plugin in settings.
|
|
103
|
-
|
|
104
|
-
**Step 3:** Add the plugin to plugins list:
|
|
105
|
-
|
|
106
|
-
```diff
|
|
107
|
-
module.exports = {
|
|
108
|
-
plugins: [
|
|
109
|
-
+ require('postcss-nested'),
|
|
110
|
-
require('autoprefixer')
|
|
111
|
-
]
|
|
112
|
-
}
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
[official docs]: https://github.com/postcss/postcss#usage
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
## Options
|
|
119
|
-
|
|
120
|
-
### `bubble`
|
|
121
|
-
|
|
122
|
-
By default, plugin will bubble only `@media` and `@supports` at-rules.
|
|
123
|
-
You can add your custom at-rules to this list by `bubble` option:
|
|
124
|
-
|
|
125
|
-
```js
|
|
126
|
-
postcss([ require('postcss-nested')({ bubble: ['phone'] }) ])
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
```css
|
|
130
|
-
/* input */
|
|
131
|
-
a {
|
|
132
|
-
color: white;
|
|
133
|
-
@phone {
|
|
134
|
-
color: black;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
/* output */
|
|
138
|
-
a {
|
|
139
|
-
color: white;
|
|
140
|
-
}
|
|
141
|
-
@phone {
|
|
142
|
-
a {
|
|
143
|
-
color: black;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
### `unwrap`
|
|
150
|
-
|
|
151
|
-
By default, plugin will unwrap only `@font-face`, `@keyframes` and `@document`
|
|
152
|
-
at-rules. You can add your custom at-rules to this list by `unwrap` option:
|
|
153
|
-
|
|
154
|
-
```js
|
|
155
|
-
postcss([ require('postcss-nested')({ unwrap: ['phone'] }) ])
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
```css
|
|
159
|
-
/* input */
|
|
160
|
-
a {
|
|
161
|
-
color: white;
|
|
162
|
-
@phone {
|
|
163
|
-
color: black;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
/* output */
|
|
167
|
-
a {
|
|
168
|
-
color: white;
|
|
169
|
-
}
|
|
170
|
-
@phone {
|
|
171
|
-
color: black;
|
|
172
|
-
}
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
### `preserveEmpty`
|
|
177
|
-
|
|
178
|
-
By default, plugin will strip out any empty selector generated by intermediate
|
|
179
|
-
nesting levels. You can set `preserveEmpty` to `true` to preserve them.
|
|
180
|
-
|
|
181
|
-
```css
|
|
182
|
-
.a {
|
|
183
|
-
.b {
|
|
184
|
-
color: black;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
Will be compiled to:
|
|
190
|
-
|
|
191
|
-
```css
|
|
192
|
-
.a { }
|
|
193
|
-
.a .b {
|
|
194
|
-
color: black;
|
|
195
|
-
}
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
This is especially useful if you want to export the empty classes with `postcss-modules`.
|
|
89
|
+
## Docs
|
|
90
|
+
Read **[full docs](https://github.com/postcss/postcss-nested#readme)** on GitHub.
|
package/index.d.ts
CHANGED
|
@@ -6,8 +6,8 @@ import { PluginCreator } from 'postcss'
|
|
|
6
6
|
declare namespace nested {
|
|
7
7
|
interface Options {
|
|
8
8
|
/**
|
|
9
|
-
* By default, plugin will bubble only `@media` and `@
|
|
10
|
-
*
|
|
9
|
+
* By default, plugin will bubble only `@media`, `@supports` and `@layer`
|
|
10
|
+
* at-rules. Use this option to add your custom at-rules to this list.
|
|
11
11
|
*/
|
|
12
12
|
bubble?: string[]
|
|
13
13
|
|
|
@@ -24,6 +24,13 @@ declare namespace nested {
|
|
|
24
24
|
* to preserve them.
|
|
25
25
|
*/
|
|
26
26
|
preserveEmpty?: boolean
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The plugin supports the SCSS custom at-rule `@at-root` which breaks
|
|
30
|
+
* rule blocks out of their nested position. If you want, you can choose
|
|
31
|
+
* a new custom name for this rule in your code.
|
|
32
|
+
*/
|
|
33
|
+
rootRuleName?: string
|
|
27
34
|
}
|
|
28
35
|
|
|
29
36
|
type Nested = PluginCreator<Options>
|
package/index.js
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
|
+
const { Rule, AtRule } = require('postcss')
|
|
1
2
|
let parser = require('postcss-selector-parser')
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Run a selector string through postcss-selector-parser
|
|
6
|
+
*/
|
|
7
|
+
function parse(rawSelector, rule) {
|
|
4
8
|
let nodes
|
|
5
|
-
let saver = parser(parsed => {
|
|
6
|
-
nodes = parsed
|
|
7
|
-
})
|
|
8
9
|
try {
|
|
9
|
-
|
|
10
|
+
parser(parsed => {
|
|
11
|
+
nodes = parsed
|
|
12
|
+
}).processSync(rawSelector)
|
|
10
13
|
} catch (e) {
|
|
11
|
-
if (
|
|
14
|
+
if (rawSelector.includes(':')) {
|
|
12
15
|
throw rule ? rule.error('Missed semicolon') : e
|
|
13
16
|
} else {
|
|
14
17
|
throw rule ? rule.error(e.message) : e
|
|
@@ -17,19 +20,27 @@ function parse (str, rule) {
|
|
|
17
20
|
return nodes.at(0)
|
|
18
21
|
}
|
|
19
22
|
|
|
20
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Replaces the "&" token in a node's selector with the parent selector
|
|
25
|
+
* similar to what SCSS does.
|
|
26
|
+
*
|
|
27
|
+
* Mutates the nodes list
|
|
28
|
+
*/
|
|
29
|
+
function interpolateAmpInSelector(nodes, parent) {
|
|
21
30
|
let replaced = false
|
|
22
|
-
nodes.each(
|
|
23
|
-
if (
|
|
24
|
-
let clonedParent = parent.clone()
|
|
25
|
-
if (
|
|
26
|
-
|
|
31
|
+
nodes.each(node => {
|
|
32
|
+
if (node.type === 'nesting') {
|
|
33
|
+
let clonedParent = parent.clone({})
|
|
34
|
+
if (node.value !== '&') {
|
|
35
|
+
node.replaceWith(
|
|
36
|
+
parse(node.value.replace('&', clonedParent.toString()))
|
|
37
|
+
)
|
|
27
38
|
} else {
|
|
28
|
-
|
|
39
|
+
node.replaceWith(clonedParent)
|
|
29
40
|
}
|
|
30
41
|
replaced = true
|
|
31
|
-
} else if (
|
|
32
|
-
if (
|
|
42
|
+
} else if ('nodes' in node && node.nodes) {
|
|
43
|
+
if (interpolateAmpInSelector(node, parent)) {
|
|
33
44
|
replaced = true
|
|
34
45
|
}
|
|
35
46
|
}
|
|
@@ -37,51 +48,60 @@ function replace (nodes, parent) {
|
|
|
37
48
|
return replaced
|
|
38
49
|
}
|
|
39
50
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
/**
|
|
52
|
+
* Combines parent and child selectors, in a SCSS-like way
|
|
53
|
+
*/
|
|
54
|
+
function mergeSelectors(parent, child) {
|
|
55
|
+
let merged = []
|
|
56
|
+
parent.selectors.forEach(sel => {
|
|
57
|
+
let parentNode = parse(sel, parent)
|
|
58
|
+
|
|
59
|
+
child.selectors.forEach(selector => {
|
|
60
|
+
if (!selector) {
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
let node = parse(selector, child)
|
|
64
|
+
let replaced = interpolateAmpInSelector(node, parentNode)
|
|
65
|
+
if (!replaced) {
|
|
66
|
+
node.prepend(parser.combinator({ value: ' ' }))
|
|
67
|
+
node.prepend(parentNode.clone({}))
|
|
54
68
|
}
|
|
69
|
+
merged.push(node.toString())
|
|
55
70
|
})
|
|
56
71
|
})
|
|
57
|
-
return
|
|
72
|
+
return merged
|
|
58
73
|
}
|
|
59
74
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
75
|
+
/**
|
|
76
|
+
* Move a child and its preceeding comment(s) to after "after"
|
|
77
|
+
*/
|
|
78
|
+
function breakOut(child, after) {
|
|
79
|
+
let prev = child.prev()
|
|
80
|
+
after.after(child)
|
|
81
|
+
while (prev && prev.type === 'comment') {
|
|
82
|
+
let nextPrev = prev.prev()
|
|
83
|
+
after.after(prev)
|
|
84
|
+
prev = nextPrev
|
|
66
85
|
}
|
|
86
|
+
return child
|
|
67
87
|
}
|
|
68
88
|
|
|
69
|
-
function createFnAtruleChilds
|
|
70
|
-
return function atruleChilds
|
|
89
|
+
function createFnAtruleChilds(bubble) {
|
|
90
|
+
return function atruleChilds(rule, atrule, bubbling, mergeSels = bubbling) {
|
|
71
91
|
let children = []
|
|
72
92
|
atrule.each(child => {
|
|
73
|
-
if (child.type === '
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
} else if (child.type === '
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if (
|
|
81
|
-
atruleChilds(rule, child, true)
|
|
82
|
-
} else {
|
|
93
|
+
if (child.type === 'rule' && bubbling) {
|
|
94
|
+
if (mergeSels) {
|
|
95
|
+
child.selectors = mergeSelectors(rule, child)
|
|
96
|
+
}
|
|
97
|
+
} else if (child.type === 'atrule' && child.nodes) {
|
|
98
|
+
if (bubble[child.name]) {
|
|
99
|
+
atruleChilds(rule, child, mergeSels)
|
|
100
|
+
} else if (atrule[rootRuleMergeSel] !== false) {
|
|
83
101
|
children.push(child)
|
|
84
102
|
}
|
|
103
|
+
} else {
|
|
104
|
+
children.push(child)
|
|
85
105
|
}
|
|
86
106
|
})
|
|
87
107
|
if (bubbling) {
|
|
@@ -96,36 +116,159 @@ function createFnAtruleChilds (bubble) {
|
|
|
96
116
|
}
|
|
97
117
|
}
|
|
98
118
|
|
|
99
|
-
function pickDeclarations
|
|
119
|
+
function pickDeclarations(selector, declarations, after) {
|
|
100
120
|
let parent = new Rule({
|
|
101
121
|
selector,
|
|
102
122
|
nodes: []
|
|
103
123
|
})
|
|
104
|
-
|
|
105
|
-
for (let declaration of declarations) {
|
|
106
|
-
parent.append(declaration)
|
|
107
|
-
}
|
|
108
|
-
|
|
124
|
+
parent.append(declarations)
|
|
109
125
|
after.after(parent)
|
|
110
126
|
return parent
|
|
111
127
|
}
|
|
112
128
|
|
|
113
|
-
function atruleNames
|
|
129
|
+
function atruleNames(defaults, custom) {
|
|
114
130
|
let list = {}
|
|
115
|
-
for (let
|
|
116
|
-
list[
|
|
131
|
+
for (let name of defaults) {
|
|
132
|
+
list[name] = true
|
|
117
133
|
}
|
|
118
134
|
if (custom) {
|
|
119
|
-
for (let
|
|
120
|
-
|
|
121
|
-
list[name] = true
|
|
135
|
+
for (let name of custom) {
|
|
136
|
+
list[name.replace(/^@/, '')] = true
|
|
122
137
|
}
|
|
123
138
|
}
|
|
124
139
|
return list
|
|
125
140
|
}
|
|
126
141
|
|
|
142
|
+
function parseRootRuleParams(params) {
|
|
143
|
+
params = params.trim()
|
|
144
|
+
let braceBlock = params.match(/^\((.*)\)$/)
|
|
145
|
+
if (!braceBlock) {
|
|
146
|
+
return { type: 'basic', selector: params }
|
|
147
|
+
}
|
|
148
|
+
let bits = braceBlock[1].match(/^(with(?:out)?):(.+)$/)
|
|
149
|
+
if (bits) {
|
|
150
|
+
let allowlist = bits[1] === 'with'
|
|
151
|
+
let rules = Object.fromEntries(
|
|
152
|
+
bits[2]
|
|
153
|
+
.trim()
|
|
154
|
+
.split(/\s+/)
|
|
155
|
+
.map(name => [name, true])
|
|
156
|
+
)
|
|
157
|
+
if (allowlist && rules.all) {
|
|
158
|
+
return { type: 'noop' }
|
|
159
|
+
}
|
|
160
|
+
let escapes = rule => !!rules[rule]
|
|
161
|
+
if (rules.all) {
|
|
162
|
+
escapes = () => true
|
|
163
|
+
} else if (allowlist) {
|
|
164
|
+
escapes = rule => (rule === 'all' ? false : !rules[rule])
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return {
|
|
168
|
+
type: 'withrules',
|
|
169
|
+
escapes
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// Unrecognized brace block
|
|
173
|
+
return { type: 'unknown' }
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function getAncestorRules(leaf) {
|
|
177
|
+
let lineage = []
|
|
178
|
+
let parent = leaf.parent
|
|
179
|
+
|
|
180
|
+
while (parent && parent instanceof AtRule) {
|
|
181
|
+
lineage.push(parent)
|
|
182
|
+
parent = parent.parent
|
|
183
|
+
}
|
|
184
|
+
return lineage
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function unwrapRootRule(rule) {
|
|
188
|
+
let escapes = rule[rootRuleEscapes]
|
|
189
|
+
|
|
190
|
+
if (!escapes) {
|
|
191
|
+
rule.after(rule.nodes)
|
|
192
|
+
} else {
|
|
193
|
+
let nodes = rule.nodes
|
|
194
|
+
|
|
195
|
+
let topEscaped
|
|
196
|
+
let topEscapedIdx = -1
|
|
197
|
+
let breakoutLeaf
|
|
198
|
+
let breakoutRoot
|
|
199
|
+
let clone
|
|
200
|
+
|
|
201
|
+
let lineage = getAncestorRules(rule)
|
|
202
|
+
lineage.forEach((parent, i) => {
|
|
203
|
+
if (escapes(parent.name)) {
|
|
204
|
+
topEscaped = parent
|
|
205
|
+
topEscapedIdx = i
|
|
206
|
+
breakoutRoot = clone
|
|
207
|
+
} else {
|
|
208
|
+
let oldClone = clone
|
|
209
|
+
clone = parent.clone({ nodes: [] })
|
|
210
|
+
oldClone && clone.append(oldClone)
|
|
211
|
+
breakoutLeaf = breakoutLeaf || clone
|
|
212
|
+
}
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
if (!topEscaped) {
|
|
216
|
+
rule.after(nodes)
|
|
217
|
+
} else if (!breakoutRoot) {
|
|
218
|
+
topEscaped.after(nodes)
|
|
219
|
+
} else {
|
|
220
|
+
let leaf = breakoutLeaf
|
|
221
|
+
leaf.append(nodes)
|
|
222
|
+
topEscaped.after(breakoutRoot)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (rule.next() && topEscaped) {
|
|
226
|
+
let restRoot
|
|
227
|
+
lineage.slice(0, topEscapedIdx + 1).forEach((parent, i, arr) => {
|
|
228
|
+
let oldRoot = restRoot
|
|
229
|
+
restRoot = parent.clone({ nodes: [] })
|
|
230
|
+
oldRoot && restRoot.append(oldRoot)
|
|
231
|
+
|
|
232
|
+
let nextSibs = []
|
|
233
|
+
let _child = arr[i - 1] || rule
|
|
234
|
+
let next = _child.next()
|
|
235
|
+
while (next) {
|
|
236
|
+
nextSibs.push(next)
|
|
237
|
+
next = next.next()
|
|
238
|
+
}
|
|
239
|
+
restRoot.append(nextSibs)
|
|
240
|
+
})
|
|
241
|
+
restRoot && (breakoutRoot || nodes[nodes.length - 1]).after(restRoot)
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
rule.remove()
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const rootRuleMergeSel = Symbol('rootRuleMergeSel')
|
|
249
|
+
const rootRuleEscapes = Symbol('rootRuleEscapes')
|
|
250
|
+
|
|
251
|
+
function normalizeRootRule(rule) {
|
|
252
|
+
let { params } = rule
|
|
253
|
+
let { type, selector, escapes } = parseRootRuleParams(params)
|
|
254
|
+
if (type === 'unknown') {
|
|
255
|
+
throw rule.error(
|
|
256
|
+
`Unknown @${rule.name} parameter ${JSON.stringify(params)}`
|
|
257
|
+
)
|
|
258
|
+
}
|
|
259
|
+
if (type === 'basic' && selector) {
|
|
260
|
+
let selectorBlock = new Rule({ selector, nodes: rule.nodes })
|
|
261
|
+
rule.removeAll()
|
|
262
|
+
rule.append(selectorBlock)
|
|
263
|
+
}
|
|
264
|
+
rule[rootRuleEscapes] = escapes
|
|
265
|
+
rule[rootRuleMergeSel] = escapes ? !escapes('all') : type === 'noop'
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const hasRootRule = Symbol('hasRootRule')
|
|
269
|
+
|
|
127
270
|
module.exports = (opts = {}) => {
|
|
128
|
-
let bubble = atruleNames(['media', 'supports'], opts.bubble)
|
|
271
|
+
let bubble = atruleNames(['media', 'supports', 'layer'], opts.bubble)
|
|
129
272
|
let atruleChilds = createFnAtruleChilds(bubble)
|
|
130
273
|
let unwrap = atruleNames(
|
|
131
274
|
[
|
|
@@ -137,11 +280,20 @@ module.exports = (opts = {}) => {
|
|
|
137
280
|
],
|
|
138
281
|
opts.unwrap
|
|
139
282
|
)
|
|
283
|
+
let rootRuleName = (opts.rootRuleName || 'at-root').replace(/^@/, '')
|
|
140
284
|
let preserveEmpty = opts.preserveEmpty
|
|
141
285
|
|
|
142
286
|
return {
|
|
143
287
|
postcssPlugin: 'postcss-nested',
|
|
144
|
-
|
|
288
|
+
|
|
289
|
+
Once(root) {
|
|
290
|
+
root.walkAtRules(rootRuleName, node => {
|
|
291
|
+
normalizeRootRule(node)
|
|
292
|
+
root[hasRootRule] = true
|
|
293
|
+
})
|
|
294
|
+
},
|
|
295
|
+
|
|
296
|
+
Rule(rule) {
|
|
145
297
|
let unwrapped = false
|
|
146
298
|
let after = rule
|
|
147
299
|
let copyDeclarations = false
|
|
@@ -150,48 +302,33 @@ module.exports = (opts = {}) => {
|
|
|
150
302
|
rule.each(child => {
|
|
151
303
|
if (child.type === 'rule') {
|
|
152
304
|
if (declarations.length) {
|
|
153
|
-
after = pickDeclarations(rule.selector, declarations, after
|
|
305
|
+
after = pickDeclarations(rule.selector, declarations, after)
|
|
154
306
|
declarations = []
|
|
155
307
|
}
|
|
156
308
|
|
|
157
309
|
copyDeclarations = true
|
|
158
310
|
unwrapped = true
|
|
159
|
-
child.selectors =
|
|
160
|
-
after =
|
|
161
|
-
after.after(child)
|
|
162
|
-
after = child
|
|
311
|
+
child.selectors = mergeSelectors(rule, child)
|
|
312
|
+
after = breakOut(child, after)
|
|
163
313
|
} else if (child.type === 'atrule') {
|
|
164
314
|
if (declarations.length) {
|
|
165
|
-
after = pickDeclarations(rule.selector, declarations, after
|
|
315
|
+
after = pickDeclarations(rule.selector, declarations, after)
|
|
166
316
|
declarations = []
|
|
167
317
|
}
|
|
168
|
-
|
|
169
|
-
if (child.name === 'at-root') {
|
|
318
|
+
if (child.name === rootRuleName) {
|
|
170
319
|
unwrapped = true
|
|
171
|
-
atruleChilds(rule, child,
|
|
172
|
-
|
|
173
|
-
let nodes = child.nodes
|
|
174
|
-
if (child.params) {
|
|
175
|
-
nodes = new Rule({ selector: child.params, nodes })
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
after.after(nodes)
|
|
179
|
-
after = nodes
|
|
180
|
-
child.remove()
|
|
320
|
+
atruleChilds(rule, child, true, child[rootRuleMergeSel])
|
|
321
|
+
after = breakOut(child, after)
|
|
181
322
|
} else if (bubble[child.name]) {
|
|
182
323
|
copyDeclarations = true
|
|
183
324
|
unwrapped = true
|
|
184
325
|
atruleChilds(rule, child, true)
|
|
185
|
-
after =
|
|
186
|
-
after.after(child)
|
|
187
|
-
after = child
|
|
326
|
+
after = breakOut(child, after)
|
|
188
327
|
} else if (unwrap[child.name]) {
|
|
189
328
|
copyDeclarations = true
|
|
190
329
|
unwrapped = true
|
|
191
330
|
atruleChilds(rule, child, false)
|
|
192
|
-
after =
|
|
193
|
-
after.after(child)
|
|
194
|
-
after = child
|
|
331
|
+
after = breakOut(child, after)
|
|
195
332
|
} else if (copyDeclarations) {
|
|
196
333
|
declarations.push(child)
|
|
197
334
|
}
|
|
@@ -201,13 +338,20 @@ module.exports = (opts = {}) => {
|
|
|
201
338
|
})
|
|
202
339
|
|
|
203
340
|
if (declarations.length) {
|
|
204
|
-
after = pickDeclarations(rule.selector, declarations, after
|
|
341
|
+
after = pickDeclarations(rule.selector, declarations, after)
|
|
205
342
|
}
|
|
206
343
|
|
|
207
344
|
if (unwrapped && preserveEmpty !== true) {
|
|
208
345
|
rule.raws.semicolon = true
|
|
209
346
|
if (rule.nodes.length === 0) rule.remove()
|
|
210
347
|
}
|
|
348
|
+
},
|
|
349
|
+
|
|
350
|
+
RootExit(root) {
|
|
351
|
+
if (root[hasRootRule]) {
|
|
352
|
+
root.walkAtRules(rootRuleName, unwrapRootRule)
|
|
353
|
+
root[hasRootRule] = false
|
|
354
|
+
}
|
|
211
355
|
}
|
|
212
356
|
}
|
|
213
357
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "postcss-nested",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"description": "PostCSS plugin to unwrap nested rules like how Sass does it",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"postcss",
|
|
@@ -23,6 +23,6 @@
|
|
|
23
23
|
"postcss": "^8.2.14"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"postcss-selector-parser": "^6.0.
|
|
26
|
+
"postcss-selector-parser": "^6.0.10"
|
|
27
27
|
}
|
|
28
28
|
}
|