UNPKG

@tbela99/css-parser

Version:

CSS parser, minifier and validator for node and the browser

726 lines (548 loc) 16.4 kB
# 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