@@ -120,6 +120,115 @@ div[data-size="calc(3*3)"] {
120120}
121121```
122122
123+ #### ` strictWhitespace ` (default: ` true ` )
124+
125+ Reject inputs that don't follow [ CSS Values 4 §10.1] [ css-values-4-syntax ] 's
126+ whitespace rule around binary ` + ` / ` - ` . With the default, ` calc(2px+3px) `
127+ is rejected (it tokenizes as ` [2px, +, 3px] ` but lacks whitespace around
128+ the ` + ` ). Set to ` false ` to recover jison-era lenient parsing.
129+
130+ ``` js
131+ calc ({strictWhitespace: false })
132+ ```
133+
134+ #### ` preserveOrder ` (default: ` false ` )
135+
136+ Preserve input order of commutative operands rather than reordering to the
137+ canonical (numeric-first, then by-discovery, then opaque) shape that
138+ [ ` @csstools/css-calc ` ] [ csstools-css-calc ] also uses.
139+
140+ ``` js
141+ calc ({preserveOrder: true })
142+ ```
143+
144+ | Input | Default | ` preserveOrder: true ` |
145+ | ---| ---| ---|
146+ | ` calc(var(--foo) + 10px) ` | ` calc(10px + var(--foo)) ` | ` calc(var(--foo) + 10px) ` |
147+ | ` calc(1px + 1) ` | ` calc(1 + 1px) ` | ` calc(1px + 1) ` |
148+ | ` calc(var(--m) * 1px) ` | ` calc(1px * var(--m)) ` | ` calc(var(--m) * 1px) ` |
149+
150+ ` preserveOrder ` operates on outer-expression positions; nested-sum
151+ flattening, constant folding, and reciprocal conversion (` a / 2 ` →
152+ ` a * 0.5 ` ) all collapse positions before assembly and can't be recovered.
153+
154+ #### ` dropZeroIdentities ` (default: ` false ` )
155+
156+ Drop ` + 0px ` / ` + 0em ` identities from sums when another term in the same
157+ sum already carries the type. The default preserves zero-valued buckets
158+ because [ WPT calc-serialization-002] [ wpt-calc-serialization ] and the
159+ round-trip property both require it (` calc(0px + 100%) ` is a length-
160+ percentage; collapsing to ` 100% ` loses the type signal).
161+
162+ ``` js
163+ calc ({dropZeroIdentities: true })
164+ ```
165+
166+ | Input | Default | ` dropZeroIdentities: true ` |
167+ | ---| ---| ---|
168+ | ` calc(100px - (100px - 100%)) ` | ` calc(0px + 100%) ` | ` 100% ` |
169+ | ` calc(99.99% * 1/1 - 0rem) ` | ` calc(99.99% + 0rem) ` | ` 99.99% ` |
170+ | ` calc((100px - 1em) + (-50px + 1em)) ` | ` calc(50px + 0em) ` | ` 50px ` |
171+
172+ ### Migrating from ` postcss-calc ` 10.x
173+
174+ 10.x used a [ jison] [ jison ] -generated parser; 11.x ships a hand-written
175+ Pratt parser whose simplifier follows [ CSS Values 4] [ css-values-4 ] . Most
176+ inputs reduce to identical output, but some 10.x results were jison
177+ implementation choices rather than spec-required behavior. The three opt-
178+ in flags above recover the most visible differences. Setting all three
179+ matches 10.x as closely as 11.x will go:
180+
181+ ``` js
182+ calc ({
183+ strictWhitespace: false ,
184+ preserveOrder: true ,
185+ dropZeroIdentities: true ,
186+ })
187+ ```
188+
189+ A handful of 11.x behaviors aren't flag-controlled — they're spec-aligned
190+ or canonical-form decisions:
191+
192+ - ** Constant folding.** ` calc(43 + pi) ` now folds to ` 46.14159 ` (§10.7.1).
193+ 10.x kept ` pi ` / ` e ` symbolic.
194+ - ** Reciprocal conversion.** ` calc(var(--x) / 2) ` becomes
195+ ` calc(var(--x) * 0.5) ` . The two are mathematically equivalent; 10.x kept
196+ the division shape.
197+ - ** Distributive multiplication.** ` calc(0.5 * (100vw - 10px)) ` becomes
198+ ` calc(50vw - 5px) ` .
199+ - ** Unit case normalization.** ` 2PX ` becomes ` 2px ` (CSS units are case-
200+ insensitive; lowercase is conventional).
201+ - ** Calc unwrap (§10.6).** ` calc(var(--foo)) ` becomes ` var(--foo) ` — a
202+ ` calc() ` containing a single value is replaced by that value.
203+ - ** Spec-style spaced operators.** ` 2px*var(--x) ` is serialized as
204+ ` 2px * var(--x) ` . The tokenizer is unaffected; only output spacing
205+ differs.
206+ - ** Division by zero / by a unit.** ` calc(500px/0) ` reduces to
207+ ` calc(infinity * 1px) ` (§10.13) instead of throwing. Use ` onParseError `
208+ if you want validation behavior.
209+
210+ #### ` onParseError `
211+
212+ Callback invoked when a ` calc() ` body fails to parse or simplify. Matches
213+ [ ` @csstools/css-calc ` ] [ csstools-css-calc ] 's shape:
214+
215+ ``` js
216+ calc ({
217+ onParseError : (err , input ) => {
218+ throw err; // or log, route to a different channel, etc.
219+ }
220+ })
221+ ```
222+
223+ When omitted, errors are reported via PostCSS ` result.warn() ` so the
224+ plugin never throws at the postcss level.
225+
226+ [ css-values-4 ] : https://www.w3.org/TR/css-values-4/
227+ [ css-values-4-syntax ] : https://www.w3.org/TR/css-values-4/#calc-syntax
228+ [ csstools-css-calc ] : https://www.npmjs.com/package/@csstools/css-calc
229+ [ wpt-calc-serialization ] : https://github.com/web-platform-tests/wpt/blob/master/css/css-values/calc-serialization-002.html
230+ [ jison ] : https://github.com/zaach/jison
231+
123232---
124233
125234## Related PostCSS plugins
0 commit comments