Browse Source

/* px-to-viewport-ignore */ & /* px-to-viewport-ignore-next */

master
Dmitry Karpunin 5 years ago
parent
commit
9d6c5cee5e
  1. 1
      .npmignore
  2. 21
      CHANGELOG.md
  3. 2
      LICENSE
  4. 94
      README.md
  5. 88
      README_CN.md
  6. 28
      example/main-viewport.css
  7. 29
      example/main.css
  8. 82
      index.js
  9. 31
      spec/px-to-viewport.spec.js

1
.npmignore

@ -3,3 +3,4 @@
npm-debug.log*
node_modules
spec
package-lock.json

21
CHANGELOG.md

@ -4,10 +4,29 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased 1.2.0] - 2020-xx-xx
You can install edge-version over
`npm i -D evrone/postcss-px-to-viewport` or `yarn add -D evrone/postcss-px-to-viewport`.
### Added
- [#50](https://github.com/evrone/postcss-px-to-viewport/pull/50) by [@IceApriler](https://github.com/IceApriler):
`include` (Regexp or Array of Regexp) If `include` is set, only matching files will be converted,
for example, only files under `src/mobile/` (`include: /\/src\/mobile\//`)
> `exclude` and `include` can be set together, and the intersection of the two rules will be taken.
- Added `/* px-to-viewport-ignore */` and `/* px-to-viewport-ignore-next */` — special comments
for ignore conversion of single lines, inspired by
[#27](https://github.com/evrone/postcss-px-to-viewport/pull/27) from [@lcat](https://github.com/lcat)
[Read more about ignoring](https://github.com/evrone/postcss-px-to-viewport#ignoring).
### Changed
- Changed testing lib to [Jest](https://github.com/facebook/jest)
from [jasmine-node](https://github.com/mhevery/jasmine-node).
- `package-lock.json` included to git-repo.
## [1.1.1] - 2019-07-08
### Fixed
- Fixed `rule.source === undefined` from `postcss-modules-values`.
## [1.1.0] - 2019-02-05

2
LICENSE

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2016-2019 Dmitry Karpunin <koderfunk@gmail.com>
Copyright (c) 2016-2020 Dmitry Karpunin <koderfunk@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

94
README.md

@ -5,11 +5,6 @@ English | [中文](README_CN.md)
A plugin for [PostCSS](https://github.com/postcss/postcss) that generates viewport units (vw, vh, vmin, vmax) from pixel units.
<a href="https://evrone.com/?utm_source=postcss-px-to-viewport">
<img src="https://user-images.githubusercontent.com/417688/34437029-dbfe4ee6-ecab-11e7-9d80-2b274b4149b3.png"
alt="Sponsored by Evrone" width="231">
</a>
## Demo
If your project involves a fixed width, this script will help to convert pixels into viewport units.
@ -27,6 +22,10 @@ If your project involves a fixed width, this script will help to convert pixels
}
.class2 {
padding-top: 10px; /* px-to-viewport-ignore */
/* px-to-viewport-ignore-next */
padding-bottom: 10px;
/* Any other comment */
border: 1px solid black;
margin-bottom: 1px;
font-size: 20px;
@ -53,6 +52,9 @@ If your project involves a fixed width, this script will help to convert pixels
}
.class2 {
padding-top: 10px;
padding-bottom: 10px;
/* Any other comment */
border: 1px solid black;
margin-bottom: 1px;
font-size: 6.25vw;
@ -120,17 +122,61 @@ Default Options:
- `minPixelValue` (Number) Set the minimum pixel value to replace.
- `mediaQuery` (Boolean) Allow px to be converted in media queries.
- `replace` (Boolean) replaces rules containing vw instead of adding fallbacks.
- `exclude` (Array or Regexp) Ignore some files like 'node_modules'
- `exclude` (Regexp or Array of Regexp) Ignore some files like 'node_modules'
- If value is regexp, will ignore the matches files.
- If value is array, the elements of the array are regexp.
- `include` (Array or Regexp) If `include` is set, only matching files will be converted, for example, only files under 'src/mobile'
- `include` (Regexp or Array of Regexp) If `include` is set, only matching files will be converted,
for example, only files under `src/mobile/` (`include: /\/src\/mobile\//`)
- If the value is regexp, the matching file will be included, otherwise it will be excluded.
- If value is array, the elements of the array are regexp.
- `landscape` (Boolean) Adds `@media (orientation: landscape)` with values converted via `landscapeWidth`.
- `landscapeUnit` (String) Expected unit for `landscape` option
- `landscapeWidth` (Number) Viewport width for landscape orientation.
> `exclude` and` include` can be set together, and the intersection of the two rules will be taken.
> `exclude` and `include` can be set together, and the intersection of the two rules will be taken.
#### Ignoring
You can use special comments for ignore conversion of single lines:
- `/* px-to-viewport-ignore-next */` — on a separate line, prevents conversion on the next line.
- `/* px-to-viewport-ignore */` — after the property on the right, prevents conversion on the same line.
Example:
```css
/* example input: */
.class {
/* px-to-viewport-ignore-next */
width: 10px;
padding: 10px;
height: 10px; /* px-to-viewport-ignore */
border: solid 2px #000; /* px-to-viewport-ignore */
}
/* example output: */
.class {
width: 10px;
padding: 3.125vw;
height: 10px;
border: solid 2px #000;
}
```
There are several more reasons why your pixels may not convert, the following options may affect this:
`propList`, `selectorBlackList`, `minPixelValue`, `mediaQuery`, `exclude`, `include`.
#### Use with PostCss configuration file
add to your `postcss.config.js`
```js
module.exports = {
plugins: {
// ...
'postcss-px-to-viewport': {
// options
}
}
}
```
#### Use with gulp-postcss
@ -155,19 +201,10 @@ gulp.task('css', function () {
});
```
#### Use with PostCss configuration file
## Contributing
add to your `postcss.config.js`
```js
module.exports = {
plugins: {
// ...
'postcss-px-to-viewport': {
// options
}
}
}
```
Please read [Code of Conduct](CODE-OF-CONDUCT.md)
and [Contributing Guidelines](CONTRIBUTING.md) for submitting pull requests to us.
## Running the tests
@ -180,18 +217,14 @@ Then run the tests via npm script:
$ npm run test
```
## Contributing
## Changelog
Please read [Code of Conduct](CODE-OF-CONDUCT.md) and [Contributing Guidelines](CONTRIBUTING.md) for submitting pull requests to us.
The changelog is [here](CHANGELOG.md).
## Versioning
We use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/evrone/postcss-px-to-viewport/tags).
## Changelog
The changelog is [here](CHANGELOG.md).
## Authors
* [Dmitry Karpunin](https://github.com/KODerFunk) - *Initial work*
@ -203,6 +236,15 @@ See also the list of [contributors](https://github.com/evrone/postcss-px-to-view
This project is licensed under the [MIT License](LICENSE).
## Sponsors
Visit [Evrone](https://evrone.com/) website to get more information about the [projects](https://evrone.com/cases) build.
<a href="https://evrone.com/?utm_source=postcss-px-to-viewport">
<img src="https://user-images.githubusercontent.com/417688/34437029-dbfe4ee6-ecab-11e7-9d80-2b274b4149b3.png"
alt="Sponsored by Evrone" width="231" />
</a>
## Acknowledgments
* Hat tip to https://github.com/cuth/postcss-pxtorem/ for inspiring us for this project.

88
README_CN.md

@ -5,11 +5,6 @@
将px单位转换为视口单位的 (vw, vh, vmin, vmax) 的 [PostCSS](https://github.com/postcss/postcss) 插件.
<a href="https://evrone.com/?utm_source=postcss-px-to-viewport">
<img src="https://user-images.githubusercontent.com/417688/34437029-dbfe4ee6-ecab-11e7-9d80-2b274b4149b3.png"
alt="Sponsored by Evrone" width="231">
</a>
## 简介
如果你的样式需要做根据视口大小来调整宽度,这个脚本可以将你CSS中的px单位转化为vw,1vw等于1/100视口宽度。
@ -27,6 +22,10 @@
}
.class2 {
padding-top: 10px; /* px-to-viewport-ignore */
/* px-to-viewport-ignore-next */
padding-bottom: 10px;
/* Any other comment */
border: 1px solid black;
margin-bottom: 1px;
font-size: 20px;
@ -53,6 +52,9 @@
}
.class2 {
padding-top: 10px;
padding-bottom: 10px;
/* Any other comment */
border: 1px solid black;
margin-bottom: 1px;
font-size: 6.25vw;
@ -124,6 +126,7 @@ $ yarn add -D postcss-px-to-viewport
- 如果值是一个正则表达式,那么匹配这个正则的文件会被忽略
- 如果传入的值是一个数组,那么数组里的值必须为正则
- `include` (Array or Regexp) 如果设置了`include`,那将只有匹配到的文件才会被转换,例如只转换 'src/mobile' 下的文件
(`include: /\/src\/mobile\//`)
- 如果值是一个正则表达式,将包含匹配的文件,否则将排除该文件
- 如果传入的值是一个数组,那么数组里的值必须为正则
- `landscape` (Boolean) 是否添加根据 `landscapeWidth` 生成的媒体查询条件 `@media (orientation: landscape)`
@ -132,6 +135,49 @@ $ yarn add -D postcss-px-to-viewport
> `exclude`和`include`是可以一起设置的,将取两者规则的交集。
#### Ignoring (需要翻译帮助。)
You can use special comments for ignore conversion of single lines:
- `/* px-to-viewport-ignore-next */` — on a separate line, prevents conversion on the next line.
- `/* px-to-viewport-ignore */` — after the property on the right, prevents conversion on the same line.
Example:
```css
/* example input: */
.class {
/* px-to-viewport-ignore-next */
width: 10px;
padding: 10px;
height: 10px; /* px-to-viewport-ignore */
border: solid 2px #000; /* px-to-viewport-ignore */
}
/* example output: */
.class {
width: 10px;
padding: 3.125vw;
height: 10px;
border: solid 2px #000;
}
```
There are several more reasons why your pixels may not convert, the following options may affect this:
`propList`, `selectorBlackList`, `minPixelValue`, `mediaQuery`, `exclude`, `include`.
#### 使用PostCss配置文件时
在`postcss.config.js`添加如下配置
```js
module.exports = {
plugins: {
// ...
'postcss-px-to-viewport': {
// options
}
}
}
```
#### 直接在gulp中使用,添加gulp-postcss
`gulpfile.js` 添加如下配置:
@ -155,19 +201,10 @@ gulp.task('css', function () {
});
```
#### 使用PostCss配置文件时
## 参与贡献
在`postcss.config.js`添加如下配置
```js
module.exports = {
plugins: {
// ...
'postcss-px-to-viewport': {
// options
}
}
}
```
在提PR之前,请先阅读 [代码指南](CODE-OF-CONDUCT.md)
和 [贡献指南](CONTRIBUTING.md)
## 测试
@ -180,18 +217,14 @@ $ npm install
$ npm run test
```
## 参与贡献
## Changelog
在提PR之前,请先阅读 [代码指南](CODE-OF-CONDUCT.md) 和 [贡献指南](CONTRIBUTING.md)
变更日志在 [](CHANGELOG.md).
## 版本跟踪
使用 [SemVer](http://semver.org/) 做版本跟踪, 可用版本可在[这](https://github.com/evrone/postcss-px-to-viewport/tags)看到
## Changelog
变更日志在 [](CHANGELOG.md).
## 作者
* [Dmitry Karpunin](https://github.com/KODerFunk) - *Initial work*
@ -203,6 +236,15 @@ $ npm run test
本项目使用 [MIT License](LICENSE).
## 赞助商
访问 [Evrone](https://evrone.com/)网站以获取有关[项目构建](https://evrone.com/cases)的更多信息。
<a href="https://evrone.com/?utm_source=postcss-px-to-viewport">
<img src="https://user-images.githubusercontent.com/417688/34437029-dbfe4ee6-ecab-11e7-9d80-2b274b4149b3.png"
alt="Sponsored by Evrone" width="231" />
</a>
## 借鉴自
* 受 https://github.com/cuth/postcss-pxtorem/ 启发有了这个项目

28
example/main-viewport.css

@ -19,6 +19,34 @@
}
}
.class4-ignore::before {
content: '';
width: 10px;
padding: 3.125vw;
height: 10px;
border: solid 2px #000;
}
.class5-bad-ignore {
/* px-to-viewport-ignore */
width: 3.125vw;
/* px-to-viewport-ignore */
height: 3.125vw;
/* px-to-viewport-ignore-next */
}
@keyframes move {
0% {
transform: translate(0, 0);
}
/* px-to-viewport-ignore-next */
50% {
transform: translate(10px, -10px);
}
100% {
transform: translate(10px, -10px); /* px-to-viewport-ignore */
}
}
/*
.class {
font-size: 16px;

29
example/main.css

@ -19,6 +19,35 @@
}
}
.class4-ignore::before {
content: '';
/* px-to-viewport-ignore-next */
width: 10px;
padding: 10px;
height: 10px; /* px-to-viewport-ignore */
border: solid 2px #000; /* px-to-viewport-ignore */
}
.class5-bad-ignore {
/* px-to-viewport-ignore */
width: 10px;
/* px-to-viewport-ignore */
height: 10px;
/* px-to-viewport-ignore-next */
}
@keyframes move {
0% {
transform: translate(0, 0);
}
/* px-to-viewport-ignore-next */
50% {
transform: translate(10px, -10px);
}
100% {
transform: translate(10px, -10px); /* px-to-viewport-ignore */
}
}
/*
.class {
font-size: 16px;

82
index.js

@ -22,42 +22,46 @@ var defaults = {
landscapeWidth: 568
};
module.exports = postcss.plugin('postcss-px-to-viewport', function (options) {
var ignoreNextComment = 'px-to-viewport-ignore-next';
var ignorePrevComment = 'px-to-viewport-ignore';
module.exports = postcss.plugin('postcss-px-to-viewport', function (options) {
var opts = objectAssign({}, defaults, options);
checkRegExpOrArray(opts, 'exclude');
checkRegExpOrArray(opts, 'include');
var pxRegex = getUnitRegexp(opts.unitToConvert);
var satisfyPropList = createPropListMatcher(opts.propList);
var landscapeRules = [];
return function (css) {
return function (css, result) {
css.walkRules(function (rule) {
// Add exclude option to ignore some files like 'node_modules'
var file = rule.source && rule.source.input.file;
if (opts.include && file) {
if (Object.prototype.toString.call(opts.include) === '[object RegExp]') {
if (!isInclude(opts.include, file)) return;
if (!opts.include.test(file)) return;
} else if (Object.prototype.toString.call(opts.include) === '[object Array]') {
var flag = false;
for (let i = 0; i < opts.include.length; i++) {
if (isInclude(opts.include[i], file)) flag = true;
for (var i = 0; i < opts.include.length; i++) {
if (opts.include[i].test(file)) {
flag = true;
break;
}
}
if (!flag) return;
} else {
throw new Error('options.include should be RegExp or Array.');
}
}
if (opts.exclude && file) {
if (Object.prototype.toString.call(opts.exclude) === '[object RegExp]') {
if (isExclude(opts.exclude, file)) return;
if (opts.exclude.test(file)) return;
} else if (Object.prototype.toString.call(opts.exclude) === '[object Array]') {
for (let i = 0; i < opts.exclude.length; i++) {
if (isExclude(opts.exclude[i], file)) return;
for (var i = 0; i < opts.exclude.length; i++) {
if (opts.exclude[i].test(file)) return;
}
} else {
throw new Error('options.exclude should be RegExp or Array.');
}
}
@ -86,6 +90,25 @@ module.exports = postcss.plugin('postcss-px-to-viewport', function (options) {
if (decl.value.indexOf(opts.unitToConvert) === -1) return;
if (!satisfyPropList(decl.prop)) return;
var prev = decl.prev();
// prev declaration is ignore conversion comment at same line
if (prev && prev.type === 'comment' && prev.text === ignoreNextComment) {
// remove comment
prev.remove();
return;
}
var next = decl.next();
// next declaration is ignore conversion comment at same line
if (next && next.type === 'comment' && next.text === ignorePrevComment) {
if (/\n/.test(next.raws.before)) {
result.warn('Unexpected comment /* ' + ignorePrevComment + ' */ must be after declaration at same line.', { node: next });
} else {
// remove comment
next.remove();
return;
}
}
var unit;
var size;
var params = rule.parent.params;
@ -135,6 +158,27 @@ function createPxReplace(opts, viewportUnit, viewportSize) {
};
}
function error(decl, message) {
throw decl.error(message, { plugin: 'postcss-px-to-viewport' });
}
function checkRegExpOrArray(options, optionName) {
var option = options[optionName];
if (!option) return;
if (Object.prototype.toString.call(option) === '[object RegExp]') return;
if (Object.prototype.toString.call(option) === '[object Array]') {
var bad = false;
for (var i = 0; i < option.length; i++) {
if (Object.prototype.toString.call(option[i]) !== '[object RegExp]') {
bad = true;
break;
}
}
if (!bad) return;
}
throw new Error('options.' + optionName + ' should be RegExp or Array of RegExp.');
}
function toFixed(number, precision) {
var multiplier = Math.pow(10, precision + 1),
wholeNumber = Math.floor(number * multiplier);
@ -149,20 +193,6 @@ function blacklistedSelector(blacklist, selector) {
});
}
function isExclude(reg, file) {
if (Object.prototype.toString.call(reg) !== '[object RegExp]') {
throw new Error('options.exclude should be RegExp.');
}
return file.match(reg) !== null;
}
function isInclude(reg, file) {
if (Object.prototype.toString.call(reg) !== '[object RegExp]') {
throw new Error('options.include should be RegExp.');
}
return file.match(reg) !== null;
}
function declarationExists(decls, prop, value) {
return decls.some(function (decl) {
return (decl.prop === prop && decl.value === value);

31
spec/px-to-viewport.spec.js

@ -605,5 +605,34 @@ describe('landscape', function() {
var expected = '.rule { font-size: 15vw }';
expect(processed).toBe(expected);
})
});
});
describe('/* px-to-viewport-ignore */ & /* px-to-viewport-ignore-next */', function() {
it('should ignore right-commented', function() {
var css = '.rule { font-size: 15px; /* simple comment */ width: 100px; /* px-to-viewport-ignore */ height: 50px; }';
var expected = '.rule { font-size: 4.6875vw; /* simple comment */ width: 100px; height: 15.625vw; }';
var processed = postcss(pxToViewport()).process(css).css;
expect(processed).toBe(expected);
});
it('should ignore right-commented in multiline-css', function() {
var css = '.rule {\n font-size: 15px;\n width: 100px; /*px-to-viewport-ignore*/\n height: 50px;\n}';
var expected = '.rule {\n font-size: 4.6875vw;\n width: 100px;\n height: 15.625vw;\n}';
var processed = postcss(pxToViewport()).process(css).css;
expect(processed).toBe(expected);
});
it('should ignore before-commented in multiline-css', function() {
var css = '.rule {\n font-size: 15px;\n /*px-to-viewport-ignore-next*/\n width: 100px;\n /*px-to-viewport-ignore*/\n height: 50px;\n}';
var expected = '.rule {\n font-size: 4.6875vw;\n width: 100px;\n /*px-to-viewport-ignore*/\n height: 15.625vw;\n}';
var processed = postcss(pxToViewport()).process(css).css;
expect(processed).toBe(expected);
});
});
Loading…
Cancel
Save