Browse Source

Merge remote-tracking branch 'origin/master' into add-prop-list

# Conflicts:
#	index.js
#	spec/px-to-viewport.spec.js
pull/20/head
Ivan Bunin 7 years ago
parent
commit
4746999676
  1. 25
      README.md
  2. 27
      index.js
  3. 63
      spec/px-to-viewport.spec.js

25
README.md

@ -2,6 +2,11 @@
A plugin for [PostCSS](https://github.com/ai/postcss) that generates viewport units (vw, vh, vmin, vmax) from pixel units.
## Install
```
$ npm install postcss-px-to-viewport --save-dev
```
## Usage
If your project involves a fixed width, this script will help to convert pixels into viewport units.
@ -96,7 +101,8 @@ Default:
fontViewportUnit: 'vw', // vmin is more suitable.
selectorBlackList: [],
minPixelValue: 1,
mediaQuery: false
mediaQuery: false,
exclude: [] // ignore some files
}
```
- `unitToConvert` (String) unit to convert, by default, it is px.
@ -118,9 +124,12 @@ Default:
- `[/^body$/]` will match `body` but not `.body`
- `minPixelValue` (Number) Set the minimum pixel value to replace.
- `mediaQuery` (Boolean) Allow px to be converted in media queries.
- `exclude` (Array or 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.
### Use with gulp-postcss
add to your gulp config:
```js
var gulp = require('gulp');
var postcss = require('gulp-postcss');
@ -140,3 +149,15 @@ gulp.task('css', function () {
.pipe(gulp.dest('build/css'));
});
```
### Use with Postcss configuration file
add to postcss.config.js
```js
module.exports = {
plugins: {
...
'postcss-px-to-viewport': {
// options
}
}
}
```

27
index.js

@ -28,12 +28,26 @@ module.exports = postcss.plugin('postcss-px-to-viewport', function (options) {
// Not anything inside url()
// Any digit followed by px
// !singlequotes|!doublequotes|!url()|pixelunit
var pxRegex = new RegExp('"[^"]+"|\'[^\']+\'|url\\([^\\)]+\\)|(\\d*\\.?\\d+)' + opts.unitToConvert, 'ig')
var pxRegex = new RegExp('"[^"]+"|\'[^\']+\'|url\\([^\\)]+\\)|(\\d*\\.?\\d+)' + opts.unitToConvert, 'ig');
var satisfyPropList = createPropListMatcher(opts.propList);
return function (css) {
css.walkDecls(function (decl, i) {
// Add exlclude option to ignore some files like 'node_modules'
if (opts.exclude && decl.source.input.file) {
if (Object.prototype.toString.call(opts.exclude) === '[object RegExp]') {
if (!handleExclude(opts.exclude, decl.source.input.file)) return;
} else if (Object.prototype.toString.call(opts.exclude) === '[object Array]') {
for (let i = 0; i < opts.exclude.length; ++i) {
if (!handleExclude(opts.exclude[i], decl.source.input.file)) return;
}
} else {
throw new Error('options.exclude should be RegExp or Array!');
}
}
if (
decl.value.indexOf(opts.unitToConvert) === -1 ||
!satisfyPropList(decl.prop) ||
@ -55,6 +69,14 @@ module.exports = postcss.plugin('postcss-px-to-viewport', function (options) {
};
});
function handleExclude (reg, file) {
if (Object.prototype.toString.call(reg) !== '[object RegExp]') {
throw new Error('options.exclude should be RegExp!');
}
if (file.match(reg) !== null) return false;
return true;
}
function getUnit(prop, opts) {
return prop.indexOf('font') === -1 ? opts.viewportUnit : opts.fontViewportUnit;
}
@ -64,7 +86,8 @@ function createPxReplace(viewportSize, minPixelValue, unitPrecision, viewportUni
if (!$1) return m;
var pixels = parseFloat($1);
if (pixels <= minPixelValue) return m;
return toFixed((pixels / viewportSize * 100), unitPrecision) + viewportUnit;
var parsedVal = toFixed((pixels / viewportSize * 100), unitPrecision);
return parsedVal === 0 ? '0' : parsedVal + viewportUnit;
};
}

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

@ -37,6 +37,13 @@ describe('px-to-viewport', function() {
expect(processed).toBe(expected);
});
it('should remain unitless if 0', function () {
var expected = '.rule { font-size: 0px; font-size: 0; }';
var processed = postcss(pxToViewport()).process(expected).css;
expect(processed).toBe(expected);
});
});
describe('value parsing', function() {
@ -58,6 +65,14 @@ describe('value parsing', function() {
expect(processed).toBe(expected);
});
it('should not replace values with an uppercase P or X', function () {
var rules = '.rule { margin: 12px calc(100% - 14PX); height: calc(100% - 20px); font-size: 12Px; line-height: 16px; }';
var expected = '.rule { margin: 3.75vw calc(100% - 14PX); height: calc(100% - 6.25vw); font-size: 12Px; line-height: 5vw; }';
var processed = postcss(pxToViewport()).process(rules).css;
expect(processed).toBe(expected);
});
});
describe('unitToConvert', function() {
@ -230,6 +245,54 @@ describe('minPixelValue', function () {
});
});
describe('exclude', function () {
var rules = '.rule { border: 1px solid #000; font-size: 16px; margin: 1px 10px; }';
var covered = '.rule { border: 1px solid #000; font-size: 5vw; margin: 1px 3.125vw; }'
it('when using regex at the time, the style should not be overwritten.', function () {
var options = {
exclude: /node_modules/
}
var processed = postcss(pxToViewport(options)).process(rules, {
from: '/node_modules/main.css'
}).css;
expect(processed).toBe(rules);
});
it('when using regex at the time, the style should be overwritten.', function () {
var options = {
exclude: /node_modules/
}
var processed = postcss(pxToViewport(options)).process(rules, {
from: '/example/main.css'
}).css;
expect(processed).toBe(covered);
});
it('when using array at the time, the style should not be overwritten.', function () {
var options = {
exclude: [/node_modules/, /exclude/]
}
var processed = postcss(pxToViewport(options)).process(rules, {
from: '/exclude/main.css'
}).css;
expect(processed).toBe(rules);
});
it('when using array at the time, the style should be overwritten.', function () {
var options = {
exclude: [/node_modules/, /exclude/]
}
var processed = postcss(pxToViewport(options)).process(rules, {
from: '/example/main.css'
}).css;
expect(processed).toBe(covered);
});
});
describe('filter-prop-list', function () {
it('should find "exact" matches from propList', function () {
var propList = ['font-size', 'margin', '!padding', '*border*', '*', '*y', '!*font*'];

Loading…
Cancel
Save