mirror of
https://github.com/hanzoai/postcss.git
synced 2026-09-24 17:01:56 +00:00
fromJSON() attached child nodes through the container constructor, which runs them back through append()/normalize(). For root-level children that re-applies insertion spacing normalization and overwrites each node's own raws.before with the previous sibling's, so toJSON() -> fromJSON() was not lossless: stylesheets with non-uniform blank lines between top-level rules came back with their spacing flattened. Rehydrate children separately and attach them directly, keeping the raws exactly as serialized.
69 lines
1.8 KiB
JavaScript
69 lines
1.8 KiB
JavaScript
'use strict'
|
|
|
|
let AtRule = require('./at-rule')
|
|
let Comment = require('./comment')
|
|
let Declaration = require('./declaration')
|
|
let Input = require('./input')
|
|
let PreviousMap = require('./previous-map')
|
|
let Root = require('./root')
|
|
let Rule = require('./rule')
|
|
|
|
function fromJSON(json, inputs) {
|
|
if (Array.isArray(json)) return json.map(n => fromJSON(n))
|
|
|
|
let { inputs: ownInputs, ...defaults } = json
|
|
if (ownInputs) {
|
|
inputs = []
|
|
for (let input of ownInputs) {
|
|
let inputHydrated = { ...input, __proto__: Input.prototype }
|
|
if (inputHydrated.map) {
|
|
inputHydrated.map = {
|
|
...inputHydrated.map,
|
|
__proto__: PreviousMap.prototype
|
|
}
|
|
}
|
|
inputs.push(inputHydrated)
|
|
}
|
|
}
|
|
// Rehydrate children separately and attach them after construction.
|
|
// Passing them through the container constructor would re-run insertion
|
|
// spacing normalization and overwrite each child's own `raws.before`.
|
|
let nodes
|
|
if (defaults.nodes) {
|
|
nodes = json.nodes.map(n => fromJSON(n, inputs))
|
|
delete defaults.nodes
|
|
}
|
|
if (defaults.source) {
|
|
let { inputId, ...source } = defaults.source
|
|
defaults.source = source
|
|
if (inputId != null) {
|
|
defaults.source.input = inputs[inputId]
|
|
}
|
|
}
|
|
|
|
let node
|
|
if (defaults.type === 'root') {
|
|
node = new Root(defaults)
|
|
} else if (defaults.type === 'decl') {
|
|
node = new Declaration(defaults)
|
|
} else if (defaults.type === 'rule') {
|
|
node = new Rule(defaults)
|
|
} else if (defaults.type === 'comment') {
|
|
node = new Comment(defaults)
|
|
} else if (defaults.type === 'atrule') {
|
|
node = new AtRule(defaults)
|
|
} else {
|
|
throw new Error('Unknown node type: ' + json.type)
|
|
}
|
|
|
|
if (nodes) {
|
|
node.nodes = nodes
|
|
for (let child of nodes) child.parent = node
|
|
}
|
|
|
|
return node
|
|
}
|
|
|
|
module.exports = fromJSON
|
|
fromJSON.default = fromJSON
|