Skip to content

fix: strip BOM before processing with postcss - #1684

Merged
alexander-akait merged 1 commit into
mainfrom
fix/strip-bom-before-postcss
Aug 27, 2026
Merged

fix: strip BOM before processing with postcss#1684
alexander-akait merged 1 commit into
mainfrom
fix/strip-bom-before-postcss

Conversation

@alexander-akait

Copy link
Copy Markdown
Member

Summary

Fixes #1678. postcss stripped a leading BOM until 8.5.24 and preserves it since, so a BOM added by an earlier loader (sass-loader with charset: true, its production default) survived into the module and landed mid-file once stylesheets were concatenated, silently dropping the rule after it.

This builds on @ShGKme's #1679 and credits that analysis; it differs in one respect. content is not always a string — when a previous loader hands over its AST via meta.ast, content is a postcss Root, and charCodeAt on it throws TypeError: content.charCodeAt is not a function (8 existing tests fail that way). So the strip is applied to both inputs postcss accepts: the string, and the Root, where the BOM lives on source.input.hasBOM rather than in the tree. The sass-loaderpostcss-loadercss-loader chain takes that second path.

What kind of change does this PR introduce?

fix

Did you add tests for your changes?

Yes — two cases in test/loader.test.js with fixtures in test/fixtures/modules/issue-1678/, one per input path. Both were confirmed to fail without their half of the fix, and the whole suite passes on postcss 8.5.5 (the lockfile version) and on 8.5.26, so they do not depend on which patch is installed.

Does this PR introduce a breaking change?

No — it restores the output postcss produced before 8.5.24.

If relevant, what needs to be documented once your changes are merged or what have you already documented?

n/a

Use of AI

Yes — Claude Code wrote the tests first and confirmed each fails without the corresponding branch of the fix, found the Root case by running the existing suite against postcss 8.5.26, and verified the suite on both postcss versions. Reviewed and edited by me before pushing.


Generated by Claude Code

postcss stripped a leading BOM until 8.5.24 and preserves it since, so a
BOM added by an earlier loader (sass-loader with `charset: true`) survived
into the module and landed mid-file once stylesheets were concatenated,
silently dropping the rule after it.

Strip it for both inputs postcss accepts: the string, and the `Root` a
previous loader hands over as `meta.ast`, where the BOM lives on
`source.input.hasBOM` rather than in the tree.
@codecov

codecov Bot commented Aug 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.28%. Comparing base (488cdb1) to head (ad75b64).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1684      +/-   ##
==========================================
+ Coverage   96.25%   96.28%   +0.02%     
==========================================
  Files          10       10              
  Lines        1201     1210       +9     
  Branches      463      468       +5     
==========================================
+ Hits         1156     1165       +9     
  Misses         40       40              
  Partials        5        5              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@alexander-akait
alexander-akait merged commit bd20834 into main Aug 27, 2026
18 of 19 checks passed
@alexander-akait
alexander-akait deleted the fix/strip-bom-before-postcss branch August 27, 2026 17:25
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.

Leading BOM from a loader-generated module survives into the middle of concatenated CSS (postcss 8.5.24)

1 participant