@tbela99/css-parser
Version:
CSS parser, minifier and validator for node and the browser
726 lines (548 loc) • 16.4 kB
Markdown
# Changelog
## v1.4.8
### Improvements
- [x] support display-p3-linear color space.
## v1.4.7
### Improvements
- [x] Added support for parsing wrapped function arguments as defined in the CSS Values & Units Level 5 specification for component functions.
```css
font-family: random-item(--x,{Times,serif},{Arial,sans-serif},{Courier,monospace})
```
### Fixes
- [x] Fixed a performance regression, resulting in approximately ***25%*** performance gain.
- [x] Fixed a `conic-gradient()` minification bug.
- [x] Fixed missing characters by the streaming tokenizer
- [x] `walk()` with reverse parameter enabled was reversing the node's children
- [x] merging nodes could introduce a null reference
## v1.4.6
- [x] Fix if syntax expansion regression bug #134
## v1.4.5
- [x] Temporarily disable if syntax expansion #131
## v1.4.4
### Validation changes
- [x] Added the `state` and `errors` properties to nodes to expose their validation status and any associated validation errors. #127
- [x] Nodes that fail validation are no longer discarded. Nodes are discarded only if they are invalid, unparsed, or malformed. Unknown nodes are discarded when lenient parsing is disabled.
### Color
- [x] `alpha()`: Added support for minifying the CSS Color 5 `alpha()` color function.
```ts
import {transform} from '@tbela99/css-parser';
const css = `
:root {
--mycolor: oklch(60% 0.25 315 / 0.8);
}
.s {
color:
alpha(from var(--mycolor) / calc(alpha * 0.5));
`;
const result = await transform(css, {
beautify: true,
inlineCssVariables: true,
});
console.debug(result.code);
```
result:
```css
.s {
color: #b538e366
}
```
- [x] `color-mix()`: Implemented support for the updated `color-mix()` syntax defined in https://www.w3.org/TR/css-values-5/#color-mix
```ts
import {transform} from '@tbela99/css-parser';
const css = `
.hsl { color: color-mix(firebrick, goldenrod); }
`;
const result = await transform(css, {
beautify: true,
convertColor: ColorType.OKLAB
});
console.debug(result.code);
```
result:
```css
.hsl {
color: oklab(.624172 .087878 .113592)
}
```
### Webkit gradient prefix removal
- [x] Convert -webkit-* gradient functions
- [x] -webkit-gradient() to:
- [x] linear-gradient()
- [ ] radial-gradient() - not supported ⚠️
- [x] -webkit-linear-gradient()
- [x] -webkit-repeating-linear-gradient()
- [x] -webkit-radial-gradient()
- [x] -webkit-repeating-radial-gradient()
### CSS gradient minification
- [x] Minify gradient functions
- [x] linear-gradient()
- [x] radial-gradient()
- [x] conic-gradient()
- [x] repeating-linear-gradient()
- [x] repeating-radial-gradient()
- [x] repeating-conic-gradient()
### Other changes
- [x] Minify transform-origin property
- [x] Changing oklab distance threshold to `0.00001` according to https://drafts.csswg.org/css-color-4/#comparing-color-values
### Bug fixes
- [x] Fix path resolution on Windows
- [x] Do not minify supports() arguments
CSS incorrectly parsed:
```css
body {
background-color: if(
supports(color: oklch(0.7 0.185 232)): oklch(0.7 0.185 232);
else: #00adf3;
);
&::after {
content: if(
supports(color: oklch(0.7 0.185 232)): "Your browser supports OKLCH";
else: "Your browser does not support OKLCH";
);
}
}
```
result:
```css
body {
background-color: if(supports(color:#00aefc):#00aefc;else:#00adf3);
&:after {
content: if(supports(color:#00aefc):"Your browser supports OKLCH";else:"Your browser does not support OKLCH")
}
}
```
instead of:
```css
body {
background-color: #00adf3;
@supports (color:oklch(.7 .185 232)) {
background-color: #00aefc
}
&:after {
content: "Your browser does not support OKLCH";
@supports (color:oklch(.7 .185 232)) {
content: "Your browser supports OKLCH"
}
}
}
```
- [x] Incorrectly parse selector when removePrefix and css module settings are enabled
```css
*,:before,:after {
box-sizing: border-box
}
```
is parsed and rendered as:
```css
,,*:before:after {
box-sizing: border-box
}
```
instead of:
```css
*,:before,:after {
box-sizing: border-box
}
```
### Deprecation
#### Loading as commonjs module
- [x] Deprecate commonjs entry point. It will be removed in a future release.
#### Functions
- [x] Deprecate `parseFile()`. Use `parse({file, asStream, ...options})` instead.
- [x] Deprecate `transformFile()`. Use `transform({file, asStream, ...options})` instead
#### Enums
- [x] Deprecate using `ValidationLevel` to configure parsing validation settings. Use `boolean` values instead.
- [x] Deprecate invalid `EnumToken` node types. There are no longer used.
- [x] `EnumToken.InvalidRuleNodeType`
- [x] `EnumToken.InvalidAtRuleNodeType`
- [x] `EnumToken.InvalidDeclarationNodeType`
#### Interfaces
- [x] `AstInvalidRule`
- [x] `AstInvalidDeclaration`
- [x] `AstInvalidAtRule`
## v1.4.3
### CSS Modules
- [x] Add css module scope 'shortest' to produce short scoped names
```typescript
result = await transform(css, {
beautify: true,
module: {scoped: ModuleScopeEnumOptions.Shortest
}
});
console.log(result.code);
```
output
```css
.a {
background: red;
color: #ff0
}
.b {
background: blue
}
```
### CSS if() function
- [x] support if() css function syntax https://drafts.csswg.org/css-values-5/#if-notation
- [x] convert css if() function into legacy syntax
```typescript
const css = `
button {
background: linear-gradient(
if(media(min-width: 768px): to right; else: to bottom),
if(style(--dark-mode): #333; else: #fff),
if(style(--dark-mode): #000; else: #ccc)
);
}`;
result = await transform(css, {
beautify: true,
expandIfSyntax: true
}
});
console.log(result.code);
```
output
```css
button {
background: linear-gradient(to bottom,#fff,#ccc);
@media (min-width:768px) {
background: linear-gradient(to right,#fff,#ccc);
@container style(--dark-mode) {
background: linear-gradient(to right,#333,#000)
}
}
@container style(--dark-mode) {
background: linear-gradient(to bottom,#333,#000)
}
}
```
### CSS Color Module Level 5 (Draft)
- [x] support contrast-color() https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/color_value/contrast-color
- [x] custom color space in color() https://drafts.csswg.org/css-color-5/#custom-color
- [x] relative color syntax
- [x] color syntax
### Media Queries
- [x] media queries validation
- [x] automatically generate range media query
- [x] add at-rule() and named-feature() to @support-condition syntax https://drafts.csswg.org/css-conditional-5/#changes-from-L4
- [x] support calc() in media features
```typescript
const css = `
@media (width >= calc(1024px + 50px)) {
h1 {
color: Highlight;
}
}`;
result = await transform(css, {
beautify: true,
validation: true
}
});
console.log(result.code);
```
output
```css
@media (width>=1074px) {
h1 {
color: Highlight
}
}
```
### Ast
- [x] add ast search functions
- [x] find() search the ast tree and return the first match
- [x] findAll() search the ast tree and return all matches
- [x] findLast() search the ast tree and return the last match
- [x] findByValue() search the ast tree by checking each node's value and return the first match
### Other Changes
- [x] fix parsing bugs
- [x] automatically rename standard declaration names : color-adjust => print-color-adjust
- [x] rewrite parsing and validation logic
- [x] selector
- [x] declaration
- [x] at-rules
- [x] @charset
- [x] @color-profile
- [x] @container
- [x] @counter-style
- [x] @custom-media
- [x] @document
- [x] @font-face
- [x] @font-feature-values
- [x] @font-palette-values
- [x] @import
- [x] @keyframes
- [x] @layer
- [x] @media
- [x] @namespace
- [x] @page
- [x] @position-try
- [x] @property
- [x] @scope
- [x] @starting-style
- [x] @supports
- [x] @view-transition
- [x] introduce rawToken type to capture unparseable tokens
## v1.4.2
- [x] add css-conditional-5 @support at-rule(<at-keyword-token>) function
- [x] fix bug when using remove prefix #120
## v1.4.0
### CSS Module support
- [x] scoped name generation
- [x] composes:
- [x] compose from local selector
- [x] compose from other files
- [x] compose from global selector
- [x] comma separated compose list
- [x] :local
- [x] :global
- [x] :local()
- [x] :global()
- [x] selector
- [x] dashed ident (custom properties)
- [x] css at-rule property
- [x] css at-rule value
- [x] keyframe animations
- [x] grid
- [x] naming
- [x] ignore
- [x] camelCase
- [x] camelCaseOnly
- [x] dashCase
- [x] dashCaseOnly
- [x] default mode
- [x] global
- [x] local
- [x] pure(at least one class or id)
- [x] icss
- [x] :import
- [x] :export
### Bug Fixes
- [x] fix \<integer\> syntax validation #115
## v1.3.4
- [x] make streaming optional #109
- [x] patch at-rule syntax for @font-feature-value #110
- [x] support percentage in transform() and scale() #111
- [x] allow arrays in visitor definition #112
## v1.3.3
- [x] relative color computation bug #105
- [x] allow duplicated declarations of whitelisted properties #106
## v1.3.2
- [x] add missing return type
## v1.3.1
- [x] generate documentation
- [x] parse input from readable stream
- [x] add parseFile() and transformFile()
-
## v1.3.0
- [x] numerical and dimension tokens use numbers instead of string
- [x] fix bug when inlineCssVariables is disabled and computeCalcExpression is enabled
## V1.2.0
- [x] convert color to any supported color space #94
- [x] dead code removal #93
- [x] validation syntax update #92
## v1.1.1
- [x] fix bug when css nesting is disabled #89
- [x] validation rules update #87
## v1.1.0
- [x] inline sourcemap
- [x] CSS validation using mdn-data
- [x] prefix removal now remove prefixes from all nodes. prefixed linear gradients are not supported
# v1.0.0
- [x] current color parse error when used in color functions
- [x] minification : CSS transform module level 2
- [x] translate
- [x] scale
- [x] rotate
- [x] skew
- [x] perspective
- [x] matrix
- [x] matrix3d
- [x] keyframes
- [x] remove consecutive keyframes with the same name
- [x] reduce keyframe selector 'from' to '0%'
- [x] reduce keyframe selector '100%' to 'to'
- [x] remove keyframe selector ignored declarations
- [x] merge keyframe rules and declarations
- [x] trim extra space in declaration value 'url() 15%' -> 'url()15%', '1% !important' -> '1%!important'
- [x] allow empty value for css variable declaration '--color: ;'
- [x] change generate nesting rule default to true
# v0.9.1
- [x] minification passes #66
- [x] nesting selector cannot match pseudo element #67
# v0.9.0
validation
- [x] validate invalid pseudo classes
- [x] rewrite selector validation
- [x] lenient mode that preserves
- [x] unknown at-rules
- [x] unknown declarations
- [x] unknown pseudo classes
media query level 5
- [x] at-rule custom-media
- [x] at-rule when-else custom media
- [x] at-rule charset validation
- [x] media query error handling
- [x] at-rule container
- [ ] expand at-rule custom-media
- [ ] expand at-rule when-else
selector validation
- [ ] pseudo class arguments validation
- [ ] pseudo class validation
declaration validation
- [ ] validate declaration
error validation
- [ ] when a parent is marked as invalid node, do not parse or validate descendant nodes
# v0.8.0
- [x] validate selectors using mdn data
- [x] at-rules prefix removal
- [x] at rules validation
- [x] at-rule prelude
- [x] at-rule body
- [x] keyframe validation
- [ ] :not() does not accept pseudo classes
- [ ] do not validate declarations in @supports
- [ ] declarations validation
- [x] evaluate math functions: calc(), clamp(), min(), max(), round(), mod(), rem(), sin(), cos(), tan(), asin(),
acos(), atan(), atan2(), pow(), sqrt(), hypot(), log(), exp(), abs(), sign() #49
- [x] incorrectly parse compound selector #51
# v0.7.1
- [x] fix nesting rules expansion #45
# v0.7.0
- [x] fix merging rules
- [ ] experimental CSS prefix removal
- [x] declaration name
- [ ] declaration value
- [ ] exclude -webkit-* gradients
- [x] css selector validation
- [x] pseudo element
- [x] partial pseudo class validation. does not validate parameters
- [x] attribute selector
- [x] combinator
- [x] simple selector
- [x] nested selector
- [x] strict vs permissive validation: allow unknown items such as pseudo classes
- [x] allow unknown pseudo classes
- [x] allow unknown attribute selectors
- [x] strip universal selector when possible
# v0.6.0
- [x] light-dark() color
- [x] system color
## V0.5.4
- [x] incorrectly expand css nesting rules
## v0.5.3
- [x] incorrectly expand css nesting rules
## v0.5.1
- [x] failed to flatten @import when using url() syntax
## v0.5.0
- [x] render node with parents
- [x] fix relative color from xyz
- [x] fix bug when inlineCss is true but no css variable exists
- [x] compute more shorthands
- [x] (web) fetch imported css files from external domains using cors
## v0.4.1
no code change
## v0.4.0
Parsing
- [x] allow async node visitors
- [x] adding declaration parsing helper async parseDeclarations(source: string): Promise<AstDeclarations[]>
CSS color level 4 & 5
- [x] color space: srgb, srgb-linear, display-p3, prophoto-rgb, a98-rgb, rec2020, xyz, xyz-d50
- [x] color-mix()
- [x] color()
- [x] relative color
- [x] lab()
- [x] lch()
- [x] oklab()
- [x] oklch()
## v0.3.0
### shorthands
- [x] column-rule
- [x] columns
- [x] container
- [x] flex
- [x] flex-flow
- [x] gap
### Other
- [x] renamed RenderOptions.colorConvert to RenderOptions.convertColor
- [x] support none keyword in color
- [x] css relative color syntax for rgb(), hsl() and hwb() colors https://www.w3.org/TR/css-color-5/#relative-colors
- [x] rgb
- [x] hex
- [x] hsl
- [x] hwb
- [x] calc()
- [x] calc() and inline var()
## v0.2.0
- [x] cancellable parser promise using abortSignal
- [x] node visitor (callback) :
- [x] Declaration visitor
- [x] selector visitor
- [x] at-rule visitor
- [x] support mixing units with calc()
### shorthands
- [x] transition
- [x] list-style
- [x] text-emphasis
- [x] animation
### Minification
- [x] parsing column combinator
- [x] css selector level 4 attribute modifiers
- [x] selector-4 parsing https://www.w3.org/TR/selectors-4/
## v0.1.0
- [x] sourcemap generation
- [x] reduce calc():
- [x] inline css variables
- [x] configure duplicate declarations removal
- [x] configure shorthand properties computation
## v0.0.1
### Minification
- [x] merge identical rules
- [x] merge adjacent rules
- [x] minify colors
- [x] minify numbers and Dimensions tokens
- [x] compute shorthand: see the list below
- [x] remove redundant declarations
- [x] simple shorthand properties (padding, margin, etc). must have all required properties
- [x] complex shorthand properties (background, font, etc.). may have optional properties
- [x] conditionally unwrap :is()
- [x] automatic css nesting
- [x] automatically wrap selectors using :is()
- [x] multi-level shorthand properties (
border - [border-width, border-color, border-style, etc.]) https://developer.mozilla.org/en-US/docs/Web/CSS/Shorthand_properties
- [x] avoid reparsing (declarations, selectors, at-rule)
- [x] node and browser versions
- [x] decode and replace utf-8 escape sequence
### Computed shorthands
- [x] background
- [x] border
- [x] border-bottom
- [x] border-color
- [x] border-left
- [x] border-radius
- [x] border-right
- [x] border-style
- [x] border-top
- [x] border-width
- [x] font
- [x] inset
- [x] margin
- [x] outline
- [x] overflow
- [x] padding
- [x] text-decoration
### Performance
- [x] flatten @import
### Error handling
- [x] parse bad comments / cdo comments
- [x] parse bad string 1
- [x] parse bad string 2
- [x] parse empty declaration
- [x] parse unclosed rule
- [x] parse unclosed at-rule
- [x] parse bad import
# Testing
- [x] node tests
- [x] browser tests
# Code Coverage
- [x] node
- [x] browser