Skip to content

Commit 11f04b0

Browse files
committed
add option to avoid converting 1px, close #18
1 parent b602ded commit 11f04b0

File tree

4 files changed

+115
-42
lines changed

4 files changed

+115
-42
lines changed

.jshintrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"browser": true,
33
"node": true,
44
"bitwise": true,
5-
"camelcase": true,
5+
"camelcase": false,
66
"curly": false,
77
"eqeqeq": true,
88
"esnext": true,

README.md

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,21 +56,25 @@ Type: `Object | Null`
5656
Default:
5757
```js
5858
{
59-
root_value: 16,
60-
unit_precision: 5,
61-
prop_white_list: ['font', 'font-size', 'line-height', 'letter-spacing'],
62-
selector_black_list: [],
59+
rootValue: 16,
60+
unitPrecision: 5,
61+
propWhiteList: ['font', 'font-size', 'line-height', 'letter-spacing'],
62+
selectorBlackList: [],
6363
replace: true,
64-
media_query: false
64+
mediaQuery: false,
65+
minPixelValue: 0
6566
}
6667
```
6768

68-
- `root_value` (Number) The root element font size.
69-
- `unit_precision` (Number) The decimal numbers to allow the REM units to grow to.
70-
- `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.
71-
- `selector_black_list` (Array) The selectors to ignore and leave as px.
69+
- `rootValue` (Number) The root element font size.
70+
- `unitPrecision` (Number) The decimal numbers to allow the REM units to grow to.
71+
- `propWhiteList` (Array) The properties that can change from px to rem.
72+
- Set this to an empty array to disable the white list and enable all properties.
73+
- Values need to be exact matches.
74+
- `selectorBlackList` (Array) The selectors to ignore and leave as px.
7275
- `replace` (Boolean) replaces rules containing rems instead of adding fallbacks.
73-
- `media_query` (Boolean) Allow px to be converted in media queries.
76+
- `mediaQuery` (Boolean) Allow px to be converted in media queries.
77+
- `minPixelValue` (Number) Set the minimum pixel value to replace.
7478

7579

7680
### Use with gulp-postcss and autoprefixer

index.js

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ var defaults = {
1010
selectorBlackList: [],
1111
propWhiteList: ['font', 'font-size', 'line-height', 'letter-spacing'],
1212
replace: true,
13-
mediaQuery: false
13+
mediaQuery: false,
14+
minPixelValue: 0
1415
};
1516

1617
var legacyOptions = {
@@ -26,29 +27,27 @@ module.exports = postcss.plugin('postcss-pxtorem', function (options) {
2627
convertLegacyOptions(options);
2728

2829
var opts = objectAssign({}, defaults, options);
29-
var pxReplace = createPxReplace(opts.rootValue, opts.unitPrecision);
30+
var pxReplace = createPxReplace(opts.rootValue, opts.unitPrecision, opts.minPixelValue);
3031

3132
return function (css) {
3233

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

3640
if (blacklistedSelector(opts.selectorBlackList, decl.parent.selector)) return;
3741

38-
var rule = decl.parent;
39-
var value = decl.value;
40-
41-
if (value.indexOf('px') !== -1) {
42-
value = value.replace(pxRegex, pxReplace);
42+
var value = decl.value.replace(pxRegex, pxReplace);
4343

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

47-
if (opts.replace) {
48-
decl.value = value;
49-
} else {
50-
rule.insertAfter(i, decl.clone({ value: value }));
51-
}
47+
if (opts.replace) {
48+
decl.value = value;
49+
} else {
50+
decl.parent.insertAfter(i, decl.clone({ value: value }));
5251
}
5352
});
5453

@@ -72,10 +71,12 @@ function convertLegacyOptions(options) {
7271
});
7372
}
7473

75-
function createPxReplace (rootValue, unitPrecision) {
74+
function createPxReplace (rootValue, unitPrecision, minPixelValue) {
7675
return function (m, $1) {
7776
if (!$1) return m;
78-
return toFixed((parseFloat($1) / rootValue), unitPrecision) + 'rem';
77+
var pixels = parseFloat($1);
78+
if (pixels < minPixelValue) return m;
79+
return toFixed((pixels / rootValue), unitPrecision) + 'rem';
7980
};
8081
}
8182

@@ -85,7 +86,7 @@ function toFixed(number, precision) {
8586
return Math.round(wholeNumber / 10) * 10 / multiplier;
8687
}
8788

88-
function remExists(decls, prop, value) {
89+
function declarationExists(decls, prop, value) {
8990
return decls.some(function (decl) {
9091
return (decl.prop === prop && decl.value === value);
9192
});

spec/pxtorem-spec.js

Lines changed: 82 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
'use strict';
99
var postcss = require('postcss');
1010
var pxtorem = require('..');
11-
var css = '.rule { font-size: 15px }';
11+
var basicCSS = '.rule { font-size: 15px }';
1212

1313
describe('pxtorem', function () {
1414

@@ -21,38 +21,71 @@ describe('pxtorem', function () {
2121
});
2222

2323
it('should replace the px unit with rem', function () {
24-
var processed = postcss(pxtorem()).process(css).css;
24+
var processed = postcss(pxtorem()).process(basicCSS).css;
2525
var expected = '.rule { font-size: 0.9375rem }';
2626

2727
expect(processed).toBe(expected);
2828
});
2929

30-
it('should replace using a root value of 10', function () {
30+
// Deprecate
31+
it('should replace using a root value of 10 - legacy', function () {
3132
var expected = '.rule { font-size: 1.5rem }';
3233
var options = {
3334
root_value: 10
3435
};
35-
var processed = postcss(pxtorem(options)).process(css).css;
36+
var processed = postcss(pxtorem(options)).process(basicCSS).css;
3637

3738
expect(processed).toBe(expected);
3839
});
3940

40-
it('should replace using a decimal of 2 places', function () {
41+
it('should replace using a root value of 10', function () {
42+
var expected = '.rule { font-size: 1.5rem }';
43+
var options = {
44+
rootValue: 10
45+
};
46+
var processed = postcss(pxtorem(options)).process(basicCSS).css;
47+
48+
expect(processed).toBe(expected);
49+
});
50+
51+
// Deprecate
52+
it('should replace using a decimal of 2 places - legacy', function () {
4153
var expected = '.rule { font-size: 0.94rem }';
4254
var options = {
4355
unit_precision: 2
4456
};
45-
var processed = postcss(pxtorem(options)).process(css).css;
57+
var processed = postcss(pxtorem(options)).process(basicCSS).css;
4658

4759
expect(processed).toBe(expected);
4860
});
4961

50-
it('should only replace properties in the white list', function () {
62+
it('should replace using a decimal of 2 places', function () {
63+
var expected = '.rule { font-size: 0.94rem }';
64+
var options = {
65+
unitPrecision: 2
66+
};
67+
var processed = postcss(pxtorem(options)).process(basicCSS).css;
68+
69+
expect(processed).toBe(expected);
70+
});
71+
72+
// Deprecate
73+
it('should only replace properties in the white list - legacy', function () {
5174
var expected = '.rule { font-size: 15px }';
5275
var options = {
5376
prop_white_list: ['font']
5477
};
55-
var processed = postcss(pxtorem(options)).process(css).css;
78+
var processed = postcss(pxtorem(options)).process(basicCSS).css;
79+
80+
expect(processed).toBe(expected);
81+
});
82+
83+
it('should only replace properties in the white list', function () {
84+
var expected = '.rule { font-size: 15px }';
85+
var options = {
86+
propWhiteList: ['font']
87+
};
88+
var processed = postcss(pxtorem(options)).process(basicCSS).css;
5689

5790
expect(processed).toBe(expected);
5891
});
@@ -61,14 +94,15 @@ describe('pxtorem', function () {
6194
var rules = '.rule { margin: 16px; font-size: 15px }';
6295
var expected = '.rule { margin: 1rem; font-size: 0.9375rem }';
6396
var options = {
64-
prop_white_list: []
97+
propWhiteList: []
6598
};
6699
var processed = postcss(pxtorem(options)).process(rules).css;
67100

68101
expect(processed).toBe(expected);
69102
});
70103

71-
it('should ignore selectors in the selector black list', function () {
104+
// Deprecate
105+
it('should ignore selectors in the selector black list - legacy', function () {
72106
var rules = '.rule { font-size: 15px } .rule2 { font-size: 15px }';
73107
var expected = '.rule { font-size: 0.9375rem } .rule2 { font-size: 15px }';
74108
var options = {
@@ -79,16 +113,28 @@ describe('pxtorem', function () {
79113
expect(processed).toBe(expected);
80114
});
81115

116+
it('should ignore selectors in the selector black list', function () {
117+
var rules = '.rule { font-size: 15px } .rule2 { font-size: 15px }';
118+
var expected = '.rule { font-size: 0.9375rem } .rule2 { font-size: 15px }';
119+
var options = {
120+
selectorBlackList: ['.rule2']
121+
};
122+
var processed = postcss(pxtorem(options)).process(rules).css;
123+
124+
expect(processed).toBe(expected);
125+
});
126+
82127
it('should leave fallback pixel unit with root em value', function () {
83128
var options = {
84129
replace: false
85130
};
86-
var processed = postcss(pxtorem(options)).process(css).css;
131+
var processed = postcss(pxtorem(options)).process(basicCSS).css;
87132
var expected = '.rule { font-size: 15px; font-size: 0.9375rem }';
88133

89134
expect(processed).toBe(expected);
90135
});
91136

137+
// Deprecate
92138
it('should replace px in media queries', function () {
93139
var options = {
94140
media_query: true
@@ -99,6 +145,16 @@ describe('pxtorem', function () {
99145
expect(processed).toBe(expected);
100146
});
101147

148+
it('should replace px in media queries', function () {
149+
var options = {
150+
mediaQuery: true
151+
};
152+
var processed = postcss(pxtorem(options)).process('@media (min-width: 500px) { .rule { font-size: 16px } }').css;
153+
var expected = '@media (min-width: 31.25rem) { .rule { font-size: 1rem } }';
154+
155+
expect(processed).toBe(expected);
156+
});
157+
102158
it('should ignore non px properties', function () {
103159
var expected = '.rule { font-size: 2em }';
104160
var processed = postcss(pxtorem()).process(expected).css;
@@ -110,7 +166,7 @@ describe('pxtorem', function () {
110166
var rules = '.rule { margin: 0.5rem .5px -0.2px -.2em }';
111167
var expected = '.rule { margin: 0.5rem 0.03125rem -0.0125rem -.2em }';
112168
var options = {
113-
prop_white_list: ['margin']
169+
propWhiteList: ['margin']
114170
};
115171
var processed = postcss(pxtorem(options)).process(rules).css;
116172

@@ -126,7 +182,7 @@ describe('pxtorem', function () {
126182

127183
it('should not replace values in double quotes or single quotes', function () {
128184
var options = {
129-
prop_white_list: []
185+
propWhiteList: []
130186
};
131187
var rules = '.rule { content: \'16px\'; font-family: "16px"; font-size: 16px; }';
132188
var expected = '.rule { content: \'16px\'; font-family: "16px"; font-size: 1rem; }';
@@ -137,12 +193,24 @@ describe('pxtorem', function () {
137193

138194
it('should not replace values in `url()`', function () {
139195
var options = {
140-
prop_white_list: []
196+
propWhiteList: []
141197
};
142198
var rules = '.rule { background: url(16px.jpg); font-size: 16px; }';
143199
var expected = '.rule { background: url(16px.jpg); font-size: 1rem; }';
144200
var processed = postcss(pxtorem(options)).process(rules).css;
145201

146202
expect(processed).toBe(expected);
147203
});
204+
205+
it('should not replace values below minPixelValue', function () {
206+
var options = {
207+
propWhiteList: [],
208+
minPixelValue: 2
209+
};
210+
var rules = '.rule { border: 1px solid #000; font-size: 16px; margin: 1px 10px; }';
211+
var expected = '.rule { border: 1px solid #000; font-size: 1rem; margin: 1px 0.625rem; }';
212+
var processed = postcss(pxtorem(options)).process(rules).css;
213+
214+
expect(processed).toBe(expected);
215+
});
148216
});

0 commit comments

Comments
 (0)