Conversation
…nify lengths This closes #774. By introducing a new OverlaySegment system in css_parse, we can insert new snippets of css before, after or replacing chunks of css. This allows us to then use this in the transformer trait to write reasonably ergonomic transformers which can stack. This also closes #777 by introducing the ReduceLengths transformer which is the first to use this kind of logic.
keithamus
added a commit
that referenced
this pull request
Jan 21, 2026
…icable In #777 @yisibl pointed out a bug in ReduceLengths (#815) in that unitless zero is not always semantically equivalent to `0px`. This is because: - Some values, e.g. `line-height` and `tab-size` have distinct `<number>` and `<length>` types. These types are distinct because they have semantic meaning (line-height uses number as a multiplier, so `1` is "1x font-size", tab-size uses number as "the number of spaces"). While for a single property a line-height of `0` vs `0px` might be _visually_ equivalent, this can cause issues with animation. - Calc's system for resolving the type requires units to be equivalent, so `calc(100px - 0px)` returns a Length, while `calc(100px - 0)` returns a Number which will be invalid in some contexts. - For unknown properties (or custom ones) we cannot make the determination whether or not they'll be used in calc, or whether or not this is a property we're not-yet parsing. Because of these gotchas, unitless zero is not _always_ equivalent to `0px`. Therefore it is not safe for us to always convert `0px` to unitless zero. However, we can reason about this using metadata. This change introduces a new UnitlessZeroResolves metadata bit, which can be used to determine how a declaration might reason about unitless zero in an abstract way (without looking up property names). The metadata system propagates through nodes, so later on when we parse calc/custom properties better, we can set the UnitlessZeroResolves::Number flag and it should retain this new behaviour. ReduceLengths has now been extended so that when it visits a declaration it will set a boolean based on this value, meaning traversing into the declaration, it can be aware as to whether or not it should coerce these values. This allows us to continue to reduce `0px` to `0` when they are semantically equivalent, while also ensuring we're only doing so when they actually are.
keithamus
added a commit
that referenced
this pull request
Jan 21, 2026
…icable In #777 @yisibl pointed out a bug in ReduceLengths (#815) in that unitless zero is not always semantically equivalent to `0px`. This is because: - Some values, e.g. `line-height` and `tab-size` have distinct `<number>` and `<length>` types. These types are distinct because they have semantic meaning (line-height uses number as a multiplier, so `1` is "1x font-size", tab-size uses number as "the number of spaces"). While for a single property a line-height of `0` vs `0px` might be _visually_ equivalent, this can cause issues with animation. - Calc's system for resolving the type requires units to be equivalent, so `calc(100px - 0px)` returns a Length, while `calc(100px - 0)` returns a Number which will be invalid in some contexts. - For unknown properties (or custom ones) we cannot make the determination whether or not they'll be used in calc, or whether or not this is a property we're not-yet parsing. This was separated out into #820. Because of these gotchas, unitless zero is not _always_ equivalent to `0px`. Therefore it is not safe for us to always convert `0px` to unitless zero. However, we can reason about this using metadata. This change introduces a new UnitlessZeroResolves metadata bit, which can be used to determine how a declaration might reason about unitless zero in an abstract way (without looking up property names). The metadata system propagates through nodes, so later on when we parse calc/custom properties better, we can set the UnitlessZeroResolves::Number flag and it should retain this new behaviour. ReduceLengths has now been extended so that when it visits a declaration it will set a boolean based on this value, meaning traversing into the declaration, it can be aware as to whether or not it should coerce these values. This allows us to continue to reduce `0px` to `0` when they are semantically equivalent, while also ensuring we're only doing so when they actually are. This fixes #820.
keithamus
added a commit
that referenced
this pull request
Jan 21, 2026
…icable (#821) In #777 @yisibl pointed out a bug in ReduceLengths (#815) in that unitless zero is not always semantically equivalent to `0px`. This is because: - Some values, e.g. `line-height` and `tab-size` have distinct `<number>` and `<length>` types. These types are distinct because they have semantic meaning (line-height uses number as a multiplier, so `1` is "1x font-size", tab-size uses number as "the number of spaces"). While for a single property a line-height of `0` vs `0px` might be _visually_ equivalent, this can cause issues with animation. - Calc's system for resolving the type requires units to be equivalent, so `calc(100px - 0px)` returns a Length, while `calc(100px - 0)` returns a Number which will be invalid in some contexts. - For unknown properties (or custom ones) we cannot make the determination whether or not they'll be used in calc, or whether or not this is a property we're not-yet parsing. This was separated out into #820. Because of these gotchas, unitless zero is not _always_ equivalent to `0px`. Therefore it is not safe for us to always convert `0px` to unitless zero. However, we can reason about this using metadata. This change introduces a new UnitlessZeroResolves metadata bit, which can be used to determine how a declaration might reason about unitless zero in an abstract way (without looking up property names). The metadata system propagates through nodes, so later on when we parse calc/custom properties better, we can set the UnitlessZeroResolves::Number flag and it should retain this new behaviour. ReduceLengths has now been extended so that when it visits a declaration it will set a boolean based on this value, meaning traversing into the declaration, it can be aware as to whether or not it should coerce these values. This allows us to continue to reduce `0px` to `0` when they are semantically equivalent, while also ensuring we're only doing so when they actually are. This fixes #820.
github-actions bot
pushed a commit
that referenced
this pull request
Jan 22, 2026
## [0.0.14] - 2026-01-22 ### Other Changes - Coverage: Add `:unknown` coverage testing to all popular CSS libraries (#796) ([#796](#796)) ### Chromashift - chromashift: Fix lossy alpha conversions (#784) ([#784](#784)) ### Css_ast - Regenerate css_ast/src/values from csswg drafts (#789) ([#789](#789)) - css_ast: Fixup MediaQueryList & ContainerConditionList to use CommaSeparated (#795) ([#795](#795)) - css_ast: Add support for parsing `@import` rules (#797) ([#797](#797)) - css_ast: enables `<display>` (#799) ([#799](#799)) - css_ast/csskit_proc_macro: Provide system for easily renaming auto-generated types (#800) ([#800](#800)) - Regenerate css_ast/src/values from csswg drafts (#801) ([#801](#801)) - Regenerate css_ast/src/values from csswg drafts (#808) ([#808](#808)) - csskit_transform: Reduce more color types (#818) ([#818](#818)) - csskit_transform: Add ReduceTimeUnits transform (#819) ([#819](#819)) - css_ast/css_transform: Only reduce lengths to unitless zero when applicable (#821) ([#821](#821)) - csskit_spec_generator/css_ast: Generate many more values (#823) ([#823](#823)) ### Css_lexer - css_lexer/css_parse: Add SourceCursor compacting, ensure CursorCompactWriteSink compacts cursors before write (#782) ([#782](#782)) ### Css_parse - csskit/csskit_transform/css_parse: Improve transform architecture. Minify lengths (#815) ([#815](#815)) ### Csskit - chore(deps): update dependencies (patch) (#790) ([#790](#790)) ### Csskit_ast - csskit_ast: Add benchmarks for linting with example cks files (#788) ([#788](#788)) ### Csskit_transform - csskit_transform: Add Reduce colors (#816) ([#816](#816)) ### Csskit_vscode - chore(deps): update dependency oxlint to v1.36.0 (#791) ([#791](#791)) - chore(deps): update dependency @types/vscode to v1.108.1 (#803) ([#803](#803)) - chore(deps): update dependency oxlint to v1.38.0 (#805) ([#805](#805)) - chore(deps): update dependencies (patch) (#802) ([#802](#802)) - fix(deps): update dependencies (patch) (#809) ([#809](#809)) - chore(deps): update dependency oxlint to v1.39.0 (#811) ([#811](#811)) - chore(deps): update dependency prettier to v3.8.0 (#813) ([#813](#813)) ### Csskit_wasm - website: fix pages deploy (#807) ([#807](#807)) - csskit_wasm: Use minifier transform architecture (#817) ([#817](#817)) [forcebuild]
Merged
github-actions bot
pushed a commit
that referenced
this pull request
Jan 22, 2026
## [0.0.14] - 2026-01-22 ### Other Changes - Coverage: Add `:unknown` coverage testing to all popular CSS libraries (#796) ([#796](#796)) ### Chromashift - chromashift: Fix lossy alpha conversions (#784) ([#784](#784)) ### Css_ast - Regenerate css_ast/src/values from csswg drafts (#789) ([#789](#789)) - css_ast: Fixup MediaQueryList & ContainerConditionList to use CommaSeparated (#795) ([#795](#795)) - css_ast: Add support for parsing `@import` rules (#797) ([#797](#797)) - css_ast: enables `<display>` (#799) ([#799](#799)) - css_ast/csskit_proc_macro: Provide system for easily renaming auto-generated types (#800) ([#800](#800)) - Regenerate css_ast/src/values from csswg drafts (#801) ([#801](#801)) - Regenerate css_ast/src/values from csswg drafts (#808) ([#808](#808)) - csskit_transform: Reduce more color types (#818) ([#818](#818)) - csskit_transform: Add ReduceTimeUnits transform (#819) ([#819](#819)) - css_ast/css_transform: Only reduce lengths to unitless zero when applicable (#821) ([#821](#821)) - csskit_spec_generator/css_ast: Generate many more values (#823) ([#823](#823)) ### Css_lexer - css_lexer/css_parse: Add SourceCursor compacting, ensure CursorCompactWriteSink compacts cursors before write (#782) ([#782](#782)) ### Css_parse - csskit/csskit_transform/css_parse: Improve transform architecture. Minify lengths (#815) ([#815](#815)) ### Csskit - chore(deps): update dependencies (patch) (#790) ([#790](#790)) ### Csskit_ast - csskit_ast: Add benchmarks for linting with example cks files (#788) ([#788](#788)) ### Csskit_transform - csskit_transform: Add Reduce colors (#816) ([#816](#816)) ### Csskit_vscode - chore(deps): update dependency oxlint to v1.36.0 (#791) ([#791](#791)) - chore(deps): update dependency @types/vscode to v1.108.1 (#803) ([#803](#803)) - chore(deps): update dependency oxlint to v1.38.0 (#805) ([#805](#805)) - chore(deps): update dependencies (patch) (#802) ([#802](#802)) - fix(deps): update dependencies (patch) (#809) ([#809](#809)) - chore(deps): update dependency oxlint to v1.39.0 (#811) ([#811](#811)) - chore(deps): update dependency prettier to v3.8.0 (#813) ([#813](#813)) ### Csskit_wasm - website: fix pages deploy (#807) ([#807](#807)) - csskit_wasm: Use minifier transform architecture (#817) ([#817](#817))
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This closes #774. By introducing a new OverlaySegment system in
css_parse, we can insert new snippets of css before, after or replacing chunks
of css. This allows us to then use this in the transformer trait to write
reasonably ergonomic transformers which can stack.
This also closes #777 by introducing the ReduceLengths transformer which is the
first to use this kind of logic.