Skip to content

Preserve source files on CSS prepended from composed dependencies#173

Open
soreavis wants to merge 1 commit into
madyankin:masterfrom
soreavis:preserve-composed-source
Open

Preserve source files on CSS prepended from composed dependencies#173
soreavis wants to merge 1 commit into
madyankin:masterfrom
soreavis:preserve-composed-source

Conversation

@soreavis

Copy link
Copy Markdown

CSS collected from composes dependencies is prepended as one concatenated string, so the re-parsed nodes carry no source.input.file. Any plugin that runs afterwards and needs to resolve relative paths — bundler url rewriters are the practical case — has nothing to resolve against. That's the metadata half of #149, and it's what breaks background images in composed CSS modules over in vitejs/vite#15410.

This keeps the prepend byte-identical (the snapshot suite passes untouched) and grafts per-file sources onto the prepended nodes afterwards: each dependency is re-parsed with its own from, and sources are paired by position. A node-count guard skips the graft if malformed CSS merges nodes across a file boundary, so a node can end up unattributed as before but never attributed to the wrong file. Custom loaders without the new finalSources getter keep the old path.

finalSource is now derived from finalSources, and there's a test asserting the composed declarations keep their origin file.

When a CSS module uses `composes: x from "./other.css"`, the CSS of
that other file is copied into the output. It was copied as plain
text, so PostCSS no longer knew which file each copied rule came
from.

Tools that run after postcss-modules need exactly that information.
A bundler's URL rewriter, for example, has to turn `url(./image.png)`
into a working path - and to do that it must know the directory of
the file the rule was written in. With the information gone, those
paths silently break.

The copied CSS still produces exactly the same output as before. But
now each dependency is also parsed once more under its own filename,
and the file information from that parse is attached to the copied
rules, matched one-to-one by position. If broken CSS makes two files'
rules merge at a boundary, the one-to-one match no longer holds - in
that case nothing is attached, which is the old behavior, rather than
attaching the wrong file. Custom loaders that don't provide the new
`finalSources` getter are unaffected.

See madyankin#149.
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.

1 participant