Skip to content

Commit

Permalink
feat: ✨ add convertUnitOnEnd feature
Browse files Browse the repository at this point in the history
  • Loading branch information
hemengke1997 committed Nov 28, 2022
1 parent f4206d8 commit 3e1dd34
Show file tree
Hide file tree
Showing 9 changed files with 160 additions and 50 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
# [1.0.0](https://github.com/hemengke1997/postcss-pxtorem/compare/v0.0.12...v1.0.0) (2022-11-17)


### Bug Fixes

* integrate postcss-nested ([07423e0](https://github.com/hemengke1997/postcss-pxtorem/commit/07423e09333b002cc91cf41c7f48adcccb80043e))
* strict regexp rule ([7d34697](https://github.com/hemengke1997/postcss-pxtorem/commit/7d34697aa3996ef94537218ad7629fbb7ced019c))



## [0.0.12](https://github.com/hemengke1997/postcss-pxtorem/compare/v0.0.11...v0.0.12) (2022-11-09)


Expand Down
68 changes: 43 additions & 25 deletions README-zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

**中文** | [English](./README.md)

[PostCSS](https://github.com/ai/postcss)插件,可以从像素单位生成rem单位

[PostCSS](https://github.com/ai/postcss)插件,可以从像素单位生成 rem 单位

## 新功能

Expand All @@ -18,8 +17,7 @@ pnpm install postcss @minko-fe/postcss-pxtorem -D

## 用法

> 像素是最容易使用的单位。它们的唯一问题是,它们不能让浏览器改变默认的16号字体大小。postcss-pxtorem将每一个px值转换为你所选择的属性中的rem,以便让浏览器设置字体大小。
> 像素是最容易使用的单位。它们的唯一问题是,它们不能让浏览器改变默认的 16 号字体大小。postcss-pxtorem 将每一个 px 值转换为你所选择的属性中的 rem,以便让浏览器设置字体大小。
### postcss.config.js

Expand All @@ -41,19 +39,20 @@ module.exports = {

### options

| Name | Type | Default | Description
|---------|----------|---------|---------
| rootValue | `number` \| `((input: Input) => number)` | 16 | 代表根元素的字体大小或根据 [`input`](https://api.postcss.org/Input.html) 参数返回根元素的字体大小
| unitToConvert | `string` | `px` | 需要转化的单位,默认 `px`
| unitPrecision | `number` | 5 | 小数点后精度
| propList | `string[]` | `['*']` | 可以从px改变为rem的属性,参考:[propList](#propList)
| selectorBlackList | `(string \| RegExp)[]` | [] | 忽略的选择器,保留为px。参考:[selectorBlackList](#selectorBlackList)
| replace | `boolean` | true | 直接在css规则上替换值而不是添加备用
| atRules | `boolean` \| `string[]` | false | 允许`at-rules`中转换rem。参考 [At-rule](https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule)
| minPixelValue | `number` | 0 | 最小的px转化值(小于这个值的不转化)
| exclude | `string` \| `RegExp` \| `((filePath: string) => boolean)` \| `null` | null | 忽略的文件路径。参考:[exclude](#exclude)
| include | `string` \| `RegExp` \| `((filePath: string) => boolean)` \| `null` | null | 包括的文件路径,与 `exclude` 相反,优先级高于 `exclude`。规则同 `exclude`
| disable | `boolean` | false | 关闭插件
| Name | Type | Default | Description |
| ----------------- | ------------------------------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------- |
| rootValue | `number` \| `((input: Input) => number)` | 16 | 代表根元素的字体大小或根据 [`input`](https://api.postcss.org/Input.html) 参数返回根元素的字体大小 |
| unitToConvert | `string` | `px` | 需要转化的单位,默认 `px` |
| unitPrecision | `number` | 5 | 小数点后精度 |
| propList | `string[]` | `['*']` | 可以从 px 改变为 rem 的属性,参考:[propList](#propList) |
| selectorBlackList | `(string \| RegExp)[]` | [] | 忽略的选择器,保留为 px。参考:[selectorBlackList](#selectorBlackList) |
| replace | `boolean` | true | 直接在 css 规则上替换值而不是添加备用 |
| atRules | `boolean` \| `string[]` | false | 允许`at-rules`中转换 rem。参考 [At-rule](https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule) |
| minPixelValue | `number` | 0 | 最小的 px 转化值(小于这个值的不转化) |
| exclude | `string` \| `RegExp` \| `((filePath: string) => boolean)` \| `null` | null | 忽略的文件路径。参考:[exclude](#exclude) |
| include | `string` \| `RegExp` \| `((filePath: string) => boolean)` \| `null` | null | 包括的文件路径,与 `exclude` 相反,优先级高于 `exclude`。规则同 `exclude` |
| disable | `boolean` | false | 关闭插件 |
| convertUnitOnEnd | `ConvertUnit` \| `ConvertUnit[]` \| false \| null | null | 插件处理的最后阶段转换单位 |

#### propList

Expand All @@ -76,33 +75,35 @@ module.exports = {
- `'exclude'` will match `\project\postcss-pxtorem\exclude\path`
- 如果值是正则,它将检查文件路径是否与正则相匹配
- `/exclude/i` will match `\project\postcss-pxtorem\exclude\path`
- 如果值是函数,你可以使用排除函数返回true,文件将被忽略
- 回调将传递文件路径作为一个参数,它应该返回一个boolean
- 如果值是函数,你可以使用排除函数返回 true,文件将被忽略
- 回调将传递文件路径作为一个参数,它应该返回一个 boolean
- `function (file) { return file.includes('exclude') }`

## ✨ 关于新特性

### ⚙️ 在css中,动态设置插件选项
### ⚙️ 在 css 中,动态设置插件选项

#### 当前文件禁用插件

```css
/* pxtorem?disabled=true */
.rule {
font-size: 15px; // 15px
}
```

#### 设置rootValue
#### 设置 rootValue

```css
/* pxtorem?rootValue=32 */
.rule {
font-size: 30px; // 0.9375rem
}
```

🌰 以上只是简单的栗子,你可以在css文件中设置任意 `postcss-pxtorem` 支持的选项
🌰 以上只是简单的栗子,你可以在 css 文件中设置任意 `postcss-pxtorem` 支持的选项

聪明的你,或许已经看出来了,`/* pxtorem?disabled=true */` 很像浏览器url?😼
聪明的你,或许已经看出来了,`/* pxtorem?disabled=true */` 很像浏览器 url?😼
没错。关于规范,只需参考:[query-string](https://github.com/sindresorhus/query-string)

#### 例子
Expand All @@ -111,14 +112,31 @@ module.exports = {
/* pxtorem?disable=false&rootValue=32&propList[]=*&replace=false&selectorBlackList[]=/some-class/i */
```

### 在css中,忽略某一行
### 在 css 中,忽略某一行

```css
.rule {
/* pxtorem-disable-next-line */
font-size: 15px; // 15px
}
```

如果你写 `15PX`(只要不是 `px`),插件也会忽略,因为 `unitToConvert` 默认是 `px`
如果你希望使用 `PX` 忽略并且希望最后得到的单位是 `px`,你可以这样

```js
module.exports = {
plugins: [
require('@minko-fe/postcss-pxtorem')({
convertUnitOnEnd: {
sourceUnit: /[p|P][x|X]$/,
targetUnit: 'px',
},
}),
],
}
```

## ❤️ 感谢

[postcss-pxtorem](https://github.com/cuth/postcss-pxtorem)
Expand All @@ -131,4 +149,4 @@ A CSS post-processor that converts px to viewport: [postcss-pxtoviewport](https:

## 💕 支持

**如果这个仓库帮了你的忙,请不吝给个star,谢谢!😎**
**如果这个仓库帮了你的忙,请不吝给个 star,谢谢!😎**
54 changes: 36 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

A plugin for [PostCSS](https://github.com/ai/postcss) that generates rem units from pixel units.


## New Features

- specify any `postcss-pxtorem` option in css.
Expand All @@ -18,11 +17,10 @@ pnpm install postcss @minko-fe/postcss-pxtorem -D

## Usage

> Pixels are the easiest unit to use (*opinion*). The only issue with them is that they don't let browsers change the default font size of 16. This script converts every px value to a rem from the properties you choose to allow the browser to set the font size.
> Pixels are the easiest unit to use (_opinion_). The only issue with them is that they don't let browsers change the default font size of 16. This script converts every px value to a rem from the properties you choose to allow the browser to set the font size.
### postcss.config.js


#### example

```js
Expand All @@ -41,19 +39,20 @@ module.exports = {

### options

| Name | Type | Default | Description
|---------|----------|---------|---------
| rootValue | `number` \| `((input: Input) => number)` | 16 | Represents the root element font size or returns the root element font size based on the [`input`](https://api.postcss.org/Input.html) parameter
| unitToConvert | `string` | `px` | unit to convert, by default, it is px
| unitPrecision | `number` | 5 | The decimal numbers to allow the REM units to grow to.
| propList | `string[]` | `['*']` | The properties that can change from px to rem. Refer to: [propList](#propList)
| selectorBlackList | `(string \| RegExp)[]` | [] | The selectors to ignore and leave as px. Refer to: [selectorBlackList](#selectorBlackList)
| replace | `boolean` | true | Replaces rules containing rems instead of adding fallbacks.
| atRules | `boolean` \| `string[]` | false | Allow px to be converted in at-rules. Refer to [At-rule](https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule)
| minPixelValue | `number` | 0 | Set the minimum pixel value to replace.
| exclude | `string` \| `RegExp` \| `((filePath: string) => boolean) \| null` | /node_modules/i | The file path to ignore and leave as px. Refer to: [exclude](#exclude)
| include | `string` \| `RegExp` \| `((filePath: string) => boolean)` \| `null` | null | The file path to convert px to rem, in contrast to `exclude`, have higher priority than `exclude`. Same rules as `exclude`
| disable | `boolean` | false | disable plugin
| Name | Type | Default | Description |
| ----------------- | ------------------------------------------------------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| rootValue | `number` \| `((input: Input) => number)` | 16 | Represents the root element font size or returns the root element font size based on the [`input`](https://api.postcss.org/Input.html) parameter |
| unitToConvert | `string` | `px` | unit to convert, by default, it is px |
| unitPrecision | `number` | 5 | The decimal numbers to allow the REM units to grow to. |
| propList | `string[]` | `['*']` | The properties that can change from px to rem. Refer to: [propList](#propList) |
| selectorBlackList | `(string \| RegExp)[]` | [] | The selectors to ignore and leave as px. Refer to: [selectorBlackList](#selectorBlackList) |
| replace | `boolean` | true | Replaces rules containing rems instead of adding fallbacks. |
| atRules | `boolean` \| `string[]` | false | Allow px to be converted in at-rules. Refer to [At-rule](https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule) |
| minPixelValue | `number` | 0 | Set the minimum pixel value to replace. |
| exclude | `string` \| `RegExp` \| `((filePath: string) => boolean) \| null` | /node_modules/i | The file path to ignore and leave as px. Refer to: [exclude](#exclude) |
| include | `string` \| `RegExp` \| `((filePath: string) => boolean)` \| `null` | null | The file path to convert px to rem, in contrast to `exclude`, have higher priority than `exclude`. Same rules as `exclude` |
| disable | `boolean` | false | disable plugin |
| convertUnitOnEnd | `ConvertUnit` \| `ConvertUnit[]` \| false \| null | null | convert unit when plugin process end |

#### propList

Expand All @@ -71,20 +70,21 @@ module.exports = {
- `[/^body$/]` will match `body` but not `.body`

#### exclude

- If value is string, it checks to see if file path contains the string.
- `'exclude'` will match `\project\postcss-pxtorem\exclude\path`
- If value is regexp, it checks to see if file path matches the regexp.
- `/exclude/i` will match `\project\postcss-pxtorem\exclude\path`
- If value is function, you can use exclude function to return a true and the file will be ignored.
- the callback will pass the file path as a parameter, it should returns a Boolean result.
- the callback will pass the file path as a parameter, it should returns a Boolean result.
- `function (file) { return file.includes('exclude') }`


## ✨ About new features

### ⚙️ Dynamically set plugin options in css

#### disable plugin

```css
/* pxtorem?disabled=true */
.rule {
Expand All @@ -93,6 +93,7 @@ module.exports = {
```

#### set rootValue

```css
/* pxtorem?rootValue=32 */
.rule {
Expand All @@ -112,13 +113,30 @@ That's right. For the specification, just refer to: [query-string](https://githu
```

### disable the next line in css file

```css
.rule {
/* pxtorem-disable-next-line */
font-size: 15px; // 15px
}
```

If you write `15PX` (as long as it's not `px`), the plugin also ignores it, because `unitToConvert` defaults to `px`
If you want to use `PX` to ignore and want the final unit to be `px`, you can:

```js
module.exports = {
plugins: [
require('@minko-fe/postcss-pxtorem')({
convertUnitOnEnd: {
sourceUnit: /[p|P][x|X]$/,
targetUnit: 'px',
},
}),
],
}
```

## ❤️ Thanks

[postcss-pxtorem](https://github.com/cuth/postcss-pxtorem)
Expand Down
4 changes: 4 additions & 0 deletions example/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import pxtorem from '../src'
const css = fs.readFileSync('main.css', 'utf8')
const options = {
replace: true,
convertUnitOnEnd: {
sourceUnit: /[p|P][x|X]$/,
targetUnit: 'px',
},
}
const processedCss = postcss(pxtorem(options), nested).process(css).css

Expand Down
6 changes: 3 additions & 3 deletions example/main-rem.css
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
.class {
margin: -0.625rem 1.25rem;
padding: 5rem 0.03125rem;
border: 0.1875rem solid black;
border: 3px solid black;
font-size: 0.875rem;
line-height: 1.25rem;
line-height: 20px;
}
.mmm {
font-size: 32px;
Expand All @@ -24,7 +24,7 @@
.class2 {
margin: -0.625rem 1.25rem;
padding: 5rem 0.03125rem;
border: 0.1875rem solid black;
border: 3px solid black;
font-size: 0.875rem;
line-height: 1.25rem;
}
Expand Down
2 changes: 1 addition & 1 deletion example/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
padding: 5rem 0.5px;
border: 3px solid black;
font-size: 14px;
line-height: 20px;
line-height: 20PX;
}
.mmm {
/* pxtorem-disable-next-line */
Expand Down
23 changes: 21 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Input, Plugin as PostcssPlugin, Rule } from 'postcss'
import { Warning } from 'postcss'
import {
blacklistedSelector,
convertUnit,
createPropListMatcher,
createPxReplace,
declarationExists,
Expand All @@ -17,6 +17,11 @@ import {
import { getUnitRegexp } from './utils/pixel-unit-regex'
import { disableNextComment } from './utils/constant'

export interface ConvertUnit {
sourceUnit: string | RegExp
targetUnit: string
}

export type PxtoremOptions = Partial<{
rootValue: number | ((input: Input) => number)
unitToConvert: string
Expand All @@ -29,6 +34,7 @@ export type PxtoremOptions = Partial<{
include: string | RegExp | ((filePath: string) => boolean) | null
exclude: string | RegExp | ((filePath: string) => boolean) | null
disable: boolean
convertUnitOnEnd: ConvertUnit | ConvertUnit[] | false | null
}>

export const defaultOptions: Required<PxtoremOptions> = {
Expand All @@ -43,6 +49,7 @@ export const defaultOptions: Required<PxtoremOptions> = {
include: null,
exclude: null,
disable: false,
convertUnitOnEnd: null,
}

function pxtorem(options?: PxtoremOptions) {
Expand Down Expand Up @@ -111,6 +118,18 @@ function pxtorem(options?: PxtoremOptions) {
decl.cloneAfter({ value })
}
},
DeclarationExit(decl) {
const { convertUnitOnEnd } = opts
if (convertUnitOnEnd) {
if (Array.isArray(convertUnitOnEnd)) {
convertUnitOnEnd.forEach((conv) => {
decl.value = convertUnit(decl.value, conv)
})
} else {
decl.value = convertUnit(decl.value, convertUnitOnEnd)
}
}
},
AtRule(atRule) {
if (opts.disable) return
if (isRepeatRun(atRule)) return
Expand All @@ -131,7 +150,7 @@ function pxtorem(options?: PxtoremOptions) {
}
}
},
Comment(comment) {
Comment(comment, { Warning }) {
opts = {
...opts,
...getOptionsFromComment(comment, Warning),
Expand Down
11 changes: 10 additions & 1 deletion src/utils/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { AtRule, ChildNode, Comment, Container, Declaration, Rule, Warning as postcssWarning } from 'postcss'
import queryString from 'query-string'
import type { PxtoremOptions } from '..'
import type { ConvertUnit, PxtoremOptions } from '..'
import { defaultOptions } from '..'
import { maybeRegExp } from './constant'
import { filterPropList } from './filter-prop-list'
Expand Down Expand Up @@ -173,6 +173,15 @@ export function judgeIsExclude<T extends PxtoremOptions['include']>(
return false
}

export function convertUnit(value: string, convert: ConvertUnit) {
if (typeof convert.sourceUnit === 'string') {
return value.replace(new RegExp(`${convert.sourceUnit}$`), convert.targetUnit)
} else if (convert.sourceUnit instanceof RegExp) {
return value.replace(new RegExp(convert.sourceUnit), convert.targetUnit)
}
return value
}

enum EnumDataType {
number = 'Number',
string = 'String',
Expand Down
Loading

0 comments on commit 3e1dd34

Please sign in to comment.