Skip to content

Commit 20d85b4

Browse files
committed
feat: add lightningcss-plugin-pxtorem
1 parent 89de9e3 commit 20d85b4

File tree

6 files changed

+217
-0
lines changed

6 files changed

+217
-0
lines changed

packages/pxtorem/README.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# ⚡ lightningcss-plugin-pxtorem
2+
3+
The `lightningcss-plugin-pxtorem` plugin is designed to convert pixel units to rem units in your CSS, making it easier to maintain responsive and scalable designs.
4+
5+
> [!NOTE]
6+
> WIP - This plugin is still a work in progress.
7+
8+
## ✨ Features
9+
10+
- ✅ Converts pixel units to rem units.
11+
- ✅ Helps maintain responsive and scalable designs.
12+
- ✅ Customizable options for root value, precision, properties, and more.
13+
14+
## ⬇️ Installation
15+
16+
You can install the `lightningcss-plugin-pxtorem` plugin using npm or yarn:
17+
18+
```sh
19+
npm install lightningcss-plugin-pxtorem
20+
```
21+
22+
or
23+
24+
```sh
25+
pnpm add lightningcss-plugin-pxtorem
26+
```
27+
28+
## 🚀 Usage
29+
30+
To use the `lightningcss-plugin-pxtorem` you need to include it in your `vite.config.js` file:
31+
32+
```js
33+
import { defineConfig } from "vite";
34+
import { composeVisitors } from "lightningcss";
35+
import pxtorem from "lightningcss-plugin-pxtorem";
36+
37+
export default defineConfig({
38+
css: {
39+
transformer: "lightningcss",
40+
lightningcss: {
41+
visitor: composeVisitors([pxtorem()]),
42+
},
43+
},
44+
});
45+
```
46+
47+
This plugin also is compatible with others tools that use Vite.
48+
49+
## 🤝 Contributing
50+
51+
If you wish to contribute to this project, you can do so by reading the [contribution guide](../../CONTRIBUTING.md).
52+
53+
## 🙌 Credits
54+
55+
This plugin was highly inspired by [postcss-pxtorem](https://github.com/cuth/postcss-pxtorem).
56+
57+
## 📄 License
58+
59+
This project is licensed under the MIT License. See the [license file](../../LICENSE) for more details.

packages/pxtorem/package.json

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{
2+
"name": "lightningcss-plugin-pxtorem",
3+
"version": "0.0.1",
4+
"description": "Convert px to rem in css files with LightningCSS.",
5+
"keywords": [
6+
"lightningcss",
7+
"lightningcss-plugin",
8+
"css",
9+
"plugin",
10+
"pxtorem",
11+
"px",
12+
"rem"
13+
],
14+
"homepage": "https://github.com/felixicaza/lightningcss-plugins/packages/pxtorem#readme",
15+
"bugs": {
16+
"url": "https://github.com/felixicaza/lightningcss-plugins/issues"
17+
},
18+
"repository": {
19+
"type": "git",
20+
"url": "git+https://github.com/felixicaza/lightningcss-plugins.git"
21+
},
22+
"license": "MIT",
23+
"author": "Felix Icaza <fx.joliett17@gmail.com>",
24+
"sideEffects": false,
25+
"type": "module",
26+
"exports": {
27+
".": "./dist/index.js"
28+
},
29+
"main": "./dist/index.js",
30+
"module": "./dist/index.js",
31+
"types": "./dist/index.d.ts",
32+
"files": [
33+
"dist"
34+
],
35+
"scripts": {
36+
"build": "tsup",
37+
"dev": "tsup --watch",
38+
"prepublishOnly": "pnpm build",
39+
"start": "tsx src/index.ts"
40+
},
41+
"packageManager": "pnpm@10.5.2"
42+
}

packages/pxtorem/src/index.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { type LengthValue, type LengthUnit } from 'lightningcss'
2+
3+
export default () => {
4+
return {
5+
Length({ unit, value }: LengthValue): { unit: LengthUnit, value: number } | undefined {
6+
if (unit === 'px') {
7+
return { unit: 'rem', value: value / 16 }
8+
}
9+
}
10+
}
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2+
3+
exports[`pxtorem plugin > should convert px to rem 1`] = `"div{margin:1rem}"`;
4+
5+
exports[`pxtorem plugin > should convert px to rem in custom properties 1`] = `":root{--margin:1rem}div{margin:var(--margin)}"`;
6+
7+
exports[`pxtorem plugin > should convert px to rem in keyframes 1`] = `"@keyframes fadeIn{0%{margin:1rem}to{margin:2rem}}"`;
8+
9+
exports[`pxtorem plugin > should convert px to rem in media queries 1`] = `"@media (width>=48rem){div{margin:1rem}}"`;
10+
11+
exports[`pxtorem plugin > should not convert other units 1`] = `"div{margin:1em}"`;

packages/pxtorem/test/index.test.ts

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { composeVisitors, transform } from 'lightningcss'
3+
import pxtorem from '../dist/index'
4+
5+
describe('pxtorem plugin', () => {
6+
it('should convert px to rem', () => {
7+
const css = 'div { margin: 16px; }'
8+
9+
const output = transform({
10+
filename: 'input.css',
11+
code: Buffer.from(css),
12+
minify: true,
13+
sourceMap: false,
14+
visitor: composeVisitors([pxtorem()])
15+
}).code.toString()
16+
17+
expect(output).toMatchSnapshot()
18+
})
19+
20+
it('should not convert other units', () => {
21+
const css = 'div { margin: 1em; }'
22+
23+
const output = transform({
24+
filename: 'input.css',
25+
code: Buffer.from(css),
26+
minify: true,
27+
sourceMap: false,
28+
drafts: {
29+
customMedia: true
30+
},
31+
nonStandard: {
32+
deepSelectorCombinator: true
33+
},
34+
errorRecovery: true,
35+
visitor: composeVisitors([pxtorem()])
36+
}).code.toString()
37+
38+
expect(output).toMatchSnapshot()
39+
})
40+
41+
it('should convert px to rem in media queries', () => {
42+
const css = '@media (min-width: 768px) { div { margin: 16px; } }'
43+
44+
const output = transform({
45+
filename: 'input.css',
46+
code: Buffer.from(css),
47+
minify: true,
48+
sourceMap: false,
49+
visitor: composeVisitors([pxtorem()])
50+
}).code.toString()
51+
52+
expect(output).toMatchSnapshot()
53+
})
54+
55+
it('should convert px to rem in keyframes', () => {
56+
const css = '@keyframes fadeIn { from { margin: 16px; } to { margin: 32px; } }'
57+
58+
const output = transform({
59+
filename: 'input.css',
60+
code: Buffer.from(css),
61+
minify: true,
62+
sourceMap: false,
63+
visitor: composeVisitors([pxtorem()])
64+
}).code.toString()
65+
66+
expect(output).toMatchSnapshot()
67+
})
68+
69+
it('should convert px to rem in custom properties', () => {
70+
const css = ':root { --margin: 16px; } div { margin: var(--margin); }'
71+
72+
const output = transform({
73+
filename: 'input.css',
74+
code: Buffer.from(css),
75+
minify: true,
76+
sourceMap: false,
77+
visitor: composeVisitors([pxtorem()])
78+
}).code.toString()
79+
80+
expect(output).toMatchSnapshot()
81+
})
82+
})

packages/pxtorem/tsup.config.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { defineConfig } from 'tsup'
2+
3+
export default defineConfig([
4+
{
5+
entry: ['src/index.ts'],
6+
format: ['esm'],
7+
dts: true,
8+
clean: true,
9+
target: 'esnext'
10+
}
11+
12+
])

0 commit comments

Comments
 (0)