Skip to content

Preserve node raws when rehydrating a JSON AST#2100

Merged
ai merged 1 commit into
postcss:mainfrom
sarathfrancis90:fix/fromjson-preserve-raws
Jun 28, 2026
Merged

Preserve node raws when rehydrating a JSON AST#2100
ai merged 1 commit into
postcss:mainfrom
sarathfrancis90:fix/fromjson-preserve-raws

Conversation

@sarathfrancis90

Copy link
Copy Markdown
Contributor

fromJSON(root.toJSON()) isn't lossless when a stylesheet has uneven spacing between its top-level nodes:

let css = 'a {}\nb {}\n\nc {}\n'
let root = postcss.parse(css)
postcss.fromJSON(JSON.parse(JSON.stringify(root.toJSON()))).toString()
// => 'a {}\nb {}\nc {}\n'   the blank line before `c` is gone

toJSON() serializes every raws.before correctly — the loss happens on the way back. fromJSON builds the child nodes and then passes them to the container constructor, which appends them; for root children that re-runs the insertion spacing logic in Root.normalize, overwriting each node's own raws.before with the previous sibling's. So every top-level node after the first inherits the first one's spacing.

It matters because round-tripping through JSON is meant to restore an AST exactly (e.g. caching a parsed AST), so a rehydrated root should stringify to the same CSS as the original.

I rehydrate the children and attach them directly instead of routing them through append, leaving their raws untouched. Runtime append/insertion behavior is unchanged. Found it round-tripping the postcss-parser-tests fixtures; added a regression test and pnpm test is green.

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.
@ai
ai merged commit 3828982 into postcss:main Jun 28, 2026
10 checks passed
@ai

ai commented Jun 28, 2026

Copy link
Copy Markdown
Member

Thanks!

@ai

ai commented Jun 28, 2026

Copy link
Copy Markdown
Member

Released in 8.5.16.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants