Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
9d0a587
update doc #159
tbela99 Sep 21, 2026
6f217b9
fix nested shorthand computation
tbela99 Sep 21, 2026
cbfe064
update doc
tbela99 Sep 21, 2026
e492d60
add ts-ignore
tbela99 Sep 21, 2026
3106f45
add ts-ignore
tbela99 Sep 21, 2026
7320538
include css-tree in benchmarck
tbela99 Sep 21, 2026
1bd7256
adding speed stettings in the benchmark
tbela99 Sep 22, 2026
35f2d7e
update readme
tbela99 Sep 22, 2026
1929ac5
update readme
tbela99 Sep 22, 2026
4819a65
update readme
tbela99 Sep 22, 2026
eef7324
update readme
tbela99 Sep 22, 2026
bf4ccab
update readme
tbela99 Sep 23, 2026
4923088
update readme
tbela99 Sep 23, 2026
97a0588
update readme
tbela99 Sep 23, 2026
7bbb981
update readme
tbela99 Sep 23, 2026
38cfbd0
update readme
tbela99 Sep 24, 2026
3dd4b3d
added RenderOptions#minifyValues and ParseOptions#minifyAST
tbela99 Sep 24, 2026
28b6e8c
added RenderOptions#minifyValues and ParseOptions#minifyAST
tbela99 Sep 24, 2026
82f3695
adding architecture graph
tbela99 Sep 25, 2026
5ad438a
adding architecture graph
tbela99 Sep 25, 2026
69eac69
adding architecture graph
tbela99 Sep 25, 2026
d0bf2ad
adding architecture graph
tbela99 Sep 25, 2026
b919351
adding architecture graph
tbela99 Sep 25, 2026
3bd1070
adding architecture graph
tbela99 Sep 25, 2026
6b59b8a
adding architecture graph
tbela99 Sep 25, 2026
252cbe9
improve grid-area shorthand minification
tbela99 Sep 26, 2026
a953902
improve grid-area shorthand minification
tbela99 Sep 26, 2026
bc5a473
update utility functions doc
tbela99 Sep 26, 2026
1b2410c
update utility functions doc
tbela99 Sep 26, 2026
38dbdf3
update utility functions doc
tbela99 Sep 26, 2026
17d1acc
update utility functions doc
tbela99 Sep 26, 2026
0d413f3
fix percentage rgb relative color handling
tbela99 Sep 27, 2026
08a1f2e
Merge branch 'master' of github.com:tbela99/css-parser into v.next
tbela99 Sep 27, 2026
4294cba
improve code coverage
tbela99 Sep 27, 2026
8f77a63
improve code coverage
tbela99 Sep 27, 2026
2206b20
improve code coverage
tbela99 Sep 27, 2026
a3ac98f
improve code coverage
tbela99 Sep 27, 2026
c48f4dd
improve code coverage
tbela99 Sep 27, 2026
fa72297
fix bugs with color-mix() using hwb and a98-rgb color spaces
tbela99 Sep 28, 2026
b74aa26
fix bugs in color-mix() when using color spaces hwb and a98-rgb #158
tbela99 Sep 28, 2026
f0db225
bump version #158
tbela99 Sep 28, 2026
bb74dc5
fix jsr errors #158
tbela99 Sep 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,48 @@
# Changelog

# v1.6.5

## New

- [x] Added fine-grained minification parameters:
- [x] RenderOptions#minifyValues: minify CSS values such as numbers and dimension tokens
- [x] ParseOptions#minifyAST: minify the AST.

## Improvement

```css
.footer{
grid-row:4;
grid-column:1;
grid-column-end:2;
}
```

is now computed as

```css
.footer {
grid-area: 4/1/auto/2
}
```

## Fixes

- [x] fix a98-rgb, hwb color color space handling in color-mix()
- [x] fix percentage handling in relative rgb color

```css
.c {
color: rgb(from rgb(20% 40% 60% / 80%) r g b / calc(alpha / 2));
```
is now computed as

```css
.c {
color: #3696
}
```

# v1.6.4

## New
Expand Down
104 changes: 104 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,49 @@ A sample result:
On the [complete benchmark suite](https://tbela99.github.io/css-parser/benchmark/index.html), css-parser generated a total output size of 2,158,698 bytes, compared to 2,494,113 bytes for Lightning CSS and larger outputs for all other tested minifiers.
While some tools prioritize raw execution speed, css-parser focuses on maximizing compression while preserving stylesheet semantics, resulting in consistently smaller production bundles.

## Minification performance vs execution speed

`css-parser` is designed for maximum minification performance, but the optimal configuration depends on what matters most for your workload.

The parser provides settings that let you choose the balance between minification performance and execution speed:

- Minification performance: prioritize the quality and efficiency of the minification process, allowing the parser to perform additional work when generating the minimized output.

- Execution speed: minimize the amount of work performed during parsing and minification to achieve the fastest possible execution time.

However, the available settings allow you to shift the balance toward execution speed when minimizing runtime is more important than performing every available minification optimization.

The example below demonstrates a balanced configuration that improves execution speed by disabling advanced minification features.

```ts

import {transformSync} from "@tbela99/css-parser";

const css = `...`;

const result = transformSync({
input: css,
minify: false,
beautify: false,
removeEmpty: true,
removeComments: true,
convertColor: true,
minifyValues: true,
});

console.debug(result.code);
console.debug(result.stats);
```

Performance vs execution speed comparison


| File: tailwind.css | Speed optimization | Minification optimization |
| --------------------- | ------------------ | ------------------------- |
| Size: 2,380,419 bytes | 1,890,728 bytes | 1,633,188 bytes |
| Time | 205.91 ms | 471.89 ms |
| Size reduction | -20.6% | -31.4% |

## Playground

Try it [online](https://tbela99.github.io/css-parser/playground/)
Expand Down Expand Up @@ -196,3 +239,64 @@ Try it [online](https://tbela99.github.io/css-parser/playground/)
## Performance

- [x] Bundle file referenced by the @import statement.

# Architecture

```mermaid
flowchart TD
%% --- Transform ---
Input(["CSS input"])


%% The Grouped Container
subgraph Group10["Transform step"]

transform["transform()/transformSync()"]


%% The Grouped Container
subgraph Group1 ["Parse step"]

%% --- Parse step ---
parse["parse()/parseSync()"]
tokenize(["tokenize()"])
parseNode(["parse and validate token stream"])
visitors(["visitors"])
minify(["minify AST"])
cssModules(["generate CSS module"])
parseResult["Parse result"]
end

%% The Grouped Container
subgraph Group2 ["Render step"]

%% --- Render step ---
renderAst(["Render AST"])
sourcemap([Sourcemap generation])

end

%% --- Result step ---
transformResult["Transform result"]
end

%% --- Routing step ---
Input --> transform
transform --> parse
parse --> tokenize
tokenize --> parseNode
parseNode -- "Visitors set?" --> visitors
visitors -- "Minify AST?" --> minify
minify -- "CSS module?" --> cssModules
visitors -- "CSS module?" --> cssModules
cssModules --> parseResult
parseNode -- "CSS module?" --> cssModules
parseNode -- "Minify AST?" --> minify
parseNode --> parseResult
visitors --> parseResult
minify --> parseResult
parseResult --> renderAst
renderAst -- "Sourcemap?" --> sourcemap
renderAst --> transformResult
sourcemap --> transformResult
```
6 changes: 3 additions & 3 deletions benchmark/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
"all": "npm run sizes && npm run bench; npm run report"
},
"dependencies": {
"@tbela99/css-parser": "^1.6.3",
"@tbela99/css-parser2": "github:tbela99/css-parser#04832c9",
"@tbela99/css-parser": "^1.6.5",
"@tbela99/css-parser2": "github:tbela99/css-parser#b74aa264",
"clean-css": "^5.3.3",
"css-tree": "^3.2.1",
"cssnano": "^9.0.5",
Expand All @@ -21,4 +21,4 @@
"postcss": "^8.5.28",
"vitest": "^5.0.1"
}
}
}
2 changes: 1 addition & 1 deletion benchmark/src/generate-report.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ for (const m of minifiers) {
totalRow += `</tr>\n`;

const headerCells = minifiers
.map((m) => `<th>${m.url != null ? `<a href="${m.url}" target="_top">${m.label}</a>` : m.label}</th>`)
.map((m) => `<th>${m.url != null ? `<a href="${m.url}" target="_top"${m.title != null ? ` title="${m.title}"` : ""}>${m.label}</a>` : m.label}</th>`)
.join("\n");

const html = `<!DOCTYPE html>
Expand Down
51 changes: 29 additions & 22 deletions benchmark/src/minifiers.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import cssnano from "cssnano";
import * as csso from "csso";
import * as csstree from "css-tree";
import * as esbuild from "esbuild";
import { transform as lightningTransform } from "lightningcss";
import { transform as tbelaTransform } from "@tbela99/css-parser";
import {transformSync as tbelaDevTransform} from "@tbela99/css-parser2";
import { transform } from "lightningcss";
import { transformSync as tbelaTransform } from "@tbela99/css-parser";
import { transformSync as tbelaDevTransform } from "@tbela99/css-parser2";

function pkgVersion(name, pathToPkgJson) {
const { version, repository } = JSON.parse(
Expand All @@ -39,16 +39,14 @@ function pkgVersion(name, pathToPkgJson) {
const githubShorthand = url.match(/^github:([^/]+\/[^/]+)$/);
if (githubShorthand) {
url = `https://github.com/${githubShorthand[1]}`;
}

else {
} else {
url = url
.replace(/^git\+/, "")
.replace(/^git@github\.com:/, "https://github.com/")
.replace(/^ssh:\/\/git@github\.com\//, "https://github.com/")
.replace(/\.git$/, "");
}

if (!url.match(/[a-zA-Z]+:/)) {
url = "https://github.com/" + url;
}
Expand Down Expand Up @@ -99,15 +97,15 @@ export const minifiers = [
minify: (css) => csso.minify(css).css,
},
// infinite loop bug
// {
// id: "css-tree",
// url: versions["css-tree"].url,
// label: `css-tree - ${versions["css-tree"].version}`,
// // css-tree has no dedicated minifier API; parse+generate already
// // drops whitespace/comments, which is how the official benchmark
// // treats it too (no property-level optimization, just compact output).
// minify: (css) => csstree.generate(csstree.parse(css)),
// },
{
id: "css-tree",
url: versions["css-tree"].url,
label: `css-tree - ${versions["css-tree"].version}`,
// css-tree has no dedicated minifier API; parse+generate already
// drops whitespace/comments, which is how the official benchmark
// treats it too (no property-level optimization, just compact output).
minify: (css) => csstree.generate(csstree.parse(css)),
},
{
id: "esbuild",
url: versions.esbuild.url,
Expand All @@ -118,19 +116,28 @@ export const minifiers = [
id: "lightningcss",
url: versions.lightningcss.url,
label: `lightningcss - ${versions.lightningcss.version}`,
minify: (css) =>
lightningTransform({ filename: "style.css", code: Buffer.from(css), minify: true }).code.toString(),
minify: (css) => transform({ filename: "style.css", code: Buffer.from(css), minify: true }).code.toString(),
},
{
id: "css-parser",
url: versions["css-parser"].url,
label: `@tbela99/css-parser - ${versions["css-parser"].version}`,
minify: async (css) => (await tbelaTransform(css, { minify: true })).code,
label: `@tbela99/css-parser (speed) - ${versions["css-parser"].version}`,
title: `settings: { minify: false, beautify: false, removeEmpty: true, removeComments: true, convertColor: true }`,
minify: async (css) =>
tbelaTransform({
input: css,
minify: false,
beautify: false,
removeEmpty: true,
removeComments: true,
convertColor: true,
// minifyValues: true,
}).code,
},
{
id: "css-parser-dev",
url: versions["css-parser-dev"].url,
label: `@tbela99/css-parser-dev - ${versions["css-parser-dev"].version}`,
minify: async (css) => (await tbelaDevTransform(css, { minify: true })).code,
label: `@tbela99/css-parser-dev (default) - ${versions["css-parser-dev"].version}`,
minify: async (css) => tbelaDevTransform({ input: css }).code,
},
];
Loading
Loading