postcss-nested 5.0.6 → 6.0.1
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 +5 -117
- package/index.d.ts +9 -2
- package/index.js +234 -87
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
title="Philosopher’s stone, logo of PostCSS"
|
|
5
5
|
src="https://postcss.org/logo-leftp.svg">
|
|
6
6
|
|
|
7
|
-
[PostCSS] plugin to unwrap nested rules
|
|
7
|
+
[PostCSS] plugin to unwrap nested rules closer to Sass syntax.
|
|
8
8
|
|
|
9
9
|
```css
|
|
10
10
|
.phone {
|
|
@@ -59,8 +59,6 @@ html {
|
|
|
59
59
|
|
|
60
60
|
Related plugins:
|
|
61
61
|
|
|
62
|
-
* Use [`postcss-atroot`] for `@at-root` at-rule to move nested child
|
|
63
|
-
to the CSS root.
|
|
64
62
|
* Use [`postcss-current-selector`] **after** this plugin if you want
|
|
65
63
|
to use current selector in properties or variables values.
|
|
66
64
|
* Use [`postcss-nested-ancestors`] **before** this plugin if you want
|
|
@@ -68,8 +66,7 @@ Related plugins:
|
|
|
68
66
|
|
|
69
67
|
Alternatives:
|
|
70
68
|
|
|
71
|
-
* See also [`postcss-nesting`], which implements [CSSWG draft]
|
|
72
|
-
(requires the `&` and introduces `@nest`).
|
|
69
|
+
* See also [`postcss-nesting`], which implements [CSSWG draft].
|
|
73
70
|
* [`postcss-nested-props`] for nested properties like `font-size`.
|
|
74
71
|
|
|
75
72
|
<a href="https://evilmartians.com/?utm_source=postcss-nested">
|
|
@@ -77,122 +74,13 @@ Alternatives:
|
|
|
77
74
|
alt="Sponsored by Evil Martians" width="236" height="54">
|
|
78
75
|
</a>
|
|
79
76
|
|
|
80
|
-
[`postcss-atroot`]: https://github.com/OEvgeny/postcss-atroot
|
|
81
77
|
[`postcss-current-selector`]: https://github.com/komlev/postcss-current-selector
|
|
82
78
|
[`postcss-nested-ancestors`]: https://github.com/toomuchdesign/postcss-nested-ancestors
|
|
83
79
|
[`postcss-nested-props`]: https://github.com/jedmao/postcss-nested-props
|
|
84
|
-
[`postcss-nesting`]: https://github.com/
|
|
80
|
+
[`postcss-nesting`]: https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-nesting
|
|
85
81
|
[CSSWG draft]: https://drafts.csswg.org/css-nesting-1/
|
|
86
82
|
[PostCSS]: https://github.com/postcss/postcss
|
|
87
83
|
|
|
88
84
|
|
|
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`.
|
|
85
|
+
## Docs
|
|
86
|
+
Read full docs **[here](https://github.com/postcss/postcss-nested#readme)**.
|
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,162 @@ 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(
|
|
271
|
+
let bubble = atruleNames(
|
|
272
|
+
['media', 'supports', 'layer', 'container'],
|
|
273
|
+
opts.bubble
|
|
274
|
+
)
|
|
129
275
|
let atruleChilds = createFnAtruleChilds(bubble)
|
|
130
276
|
let unwrap = atruleNames(
|
|
131
277
|
[
|
|
@@ -137,11 +283,20 @@ module.exports = (opts = {}) => {
|
|
|
137
283
|
],
|
|
138
284
|
opts.unwrap
|
|
139
285
|
)
|
|
286
|
+
let rootRuleName = (opts.rootRuleName || 'at-root').replace(/^@/, '')
|
|
140
287
|
let preserveEmpty = opts.preserveEmpty
|
|
141
288
|
|
|
142
289
|
return {
|
|
143
290
|
postcssPlugin: 'postcss-nested',
|
|
144
|
-
|
|
291
|
+
|
|
292
|
+
Once(root) {
|
|
293
|
+
root.walkAtRules(rootRuleName, node => {
|
|
294
|
+
normalizeRootRule(node)
|
|
295
|
+
root[hasRootRule] = true
|
|
296
|
+
})
|
|
297
|
+
},
|
|
298
|
+
|
|
299
|
+
Rule(rule) {
|
|
145
300
|
let unwrapped = false
|
|
146
301
|
let after = rule
|
|
147
302
|
let copyDeclarations = false
|
|
@@ -150,48 +305,33 @@ module.exports = (opts = {}) => {
|
|
|
150
305
|
rule.each(child => {
|
|
151
306
|
if (child.type === 'rule') {
|
|
152
307
|
if (declarations.length) {
|
|
153
|
-
after = pickDeclarations(rule.selector, declarations, after
|
|
308
|
+
after = pickDeclarations(rule.selector, declarations, after)
|
|
154
309
|
declarations = []
|
|
155
310
|
}
|
|
156
311
|
|
|
157
312
|
copyDeclarations = true
|
|
158
313
|
unwrapped = true
|
|
159
|
-
child.selectors =
|
|
160
|
-
after =
|
|
161
|
-
after.after(child)
|
|
162
|
-
after = child
|
|
314
|
+
child.selectors = mergeSelectors(rule, child)
|
|
315
|
+
after = breakOut(child, after)
|
|
163
316
|
} else if (child.type === 'atrule') {
|
|
164
317
|
if (declarations.length) {
|
|
165
|
-
after = pickDeclarations(rule.selector, declarations, after
|
|
318
|
+
after = pickDeclarations(rule.selector, declarations, after)
|
|
166
319
|
declarations = []
|
|
167
320
|
}
|
|
168
|
-
|
|
169
|
-
if (child.name === 'at-root') {
|
|
321
|
+
if (child.name === rootRuleName) {
|
|
170
322
|
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()
|
|
323
|
+
atruleChilds(rule, child, true, child[rootRuleMergeSel])
|
|
324
|
+
after = breakOut(child, after)
|
|
181
325
|
} else if (bubble[child.name]) {
|
|
182
326
|
copyDeclarations = true
|
|
183
327
|
unwrapped = true
|
|
184
328
|
atruleChilds(rule, child, true)
|
|
185
|
-
after =
|
|
186
|
-
after.after(child)
|
|
187
|
-
after = child
|
|
329
|
+
after = breakOut(child, after)
|
|
188
330
|
} else if (unwrap[child.name]) {
|
|
189
331
|
copyDeclarations = true
|
|
190
332
|
unwrapped = true
|
|
191
333
|
atruleChilds(rule, child, false)
|
|
192
|
-
after =
|
|
193
|
-
after.after(child)
|
|
194
|
-
after = child
|
|
334
|
+
after = breakOut(child, after)
|
|
195
335
|
} else if (copyDeclarations) {
|
|
196
336
|
declarations.push(child)
|
|
197
337
|
}
|
|
@@ -201,13 +341,20 @@ module.exports = (opts = {}) => {
|
|
|
201
341
|
})
|
|
202
342
|
|
|
203
343
|
if (declarations.length) {
|
|
204
|
-
after = pickDeclarations(rule.selector, declarations, after
|
|
344
|
+
after = pickDeclarations(rule.selector, declarations, after)
|
|
205
345
|
}
|
|
206
346
|
|
|
207
347
|
if (unwrapped && preserveEmpty !== true) {
|
|
208
348
|
rule.raws.semicolon = true
|
|
209
349
|
if (rule.nodes.length === 0) rule.remove()
|
|
210
350
|
}
|
|
351
|
+
},
|
|
352
|
+
|
|
353
|
+
RootExit(root) {
|
|
354
|
+
if (root[hasRootRule]) {
|
|
355
|
+
root.walkAtRules(rootRuleName, unwrapRootRule)
|
|
356
|
+
root[hasRootRule] = false
|
|
357
|
+
}
|
|
211
358
|
}
|
|
212
359
|
}
|
|
213
360
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "postcss-nested",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.1",
|
|
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.11"
|
|
27
27
|
}
|
|
28
28
|
}
|