postcss 8.5.14 → 8.5.16

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 CHANGED
@@ -23,6 +23,3 @@ and JetBrains. The [Autoprefixer] and [Stylelint] PostCSS plugins are some o
23
23
  [Autoprefixer]: https://github.com/postcss/autoprefixer
24
24
  [Stylelint]: https://stylelint.io/
25
25
  [plugins]: https://github.com/postcss/postcss#plugins
26
-
27
- ## Docs
28
- Read full docs **[here](https://postcss.org/)**.
package/lib/fromJSON.js CHANGED
@@ -25,8 +25,13 @@ function fromJSON(json, inputs) {
25
25
  inputs.push(inputHydrated)
26
26
  }
27
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
28
32
  if (defaults.nodes) {
29
- defaults.nodes = json.nodes.map(n => fromJSON(n, inputs))
33
+ nodes = json.nodes.map(n => fromJSON(n, inputs))
34
+ delete defaults.nodes
30
35
  }
31
36
  if (defaults.source) {
32
37
  let { inputId, ...source } = defaults.source
@@ -35,19 +40,28 @@ function fromJSON(json, inputs) {
35
40
  defaults.source.input = inputs[inputId]
36
41
  }
37
42
  }
43
+
44
+ let node
38
45
  if (defaults.type === 'root') {
39
- return new Root(defaults)
46
+ node = new Root(defaults)
40
47
  } else if (defaults.type === 'decl') {
41
- return new Declaration(defaults)
48
+ node = new Declaration(defaults)
42
49
  } else if (defaults.type === 'rule') {
43
- return new Rule(defaults)
50
+ node = new Rule(defaults)
44
51
  } else if (defaults.type === 'comment') {
45
- return new Comment(defaults)
52
+ node = new Comment(defaults)
46
53
  } else if (defaults.type === 'atrule') {
47
- return new AtRule(defaults)
54
+ node = new AtRule(defaults)
48
55
  } else {
49
56
  throw new Error('Unknown node type: ' + json.type)
50
57
  }
58
+
59
+ if (nodes) {
60
+ node.nodes = nodes
61
+ for (let child of nodes) child.parent = node
62
+ }
63
+
64
+ return node
51
65
  }
52
66
 
53
67
  module.exports = fromJSON
package/lib/input.js CHANGED
@@ -206,12 +206,15 @@ class Input {
206
206
  if (!this.map) return false
207
207
  let consumer = this.map.consumer()
208
208
 
209
- let from = consumer.originalPositionFor({ column, line })
209
+ let from = consumer.originalPositionFor({ column: column - 1, line })
210
210
  if (!from.source) return false
211
211
 
212
212
  let to
213
213
  if (typeof endLine === 'number') {
214
- to = consumer.originalPositionFor({ column: endColumn, line: endLine })
214
+ to = consumer.originalPositionFor({
215
+ column: endColumn - 1,
216
+ line: endLine
217
+ })
215
218
  }
216
219
 
217
220
  let fromUrl
@@ -226,8 +229,8 @@ class Input {
226
229
  }
227
230
 
228
231
  let result = {
229
- column: from.column,
230
- endColumn: to && to.column,
232
+ column: from.column + 1,
233
+ endColumn: to && to.column + 1,
231
234
  endLine: to && to.line,
232
235
  line: from.line,
233
236
  url: fromUrl.toString()
package/lib/node.js CHANGED
@@ -73,7 +73,10 @@ class Node {
73
73
  if (name === 'nodes') {
74
74
  this.nodes = []
75
75
  for (let node of defaults[name]) {
76
- if (typeof node.clone === 'function') {
76
+ // Clone only nodes that already belong to another tree, so passing a
77
+ // freshly created (parent-less) node adopts that instance instead of
78
+ // a copy and keeps the caller's reference usable. See #1987.
79
+ if (typeof node.clone === 'function' && node.parent) {
77
80
  this.append(node.clone())
78
81
  } else {
79
82
  this.append(node)
@@ -206,14 +209,18 @@ class Node {
206
209
  }
207
210
 
208
211
  positionBy(opts = {}) {
209
- let pos = this.source.start
212
+ let inputString =
213
+ 'document' in this.source.input
214
+ ? this.source.input.document
215
+ : this.source.input.css
216
+ let pos = {
217
+ column: this.source.start.column,
218
+ line: this.source.start.line,
219
+ offset: sourceOffset(inputString, this.source.start)
220
+ }
210
221
  if (opts.index) {
211
222
  pos = this.positionInside(opts.index)
212
223
  } else if (opts.word) {
213
- let inputString =
214
- 'document' in this.source.input
215
- ? this.source.input.document
216
- : this.source.input.css
217
224
  let stringRepresentation = inputString.slice(
218
225
  sourceOffset(inputString, this.source.start),
219
226
  sourceOffset(inputString, this.source.end)
@@ -298,7 +305,7 @@ class Node {
298
305
  line: opts.start.line,
299
306
  offset: sourceOffset(inputString, opts.start)
300
307
  }
301
- } else if (opts.index) {
308
+ } else if (typeof opts.index === 'number') {
302
309
  start = this.positionInside(opts.index)
303
310
  }
304
311
 
@@ -310,7 +317,7 @@ class Node {
310
317
  }
311
318
  } else if (typeof opts.endIndex === 'number') {
312
319
  end = this.positionInside(opts.endIndex)
313
- } else if (opts.index) {
320
+ } else if (typeof opts.index === 'number') {
314
321
  end = this.positionInside(opts.index + 1)
315
322
  }
316
323
  }
package/lib/parser.js CHANGED
@@ -20,6 +20,12 @@ function findLastWithPosition(tokens) {
20
20
  }
21
21
  }
22
22
 
23
+ function tokensToString(tokens, from, to) {
24
+ let result = ''
25
+ for (let i = from; i < to; i++) result += tokens[i][1]
26
+ return result
27
+ }
28
+
23
29
  class Parser {
24
30
  constructor(input) {
25
31
  this.input = input
@@ -132,9 +138,10 @@ class Parser {
132
138
  if (founded === 2) break
133
139
  }
134
140
  }
135
- // If the token is a word, e.g. `!important`, `red` or any other valid property's value.
136
- // Then we need to return the colon after that word token. [3] is the "end" colon of that word.
137
- // And because we need it after that one we do +1 to get the next one.
141
+ // If the token is a word, e.g. `!important`, `red` or any other valid
142
+ // property's value. Then we need to return the colon after that word
143
+ // token. [3] is the "end" colon of that word. And because we need it
144
+ // after that one we do +1 to get the next one.
138
145
  throw this.input.error(
139
146
  'Missed semicolon',
140
147
  token[0] === 'word' ? token[3] + 1 : token[2]
@@ -207,50 +214,50 @@ class Parser {
207
214
  )
208
215
  node.source.end.offset++
209
216
 
210
- while (tokens[0][0] !== 'word') {
211
- if (tokens.length === 1) this.unknownWord(tokens)
212
- node.raws.before += tokens.shift()[1]
217
+ let start = 0
218
+ while (tokens[start][0] !== 'word') {
219
+ if (start === tokens.length - 1) this.unknownWord([tokens[start]])
220
+ start++
213
221
  }
214
- node.source.start = this.getPosition(tokens[0][2])
222
+ node.raws.before += tokensToString(tokens, 0, start)
223
+ node.source.start = this.getPosition(tokens[start][2])
215
224
 
216
- node.prop = ''
217
- while (tokens.length) {
218
- let type = tokens[0][0]
225
+ let propStart = start
226
+ while (start < tokens.length) {
227
+ let type = tokens[start][0]
219
228
  if (type === ':' || type === 'space' || type === 'comment') {
220
229
  break
221
230
  }
222
- node.prop += tokens.shift()[1]
231
+ start++
223
232
  }
233
+ node.prop = tokensToString(tokens, propStart, start)
224
234
 
225
- node.raws.between = ''
226
-
235
+ let betweenStart = start
227
236
  let token
228
- while (tokens.length) {
229
- token = tokens.shift()
230
-
231
- if (token[0] === ':') {
232
- node.raws.between += token[1]
233
- break
234
- } else {
235
- if (token[0] === 'word' && /\w/.test(token[1])) {
236
- this.unknownWord([token])
237
- }
238
- node.raws.between += token[1]
237
+ while (start < tokens.length) {
238
+ token = tokens[start]
239
+ start++
240
+ if (token[0] === ':') break
241
+ if (token[0] === 'word' && /\w/.test(token[1])) {
242
+ this.unknownWord([token])
239
243
  }
240
244
  }
245
+ node.raws.between = tokensToString(tokens, betweenStart, start)
241
246
 
242
247
  if (node.prop[0] === '_' || node.prop[0] === '*') {
243
248
  node.raws.before += node.prop[0]
244
249
  node.prop = node.prop.slice(1)
245
250
  }
246
251
 
247
- let firstSpaces = []
248
- let next
249
- while (tokens.length) {
250
- next = tokens[0][0]
252
+ let firstSpacesStart = start
253
+ while (start < tokens.length) {
254
+ let next = tokens[start][0]
251
255
  if (next !== 'space' && next !== 'comment') break
252
- firstSpaces.push(tokens.shift())
256
+ start++
253
257
  }
258
+ let firstSpaces = tokens.slice(firstSpacesStart, start)
259
+
260
+ tokens = tokens.slice(start)
254
261
 
255
262
  this.precheckMissedSemicolon(tokens)
256
263
 
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.14'
10
+ this.version = '8.5.16'
11
11
  this.plugins = this.normalize(plugins)
12
12
  }
13
13
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "postcss",
3
- "version": "8.5.14",
3
+ "version": "8.5.16",
4
4
  "description": "Tool for transforming styles with JS plugins",
5
5
  "keywords": [
6
6
  "css",
@@ -78,7 +78,7 @@
78
78
  "./package.json": "./package.json"
79
79
  },
80
80
  "dependencies": {
81
- "nanoid": "^3.3.11",
81
+ "nanoid": "^3.3.12",
82
82
  "picocolors": "^1.1.1",
83
83
  "source-map-js": "^1.2.1"
84
84
  },