postcss 8.5.16 → 8.5.17

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/lib/container.js CHANGED
@@ -8,18 +8,25 @@ let { isClean, my } = require('./symbols')
8
8
  let AtRule, parse, Root, Rule
9
9
 
10
10
  function cleanSource(nodes) {
11
- return nodes.map(i => {
12
- if (i.nodes) i.nodes = cleanSource(i.nodes)
13
- delete i.source
14
- return i
15
- })
11
+ let stack = nodes.slice()
12
+ while (stack.length > 0) {
13
+ let node = stack.pop()
14
+ delete node.source
15
+ if (node.nodes) {
16
+ node.nodes = node.nodes.slice()
17
+ for (let i of node.nodes) stack.push(i)
18
+ }
19
+ }
20
+ return nodes.slice()
16
21
  }
17
22
 
18
23
  function markTreeDirty(node) {
19
- node[isClean] = false
20
- if (node.proxyOf.nodes) {
21
- for (let i of node.proxyOf.nodes) {
22
- markTreeDirty(i)
24
+ let stack = [node]
25
+ while (stack.length > 0) {
26
+ let next = stack.pop()
27
+ next[isClean] = false
28
+ if (next.proxyOf.nodes) {
29
+ for (let i of next.proxyOf.nodes) stack.push(i)
23
30
  }
24
31
  }
25
32
  }
@@ -47,9 +54,18 @@ class Container extends Node {
47
54
  }
48
55
 
49
56
  cleanRaws(keepBetween) {
50
- super.cleanRaws(keepBetween)
51
- if (this.nodes) {
52
- for (let node of this.nodes) node.cleanRaws(keepBetween)
57
+ let stack = [this]
58
+ while (stack.length > 0) {
59
+ let node = stack.pop()
60
+ if (node !== this && node.cleanRaws !== Container.prototype.cleanRaws) {
61
+ // Subclass with own logic; let it handle its subtree
62
+ node.cleanRaws(keepBetween)
63
+ continue
64
+ }
65
+ Node.prototype.cleanRaws.call(node, keepBetween)
66
+ if (node.nodes) {
67
+ for (let child of node.nodes) stack.push(child)
68
+ }
53
69
  }
54
70
  }
55
71
 
@@ -309,19 +325,48 @@ class Container extends Node {
309
325
  }
310
326
 
311
327
  walk(callback) {
312
- return this.each((child, i) => {
328
+ if (!this.proxyOf.nodes) return undefined
329
+
330
+ // An explicit stack instead of recursive `each()` calls to survive
331
+ // deeply nested trees. Each frame keeps a live `indexes` slot, so
332
+ // insertion and removal during the walk behave like `each()`: the
333
+ // slot stays at the current child until its subtree is finished.
334
+ let stack = [{ iterator: this.getIterator(), node: this.proxyOf }]
335
+
336
+ while (stack.length > 0) {
337
+ let { iterator, node } = stack[stack.length - 1]
338
+ let index = node.indexes[iterator]
339
+
340
+ if (index >= node.proxyOf.nodes.length) {
341
+ delete node.indexes[iterator]
342
+ stack.pop()
343
+ let parent = stack[stack.length - 1]
344
+ // Finish the parent’s step for the child subtree we just left
345
+ if (parent) parent.node.indexes[parent.iterator] += 1
346
+ continue
347
+ }
348
+
349
+ let child = node.proxyOf.nodes[index]
313
350
  let result
314
351
  try {
315
- result = callback(child, i)
352
+ result = callback(child, index)
316
353
  } catch (e) {
317
354
  throw child.addToError(e)
318
355
  }
319
- if (result !== false && child.walk) {
320
- result = child.walk(callback)
356
+ if (result === false) {
357
+ for (let opened of stack) {
358
+ delete opened.node.indexes[opened.iterator]
359
+ }
360
+ return false
361
+ }
362
+ if (child.walk && child.proxyOf.nodes) {
363
+ stack.push({ iterator: child.getIterator(), node: child })
364
+ } else {
365
+ node.indexes[iterator] += 1
321
366
  }
367
+ }
322
368
 
323
- return result
324
- })
369
+ return undefined
325
370
  }
326
371
 
327
372
  walkAtRules(name, callback) {
@@ -424,24 +469,26 @@ Container.default = Container
424
469
 
425
470
  /* c8 ignore start */
426
471
  Container.rebuild = node => {
427
- if (node.type === 'atrule') {
428
- Object.setPrototypeOf(node, AtRule.prototype)
429
- } else if (node.type === 'rule') {
430
- Object.setPrototypeOf(node, Rule.prototype)
431
- } else if (node.type === 'decl') {
432
- Object.setPrototypeOf(node, Declaration.prototype)
433
- } else if (node.type === 'comment') {
434
- Object.setPrototypeOf(node, Comment.prototype)
435
- } else if (node.type === 'root') {
436
- Object.setPrototypeOf(node, Root.prototype)
437
- }
472
+ let stack = [node]
473
+ while (stack.length > 0) {
474
+ let next = stack.pop()
475
+ if (next.type === 'atrule') {
476
+ Object.setPrototypeOf(next, AtRule.prototype)
477
+ } else if (next.type === 'rule') {
478
+ Object.setPrototypeOf(next, Rule.prototype)
479
+ } else if (next.type === 'decl') {
480
+ Object.setPrototypeOf(next, Declaration.prototype)
481
+ } else if (next.type === 'comment') {
482
+ Object.setPrototypeOf(next, Comment.prototype)
483
+ } else if (next.type === 'root') {
484
+ Object.setPrototypeOf(next, Root.prototype)
485
+ }
438
486
 
439
- node[my] = true
487
+ next[my] = true
440
488
 
441
- if (node.nodes) {
442
- node.nodes.forEach(child => {
443
- Container.rebuild(child)
444
- })
489
+ if (next.nodes) {
490
+ for (let child of next.nodes) stack.push(child)
491
+ }
445
492
  }
446
493
  }
447
494
  /* c8 ignore stop */
package/lib/fromJSON.js CHANGED
@@ -8,31 +8,24 @@ let PreviousMap = require('./previous-map')
8
8
  let Root = require('./root')
9
9
  let Rule = require('./rule')
10
10
 
11
- function fromJSON(json, inputs) {
12
- if (Array.isArray(json)) return json.map(n => fromJSON(n))
13
-
14
- let { inputs: ownInputs, ...defaults } = json
15
- if (ownInputs) {
16
- inputs = []
17
- for (let input of ownInputs) {
18
- let inputHydrated = { ...input, __proto__: Input.prototype }
19
- if (inputHydrated.map) {
20
- inputHydrated.map = {
21
- ...inputHydrated.map,
22
- __proto__: PreviousMap.prototype
23
- }
11
+ function hydrateInputs(json, inputs) {
12
+ if (!json.inputs) return inputs
13
+ return json.inputs.map(input => {
14
+ let inputHydrated = { ...input, __proto__: Input.prototype }
15
+ if (inputHydrated.map) {
16
+ inputHydrated.map = {
17
+ ...inputHydrated.map,
18
+ __proto__: PreviousMap.prototype
24
19
  }
25
- inputs.push(inputHydrated)
26
20
  }
27
- }
28
- // Rehydrate children separately and attach them after construction.
29
- // Passing them through the container constructor would re-run insertion
30
- // spacing normalization and overwrite each child's own `raws.before`.
31
- let nodes
32
- if (defaults.nodes) {
33
- nodes = json.nodes.map(n => fromJSON(n, inputs))
34
- delete defaults.nodes
35
- }
21
+ return inputHydrated
22
+ })
23
+ }
24
+
25
+ function constructNode(json, inputs, children) {
26
+ let defaults = { ...json }
27
+ delete defaults.inputs
28
+ delete defaults.nodes
36
29
  if (defaults.source) {
37
30
  let { inputId, ...source } = defaults.source
38
31
  defaults.source = source
@@ -56,13 +49,59 @@ function fromJSON(json, inputs) {
56
49
  throw new Error('Unknown node type: ' + json.type)
57
50
  }
58
51
 
59
- if (nodes) {
60
- node.nodes = nodes
61
- for (let child of nodes) child.parent = node
52
+ // Rehydrated children are attached after construction. Passing them
53
+ // through the container constructor would re-run insertion spacing
54
+ // normalization and overwrite each child's own `raws.before`.
55
+ if (children) {
56
+ node.nodes = children
57
+ for (let child of children) child.parent = node
62
58
  }
63
59
 
64
60
  return node
65
61
  }
66
62
 
63
+ function fromJSON(json, inputs) {
64
+ if (Array.isArray(json)) return json.map(n => fromJSON(n))
65
+
66
+ // An explicit stack instead of recursive calls to survive deeply
67
+ // nested trees. Children are rehydrated before their parent node
68
+ // is constructed.
69
+ let result
70
+ let stack = [
71
+ { childIndex: 0, children: [], inputs: hydrateInputs(json, inputs), json }
72
+ ]
73
+
74
+ while (stack.length > 0) {
75
+ let frame = stack[stack.length - 1]
76
+ let jsonNodes = frame.json.nodes
77
+
78
+ if (jsonNodes && frame.childIndex < jsonNodes.length) {
79
+ let childJson = jsonNodes[frame.childIndex]
80
+ frame.childIndex += 1
81
+ stack.push({
82
+ childIndex: 0,
83
+ children: [],
84
+ inputs: hydrateInputs(childJson, frame.inputs),
85
+ json: childJson
86
+ })
87
+ continue
88
+ }
89
+
90
+ stack.pop()
91
+ let node = constructNode(
92
+ frame.json,
93
+ frame.inputs,
94
+ jsonNodes ? frame.children : undefined
95
+ )
96
+ if (stack.length > 0) {
97
+ stack[stack.length - 1].children.push(node)
98
+ } else {
99
+ result = node
100
+ }
101
+ }
102
+
103
+ return result
104
+ }
105
+
67
106
  module.exports = fromJSON
68
107
  fromJSON.default = fromJSON
package/lib/input.js CHANGED
@@ -211,10 +211,16 @@ class Input {
211
211
 
212
212
  let to
213
213
  if (typeof endLine === 'number') {
214
- to = consumer.originalPositionFor({
214
+ let toPosition = consumer.originalPositionFor({
215
215
  column: endColumn - 1,
216
216
  line: endLine
217
217
  })
218
+ // The source map may not have a mapping that covers the end position
219
+ // (`originalPositionFor()` then returns `null` for `line`/`column`
220
+ // instead of omitting them). Treat that the same as not requesting
221
+ // an end position at all, so `endLine`/`endColumn` stay a consistent
222
+ // `undefined` pair instead of a mix of `null` and a bogus number.
223
+ if (toPosition.source) to = toPosition
218
224
  }
219
225
 
220
226
  let fromUrl
@@ -97,8 +97,14 @@ function toStack(node) {
97
97
  }
98
98
 
99
99
  function cleanMarks(node) {
100
- node[isClean] = false
101
- if (node.nodes) node.nodes.forEach(i => cleanMarks(i))
100
+ let stack = [node]
101
+ while (stack.length > 0) {
102
+ let next = stack.pop()
103
+ next[isClean] = false
104
+ if (next.nodes) {
105
+ for (let i of next.nodes) stack.push(i)
106
+ }
107
+ }
102
108
  return node
103
109
  }
104
110
 
@@ -529,21 +535,57 @@ class LazyResult {
529
535
  }
530
536
 
531
537
  walkSync(node) {
538
+ // An explicit stack like in async `visitTick()` to survive deeply
539
+ // nested trees. Unlike `visitTick()`, nodes are marked clean only
540
+ // on entering, so a node dirtied by its own visitors is revisited
541
+ // on the next pass.
532
542
  node[isClean] = true
533
- let events = getEvents(node)
534
- for (let event of events) {
535
- if (event === CHILDREN) {
536
- if (node.nodes) {
537
- node.each(child => {
538
- if (!child[isClean]) this.walkSync(child)
539
- })
543
+ let stack = [{ eventIndex: 0, events: getEvents(node), iterator: 0, node }]
544
+
545
+ while (stack.length > 0) {
546
+ let visit = stack[stack.length - 1]
547
+ let visitNode = visit.node
548
+
549
+ if (visit.iterator !== 0) {
550
+ let iterator = visit.iterator
551
+ let child
552
+ let descended = false
553
+ while ((child = visitNode.nodes[visitNode.indexes[iterator]])) {
554
+ visitNode.indexes[iterator] += 1
555
+ if (!child[isClean]) {
556
+ child[isClean] = true
557
+ stack.push({
558
+ eventIndex: 0,
559
+ events: getEvents(child),
560
+ iterator: 0,
561
+ node: child
562
+ })
563
+ descended = true
564
+ break
565
+ }
540
566
  }
541
- } else {
542
- let visitors = this.listeners[event]
543
- if (visitors) {
544
- if (this.visitSync(visitors, node.toProxy())) return
567
+ if (descended) continue
568
+ visit.iterator = 0
569
+ delete visitNode.indexes[iterator]
570
+ }
571
+
572
+ if (visit.eventIndex < visit.events.length) {
573
+ let event = visit.events[visit.eventIndex]
574
+ visit.eventIndex += 1
575
+ if (event === CHILDREN) {
576
+ if (visitNode.nodes && visitNode.nodes.length) {
577
+ visit.iterator = visitNode.getIterator()
578
+ }
579
+ } else {
580
+ let visitors = this.listeners[event]
581
+ if (visitors) {
582
+ if (this.visitSync(visitors, visitNode.toProxy())) stack.pop()
583
+ }
545
584
  }
585
+ continue
546
586
  }
587
+
588
+ stack.pop()
547
589
  }
548
590
  }
549
591
 
package/lib/node.js CHANGED
@@ -7,25 +7,41 @@ let { isClean, my } = require('./symbols')
7
7
 
8
8
  function cloneNode(obj, parent) {
9
9
  let cloned = new obj.constructor()
10
-
11
- for (let i in obj) {
12
- if (!Object.prototype.hasOwnProperty.call(obj, i)) {
13
- /* c8 ignore next 2 */
14
- continue
15
- }
16
- if (i === 'proxyCache') continue
17
- let value = obj[i]
18
- let type = typeof value
19
-
20
- if (i === 'parent' && type === 'object') {
21
- if (parent) cloned[i] = parent
22
- } else if (i === 'source') {
23
- cloned[i] = value
24
- } else if (Array.isArray(value)) {
25
- cloned[i] = value.map(j => cloneNode(j, cloned))
26
- } else {
27
- if (type === 'object' && value !== null) value = cloneNode(value)
28
- cloned[i] = value
10
+ // An explicit stack instead of recursive calls to survive deeply
11
+ // nested trees. Each entry is [source, its clone, clone's parent].
12
+ let stack = [[obj, cloned, parent]]
13
+
14
+ while (stack.length > 0) {
15
+ let [source, target, targetParent] = stack.pop()
16
+ for (let i in source) {
17
+ if (!Object.prototype.hasOwnProperty.call(source, i)) {
18
+ /* c8 ignore next 2 */
19
+ continue
20
+ }
21
+ if (i === 'proxyCache') continue
22
+ let value = source[i]
23
+ let type = typeof value
24
+
25
+ if (i === 'parent' && type === 'object') {
26
+ if (targetParent) target[i] = targetParent
27
+ } else if (i === 'source') {
28
+ target[i] = value
29
+ } else if (Array.isArray(value)) {
30
+ let children = []
31
+ target[i] = children
32
+ for (let j of value) {
33
+ let childClone = new j.constructor()
34
+ children.push(childClone)
35
+ stack.push([j, childClone, target])
36
+ }
37
+ } else {
38
+ if (type === 'object' && value !== null) {
39
+ let valueClone = new value.constructor()
40
+ stack.push([value, valueClone, undefined])
41
+ value = valueClone
42
+ }
43
+ target[i] = value
44
+ }
29
45
  }
30
46
  }
31
47
 
@@ -69,7 +85,8 @@ class Node {
69
85
  this[isClean] = false
70
86
  this[my] = true
71
87
 
72
- for (let name in defaults) {
88
+ for (let name of Object.keys(defaults)) {
89
+ if (name === '__proto__') continue
73
90
  if (name === 'nodes') {
74
91
  this.nodes = []
75
92
  for (let node of defaults[name]) {
@@ -381,47 +398,68 @@ class Node {
381
398
  }
382
399
 
383
400
  toJSON(_, inputs) {
384
- let fixed = {}
385
401
  let emitInputs = inputs == null
386
402
  inputs = inputs || new Map()
387
- let inputsNextIndex = 0
388
403
 
389
- for (let name in this) {
390
- if (!Object.prototype.hasOwnProperty.call(this, name)) {
391
- /* c8 ignore next 2 */
392
- continue
393
- }
394
- if (name === 'parent' || name === 'proxyCache') continue
395
- let value = this[name]
396
-
397
- if (Array.isArray(value)) {
398
- fixed[name] = value.map(i => {
399
- if (typeof i === 'object' && i.toJSON) {
400
- return i.toJSON(null, inputs)
404
+ // A worklist instead of recursive `toJSON()` calls to survive deeply
405
+ // nested trees. Each entry converts one node and writes the result
406
+ // into the already converted parent by [holder, key].
407
+ let holderOfRoot = []
408
+ let queue = [[this, holderOfRoot, 0]]
409
+
410
+ for (let step = 0; step < queue.length; step++) {
411
+ let [node, holder, key] = queue[step]
412
+ let fixed = {}
413
+ holder[key] = fixed
414
+
415
+ for (let name in node) {
416
+ if (!Object.prototype.hasOwnProperty.call(node, name)) {
417
+ /* c8 ignore next 2 */
418
+ continue
419
+ }
420
+ if (name === 'parent' || name === 'proxyCache') continue
421
+ let value = node[name]
422
+
423
+ if (Array.isArray(value)) {
424
+ let fixedArray = []
425
+ fixed[name] = fixedArray
426
+ for (let i = 0; i < value.length; i++) {
427
+ let item = value[i]
428
+ if (typeof item === 'object' && item.toJSON) {
429
+ if (item.toJSON === Node.prototype.toJSON) {
430
+ queue.push([item, fixedArray, i])
431
+ } else {
432
+ fixedArray[i] = item.toJSON(null, inputs)
433
+ }
434
+ } else {
435
+ fixedArray[i] = item
436
+ }
437
+ }
438
+ } else if (typeof value === 'object' && value.toJSON) {
439
+ if (value.toJSON === Node.prototype.toJSON) {
440
+ queue.push([value, fixed, name])
401
441
  } else {
402
- return i
442
+ fixed[name] = value.toJSON(null, inputs)
403
443
  }
404
- })
405
- } else if (typeof value === 'object' && value.toJSON) {
406
- fixed[name] = value.toJSON(null, inputs)
407
- } else if (name === 'source') {
408
- if (value == null) continue
409
- let inputId = inputs.get(value.input)
410
- if (inputId == null) {
411
- inputId = inputsNextIndex
412
- inputs.set(value.input, inputsNextIndex)
413
- inputsNextIndex++
414
- }
415
- fixed[name] = {
416
- end: value.end,
417
- inputId,
418
- start: value.start
444
+ } else if (name === 'source') {
445
+ if (value == null) continue
446
+ let inputId = inputs.get(value.input)
447
+ if (inputId == null) {
448
+ inputId = inputs.size
449
+ inputs.set(value.input, inputId)
450
+ }
451
+ fixed[name] = {
452
+ end: value.end,
453
+ inputId,
454
+ start: value.start
455
+ }
456
+ } else {
457
+ fixed[name] = value
419
458
  }
420
- } else {
421
- fixed[name] = value
422
459
  }
423
460
  }
424
461
 
462
+ let fixed = holderOfRoot[0]
425
463
  if (emitInputs) {
426
464
  fixed.inputs = [...inputs.keys()].map(input => input.toJSON())
427
465
  }
package/lib/processor.js CHANGED
@@ -7,7 +7,7 @@ let Root = require('./root')
7
7
 
8
8
  class Processor {
9
9
  constructor(plugins = []) {
10
- this.version = '8.5.16'
10
+ this.version = '8.5.17'
11
11
  this.plugins = this.normalize(plugins)
12
12
  }
13
13
 
@@ -31,27 +31,74 @@ function capitalize(str) {
31
31
  return str[0].toUpperCase() + str.slice(1)
32
32
  }
33
33
 
34
+ function atruleStart(str, node) {
35
+ let name = '@' + node.name
36
+ let params = node.params ? str.rawValue(node, 'params') : ''
37
+
38
+ if (typeof node.raws.afterName !== 'undefined') {
39
+ name += node.raws.afterName
40
+ } else if (params) {
41
+ name += ' '
42
+ }
43
+
44
+ return name + params
45
+ }
46
+
47
+ function pushBody(str, stack, node) {
48
+ let nodes = node.nodes
49
+ let last = nodes.length - 1
50
+ while (last > 0) {
51
+ if (nodes[last].type !== 'comment') break
52
+ last -= 1
53
+ }
54
+
55
+ let semicolon = str.raw(node, 'semicolon')
56
+ let isDocument = node.type === 'document'
57
+ for (let i = nodes.length - 1; i >= 0; i--) {
58
+ stack.push({
59
+ document: isDocument,
60
+ node: nodes[i],
61
+ semicolon: last !== i || semicolon
62
+ })
63
+ }
64
+ }
65
+
66
+ function pushBlock(str, stack, node, start) {
67
+ let between = str.raw(node, 'between', 'beforeOpen')
68
+ str.builder(escapeHTMLInCSS(start + between) + '{', node, 'start')
69
+
70
+ let hasNodes = node.nodes && node.nodes.length
71
+ let close = () => {
72
+ let after = hasNodes
73
+ ? str.raw(node, 'after')
74
+ : str.raw(node, 'after', 'emptyBody')
75
+ if (after) str.builder(escapeHTMLInCSS(after))
76
+ str.builder('}', node, 'end')
77
+ if (node.type === 'rule' && node.raws.ownSemicolon) {
78
+ str.builder(escapeHTMLInCSS(node.raws.ownSemicolon), node, 'end')
79
+ }
80
+ }
81
+
82
+ if (hasNodes) {
83
+ stack.push(close)
84
+ pushBody(str, stack, node)
85
+ } else {
86
+ close()
87
+ }
88
+ }
89
+
34
90
  class Stringifier {
35
91
  constructor(builder) {
36
92
  this.builder = builder
37
93
  }
38
94
 
39
95
  atrule(node, semicolon) {
40
- let raws = node.raws
41
- let name = '@' + node.name
42
- let params = node.params ? this.rawValue(node, 'params') : ''
43
-
44
- if (typeof raws.afterName !== 'undefined') {
45
- name += raws.afterName
46
- } else if (params) {
47
- name += ' '
48
- }
49
-
96
+ let start = atruleStart(this, node)
50
97
  if (node.nodes) {
51
- this.block(node, name + params)
98
+ this.block(node, start)
52
99
  } else {
53
- let end = (raws.between || '') + (semicolon ? ';' : '')
54
- this.builder(escapeHTMLInCSS(name + params + end), node)
100
+ let end = (node.raws.between || '') + (semicolon ? ';' : '')
101
+ this.builder(escapeHTMLInCSS(start + end), node)
55
102
  }
56
103
  }
57
104
 
@@ -101,20 +148,38 @@ class Stringifier {
101
148
  }
102
149
 
103
150
  body(node) {
104
- let nodes = node.nodes
105
- let last = nodes.length - 1
106
- while (last > 0) {
107
- if (nodes[last].type !== 'comment') break
108
- last -= 1
109
- }
151
+ // Rules and at-rules are expanded into an explicit stack instead of
152
+ // recursive `stringify()` calls to survive deeply nested trees.
153
+ // If a subclass changes the traversal methods, its children go
154
+ // through `stringify()` to keep the override in charge.
155
+ let proto = Stringifier.prototype
156
+ let expandable = ['atrule', 'block', 'body', 'rule', 'stringify'].every(
157
+ method => this[method] === proto[method]
158
+ )
159
+
160
+ let stack = []
161
+ pushBody(this, stack, node)
162
+
163
+ while (stack.length > 0) {
164
+ let entry = stack.pop()
165
+ if (typeof entry === 'function') {
166
+ entry()
167
+ continue
168
+ }
110
169
 
111
- let semicolon = this.raw(node, 'semicolon')
112
- let isDocument = node.type === 'document'
113
- for (let i = 0; i < nodes.length; i++) {
114
- let child = nodes[i]
170
+ let child = entry.node
115
171
  let before = this.raw(child, 'before')
116
- if (before) this.builder(isDocument ? before : escapeHTMLInCSS(before))
117
- this.stringify(child, last !== i || semicolon)
172
+ if (before) {
173
+ this.builder(entry.document ? before : escapeHTMLInCSS(before))
174
+ }
175
+
176
+ if (expandable && child.type === 'rule') {
177
+ pushBlock(this, stack, child, this.rawValue(child, 'selector'))
178
+ } else if (expandable && child.type === 'atrule' && child.nodes) {
179
+ pushBlock(this, stack, child, atruleStart(this, child))
180
+ } else {
181
+ this.stringify(child, entry.semicolon)
182
+ }
118
183
  }
119
184
  }
120
185
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "postcss",
3
- "version": "8.5.16",
3
+ "version": "8.5.17",
4
4
  "description": "Tool for transforming styles with JS plugins",
5
5
  "keywords": [
6
6
  "css",