Skip to content

Commit bf89798

Browse files
add landscape width and change landscape default units; add processing for landscape orientation specified by user
1 parent df65161 commit bf89798

File tree

2 files changed

+80
-32
lines changed

2 files changed

+80
-32
lines changed

index.js

Lines changed: 49 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@ var defaults = {
1818
mediaQuery: false,
1919
replace: true,
2020
landscape: false,
21-
landscapeUnit: 'vh'
21+
landscapeUnit: 'vw',
22+
landscapeWidth: 568
2223
};
2324

2425
module.exports = postcss.plugin('postcss-px-to-viewport', function (options) {
2526

2627
var opts = objectAssign({}, defaults, options);
28+
2729
var pxRegex = getUnitRegexp(opts.unitToConvert);
2830
var satisfyPropList = createPropListMatcher(opts.propList);
2931
var landscapeRules = [];
@@ -32,42 +34,63 @@ module.exports = postcss.plugin('postcss-px-to-viewport', function (options) {
3234
css.walkRules(function (rule) {
3335
// Add exclude option to ignore some files like 'node_modules'
3436
var file = rule.source.input.file;
35-
37+
3638
if (opts.exclude && file) {
3739
if (Object.prototype.toString.call(opts.exclude) === '[object RegExp]') {
38-
if (!handleExclude(opts.exclude, file)) return;
40+
if (isExclude(opts.exclude, file)) return;
3941
} else if (Object.prototype.toString.call(opts.exclude) === '[object Array]') {
4042
for (let i = 0; i < opts.exclude.length; i++) {
41-
if (!handleExclude(opts.exclude[i], file)) return;
43+
if (isExclude(opts.exclude[i], file)) return;
4244
}
4345
} else {
4446
throw new Error('options.exclude should be RegExp or Array.');
4547
}
4648
}
4749

48-
if (!validateParams(rule.parent.params, opts.mediaQuery)) return;
4950
if (blacklistedSelector(opts.selectorBlackList, rule.selector)) return;
50-
51+
5152
if (opts.landscape && !rule.parent.params) {
5253
var landscapeRule = rule.clone().removeAll();
53-
landscapeRules.push(landscapeRule);
54-
54+
5555
rule.walkDecls(function(decl) {
5656
if (decl.value.indexOf(opts.unitToConvert) === -1) return;
5757
if (!satisfyPropList(decl.prop)) return;
5858

59-
landscapeRule.append(decl.clone({
60-
value: decl.value.replace(pxRegex, createPxReplace(opts, opts.landscapeUnit))
61-
}));
59+
var landscapeDecl = decl.clone({
60+
value: decl.value.replace(pxRegex, createPxReplace(opts, opts.landscapeUnit, opts.landscapeWidth))
61+
});
62+
63+
if (opts.replace) {
64+
landscapeRule.append(landscapeDecl);
65+
} else {
66+
landscapeRule.append([decl.clone(), landscapeDecl]);
67+
}
6268
});
69+
70+
if (landscapeRule.nodes.length > 0) {
71+
landscapeRules.push(landscapeRule);
72+
}
6373
}
74+
75+
if (!validateParams(rule.parent.params, opts.mediaQuery)) return;
6476

6577
rule.walkDecls(function(decl, i) {
6678
if (decl.value.indexOf(opts.unitToConvert) === -1) return;
6779
if (!satisfyPropList(decl.prop)) return;
6880

69-
var unit = getUnit(decl.prop, opts);
70-
var value = decl.value.replace(pxRegex, createPxReplace(opts, unit));
81+
var unit;
82+
var size;
83+
var params = rule.parent.params;
84+
85+
if (opts.landscape && params && params.indexOf('landscape') !== -1) {
86+
unit = opts.landscapeUnit;
87+
size = opts.landscapeWidth;
88+
} else {
89+
unit = getUnit(decl.prop, opts);
90+
size = opts.viewportWidth;
91+
}
92+
93+
var value = decl.value.replace(pxRegex, createPxReplace(opts, unit, size));
7194

7295
if (declarationExists(decl.parent, decl.prop, value)) return;
7396

@@ -82,29 +105,24 @@ module.exports = postcss.plugin('postcss-px-to-viewport', function (options) {
82105
if (landscapeRules.length > 0) {
83106
var landscapeRoot = new postcss.atRule({ params: '(orientation: landscape)', name: 'media' });
84107

85-
landscapeRules.forEach(rule => landscapeRoot.append(rule));
108+
landscapeRules.forEach(function(rule) {
109+
landscapeRoot.append(rule);
110+
});
86111
css.append(landscapeRoot);
87112
}
88113
};
89114
});
90115

91-
function handleExclude (reg, file) {
92-
if (Object.prototype.toString.call(reg) !== '[object RegExp]') {
93-
throw new Error('options.exclude should be RegExp.');
94-
}
95-
return file.match(reg) === null;
96-
}
97-
98116
function getUnit(prop, opts) {
99117
return prop.indexOf('font') === -1 ? opts.viewportUnit : opts.fontViewportUnit;
100118
}
101119

102-
function createPxReplace(opts, viewportUnit) {
120+
function createPxReplace(opts, viewportUnit, viewportSize) {
103121
return function (m, $1) {
104122
if (!$1) return m;
105123
var pixels = parseFloat($1);
106124
if (pixels <= opts.minPixelValue) return m;
107-
var parsedVal = toFixed((pixels / opts.viewportWidth * 100), opts.unitPrecision);
125+
var parsedVal = toFixed((pixels / viewportSize * 100), opts.unitPrecision);
108126
return parsedVal === 0 ? '0' : parsedVal + viewportUnit;
109127
};
110128
}
@@ -123,12 +141,19 @@ function blacklistedSelector(blacklist, selector) {
123141
});
124142
}
125143

144+
function isExclude(reg, file) {
145+
if (Object.prototype.toString.call(reg) !== '[object RegExp]') {
146+
throw new Error('options.exclude should be RegExp.');
147+
}
148+
return file.match(reg) !== null;
149+
}
150+
126151
function declarationExists(decls, prop, value) {
127152
return decls.some(function (decl) {
128153
return (decl.prop === prop && decl.value === value);
129154
});
130155
}
131156

132157
function validateParams(params, mediaQuery) {
133-
return !params || (params && mediaQuery && params.indexOf('landscape') === -1);
158+
return !params || (params && mediaQuery);
134159
}

spec/px-to-viewport.spec.js

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -222,12 +222,13 @@ describe('mediaQuery', function () {
222222
expect(processed).toBe(expected);
223223
});
224224

225-
it('should not replace px inside media queries if it has params orientation landscape', function() {
225+
it('should replace px inside media queries if it has params orientation landscape and landscape option', function() {
226226
var options = {
227-
mediaQuery: true
227+
mediaQuery: true,
228+
landscape: true
228229
};
229230
var processed = postcss(pxToViewport(options)).process('@media (orientation-landscape) and (min-width: 500px) { .rule { font-size: 16px } }').css;
230-
var expected = '@media (orientation-landscape) and (min-width: 500px) { .rule { font-size: 16px } }';
231+
var expected = '@media (orientation-landscape) and (min-width: 500px) { .rule { font-size: 2.8169vw } }';
231232

232233
expect(processed).toBe(expected);
233234
});
@@ -392,7 +393,7 @@ describe('filter-prop-list', function () {
392393
describe('landscape', function() {
393394
it('should add landscape atRule', function() {
394395
var css = '.rule { font-size: 16px; margin: 16px; margin-left: 5px; padding: 5px; padding-right: 16px }';
395-
var expected = '.rule { font-size: 5vw; margin: 5vw; margin-left: 1.5625vw; padding: 1.5625vw; padding-right: 5vw }@media (orientation: landscape) {.rule { font-size: 5vh; margin: 5vh; margin-left: 1.5625vh; padding: 1.5625vh; padding-right: 5vh } }';
396+
var expected = '.rule { font-size: 5vw; margin: 5vw; margin-left: 1.5625vw; padding: 1.5625vw; padding-right: 5vw }@media (orientation: landscape) {.rule { font-size: 2.8169vw; margin: 2.8169vw; margin-left: 0.88028vw; padding: 0.88028vw; padding-right: 2.8169vw } }';
396397
var options = {
397398
landscape: true
398399
};
@@ -403,10 +404,10 @@ describe('landscape', function() {
403404

404405
it('should add landscape atRule with specified landscapeUnits', function() {
405406
var css = '.rule { font-size: 16px; margin: 16px; margin-left: 5px; padding: 5px; padding-right: 16px }';
406-
var expected = '.rule { font-size: 5vw; margin: 5vw; margin-left: 1.5625vw; padding: 1.5625vw; padding-right: 5vw }@media (orientation: landscape) {.rule { font-size: 5vw; margin: 5vw; margin-left: 1.5625vw; padding: 1.5625vw; padding-right: 5vw } }';
407+
var expected = '.rule { font-size: 5vw; margin: 5vw; margin-left: 1.5625vw; padding: 1.5625vw; padding-right: 5vw }@media (orientation: landscape) {.rule { font-size: 2.8169vh; margin: 2.8169vh; margin-left: 0.88028vh; padding: 0.88028vh; padding-right: 2.8169vh } }';
407408
var options = {
408409
landscape: true,
409-
landscapeUnit: 'vw'
410+
landscapeUnit: 'vh'
410411
};
411412
var processed = postcss(pxToViewport(options)).process(css).css;
412413

@@ -425,13 +426,35 @@ describe('landscape', function() {
425426
expect(processed).toBe(expected);
426427
});
427428

428-
it('should not replace values inside landscape atRule', function() {
429+
it('should replace values inside landscape atRule', function() {
429430
var options = {
430431
replace: false,
431432
landscape: true
432433
};
433434
var processed = postcss(pxToViewport(options)).process(basicCSS).css;
434-
var expected = '.rule { font-size: 15px; font-size: 4.6875vw }@media (orientation: landscape) {.rule { font-size: 4.6875vh } }';
435+
var expected = '.rule { font-size: 15px; font-size: 4.6875vw }@media (orientation: landscape) {.rule { font-size: 15px; font-size: 2.64085vw } }';
436+
437+
expect(processed).toBe(expected);
438+
});
439+
440+
it('should add landscape atRule with specified landscapeWidth', function() {
441+
var options = {
442+
landscape: true,
443+
landscapeWidth: 768
444+
};
445+
var processed = postcss(pxToViewport(options)).process(basicCSS).css;
446+
var expected = '.rule { font-size: 4.6875vw }@media (orientation: landscape) {.rule { font-size: 1.95313vw } }';
447+
448+
expect(processed).toBe(expected);
449+
});
450+
451+
it('should not add landscape atRule if it has no nodes', function() {
452+
var css = '.rule { font-size: 15vw }';
453+
var options = {
454+
landscape: true
455+
};
456+
var processed = postcss(pxToViewport(options)).process(css).css;
457+
var expected = '.rule { font-size: 15vw }';
435458

436459
expect(processed).toBe(expected);
437460
})

0 commit comments

Comments
 (0)