Skip to content

Commit

Permalink
Merge branch 'feature/minPixelValue'
Browse files Browse the repository at this point in the history
  • Loading branch information
cuth committed Dec 22, 2015
2 parents 129767f + 11f04b0 commit b4e50e5
Show file tree
Hide file tree
Showing 9 changed files with 192 additions and 90 deletions.
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ insert_final_newline = true

[*.md]
trim_trailing_whitespace = false

[*.json]
indent_size = 2
2 changes: 1 addition & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
@@ -1 +1 @@
* text=auto
* text=auto eol=lf
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
node_modules
.DS_Store
6 changes: 4 additions & 2 deletions .jshintrc
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
{
"browser": true,
"node": true,
"bitwise": true,
"camelcase": false,
"curly": false,
"eqeqeq": true,
"esnext": true,
"immed": true,
"indent": 4,
"latedef": "nofunc",
"latedef": false,
"newcap": true,
"nonbsp": true,
"quotmark": "single",
"undef": true,
"unused": true,
"strict": true,
"strict": false,
"trailing": true
}
24 changes: 14 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,21 +56,25 @@ Type: `Object | Null`
Default:
```js
{
root_value: 16,
unit_precision: 5,
prop_white_list: ['font', 'font-size', 'line-height', 'letter-spacing'],
selector_black_list: [],
rootValue: 16,
unitPrecision: 5,
propWhiteList: ['font', 'font-size', 'line-height', 'letter-spacing'],
selectorBlackList: [],
replace: true,
media_query: false
mediaQuery: false,
minPixelValue: 0
}
```

- `root_value` (Number) The root element font size.
- `unit_precision` (Number) The decimal numbers to allow the REM units to grow to.
- `prop_white_list` (Array) The properties that can change from px to rem. Set this to an empty array to disable the white list and enable all properties.
- `selector_black_list` (Array) The selectors to ignore and leave as px.
- `rootValue` (Number) The root element font size.
- `unitPrecision` (Number) The decimal numbers to allow the REM units to grow to.
- `propWhiteList` (Array) The properties that can change from px to rem.
- Set this to an empty array to disable the white list and enable all properties.
- Values need to be exact matches.
- `selectorBlackList` (Array) The selectors to ignore and leave as px.
- `replace` (Boolean) replaces rules containing rems instead of adding fallbacks.
- `media_query` (Boolean) Allow px to be converted in media queries.
- `mediaQuery` (Boolean) Allow px to be converted in media queries.
- `minPixelValue` (Number) Set the minimum pixel value to replace.


### Use with gulp-postcss and autoprefixer
Expand Down
91 changes: 58 additions & 33 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,66 +2,91 @@

var postcss = require('postcss');
var pxRegex = require('./lib/pixel-unit-regex');
var objectAssign = require('object-assign');

var defaults = {
rootValue: 16,
unitPrecision: 5,
selectorBlackList: [],
propWhiteList: ['font', 'font-size', 'line-height', 'letter-spacing'],
replace: true,
mediaQuery: false,
minPixelValue: 0
};

var legacyOptions = {
'root_value': 'rootValue',
'unit_precision': 'unitPrecision',
'selector_black_list': 'selectorBlackList',
'prop_white_list': 'propWhiteList',
'media_query': 'mediaQuery'
};

module.exports = postcss.plugin('postcss-pxtorem', function (options) {

return function (css) {
convertLegacyOptions(options);

options = options || {};
var rootValue = options.root_value || 16;
var unitPrecision = options.unit_precision || 5;
var selectorBlackList = options.selector_black_list || [];
var propWhiteList = options.prop_white_list || ['font', 'font-size', 'line-height', 'letter-spacing'];
var replace = (options.replace === false) ? false : true;
var mediaQuery = options.media_query || false;
var opts = objectAssign({}, defaults, options);
var pxReplace = createPxReplace(opts.rootValue, opts.unitPrecision, opts.minPixelValue);

var pxReplace = function (m, $1) {
if (!$1) return m;
return toFixed((parseFloat($1) / rootValue), unitPrecision) + 'rem';
};
return function (css) {

css.walkDecls(function (decl, i) {
if (propWhiteList.length && propWhiteList.indexOf(decl.prop) === -1) return;
// This should be the fastest test and will remove most declarations
if (decl.value.indexOf('px') === -1) return;

if (blacklistedSelector(selectorBlackList, decl.parent.selector)) return;
if (opts.propWhiteList.length && opts.propWhiteList.indexOf(decl.prop) === -1) return;

var rule = decl.parent;
var value = decl.value;
if (blacklistedSelector(opts.selectorBlackList, decl.parent.selector)) return;

if (value.indexOf('px') !== -1) {
value = value.replace(pxRegex, pxReplace);
var value = decl.value.replace(pxRegex, pxReplace);

// if rem unit already exists, do not add or replace
if (remExists(rule, decl.prop, value)) return;
// if rem unit already exists, do not add or replace
if (declarationExists(decl.parent, decl.prop, value)) return;

if (replace) {
decl.value = value;
} else {
rule.insertAfter(i, decl.clone({ value: value }));
}
if (opts.replace) {
decl.value = value;
} else {
decl.parent.insertAfter(i, decl.clone({ value: value }));
}
});

if (mediaQuery) {
css.walkAtRules(function (rule) {
if (rule.name !== 'media') return;

if (rule.params.indexOf('px') !== -1) {
rule.params = rule.params.replace(pxRegex, pxReplace);
}
if (opts.mediaQuery) {
css.walkAtRules('media', function (rule) {
if (rule.params.indexOf('px') === -1) return;
rule.params = rule.params.replace(pxRegex, pxReplace);
});
}

};
});

function convertLegacyOptions(options) {
if (typeof options !== 'object') return;
Object.keys(legacyOptions).forEach(function (key) {
if (options.hasOwnProperty(key)) {
options[legacyOptions[key]] = options[key];
delete options[key];
}
});
}

function createPxReplace (rootValue, unitPrecision, minPixelValue) {
return function (m, $1) {
if (!$1) return m;
var pixels = parseFloat($1);
if (pixels < minPixelValue) return m;
return toFixed((pixels / rootValue), unitPrecision) + 'rem';
};
}

function toFixed(number, precision) {
var multiplier = Math.pow(10, precision + 1),
wholeNumber = Math.floor(number * multiplier);
return Math.round(wholeNumber / 10) * 10 / multiplier;
}

function remExists(decls, prop, value) {
function declarationExists(decls, prop, value) {
return decls.some(function (decl) {
return (decl.prop === prop && decl.value === value);
});
Expand Down
2 changes: 1 addition & 1 deletion lib/pixel-unit-regex.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// excluding regex trick: http://www.rexegg.com/regex-best-trick.html

// Not anything inside single quotes
// Not anything inside double quotes
// Not anything inside single quotes
// Not anything inside url()
// Any digit followed by px
// !singlequotes|!doublequotes|!url()|pixelunit
Expand Down
57 changes: 29 additions & 28 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
{
"name": "postcss-pxtorem",
"description": "A CSS post-processor that converts px to rem.",
"version": "3.1.1",
"author": "cuth",
"license": "MIT",
"repository": {
"type": "git",
"url": "git://github.com/cuth/pxtorem"
},
"bugs": "https://github.com/cuth/pxtorem/issues",
"main": "index.js",
"scripts": {
"test": "jasmine-node spec"
},
"devDependencies": {
"jasmine-node": "~1.11.0"
},
"keywords": [
"css",
"rem",
"pixel",
"px",
"postcss",
"postcss-plugin"
],
"dependencies": {
"postcss": "^5.0.2"
}
"name": "postcss-pxtorem",
"description": "A CSS post-processor that converts px to rem.",
"version": "3.1.1",
"author": "cuth",
"license": "MIT",
"repository": {
"type": "git",
"url": "git://github.com/cuth/pxtorem"
},
"bugs": "https://github.com/cuth/pxtorem/issues",
"main": "index.js",
"scripts": {
"test": "jasmine-node spec"
},
"devDependencies": {
"jasmine-node": "~1.11.0"
},
"keywords": [
"css",
"rem",
"pixel",
"px",
"postcss",
"postcss-plugin"
],
"dependencies": {
"object-assign": "^4.0.1",
"postcss": "^5.0.2"
}
}
Loading

0 comments on commit b4e50e5

Please sign in to comment.