Browse Source

add landscape width and change landscape default units; add processing for landscape orientation specified by user

add-media-landscape
Ivan Bunin 7 years ago
parent
commit
bf89798af0
  1. 67
      index.js
  2. 39
      spec/px-to-viewport.spec.js

67
index.js

@ -18,12 +18,14 @@ var defaults = {
mediaQuery: false,
replace: true,
landscape: false,
landscapeUnit: 'vh'
landscapeUnit: 'vw',
landscapeWidth: 568
};
module.exports = postcss.plugin('postcss-px-to-viewport', function (options) {
var opts = objectAssign({}, defaults, options);
var pxRegex = getUnitRegexp(opts.unitToConvert);
var satisfyPropList = createPropListMatcher(opts.propList);
var landscapeRules = [];
@ -35,39 +37,60 @@ module.exports = postcss.plugin('postcss-px-to-viewport', function (options) {
if (opts.exclude && file) {
if (Object.prototype.toString.call(opts.exclude) === '[object RegExp]') {
if (!handleExclude(opts.exclude, file)) return;
if (isExclude(opts.exclude, 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], file)) return;
if (isExclude(opts.exclude[i], file)) return;
}
} else {
throw new Error('options.exclude should be RegExp or Array.');
}
}
if (!validateParams(rule.parent.params, opts.mediaQuery)) return;
if (blacklistedSelector(opts.selectorBlackList, rule.selector)) return;
if (opts.landscape && !rule.parent.params) {
var landscapeRule = rule.clone().removeAll();
landscapeRules.push(landscapeRule);
rule.walkDecls(function(decl) {
if (decl.value.indexOf(opts.unitToConvert) === -1) return;
if (!satisfyPropList(decl.prop)) return;
landscapeRule.append(decl.clone({
value: decl.value.replace(pxRegex, createPxReplace(opts, opts.landscapeUnit))
}));
var landscapeDecl = decl.clone({
value: decl.value.replace(pxRegex, createPxReplace(opts, opts.landscapeUnit, opts.landscapeWidth))
});
if (opts.replace) {
landscapeRule.append(landscapeDecl);
} else {
landscapeRule.append([decl.clone(), landscapeDecl]);
}
});
if (landscapeRule.nodes.length > 0) {
landscapeRules.push(landscapeRule);
}
}
if (!validateParams(rule.parent.params, opts.mediaQuery)) return;
rule.walkDecls(function(decl, i) {
if (decl.value.indexOf(opts.unitToConvert) === -1) return;
if (!satisfyPropList(decl.prop)) return;
var unit = getUnit(decl.prop, opts);
var value = decl.value.replace(pxRegex, createPxReplace(opts, unit));
var unit;
var size;
var params = rule.parent.params;
if (opts.landscape && params && params.indexOf('landscape') !== -1) {
unit = opts.landscapeUnit;
size = opts.landscapeWidth;
} else {
unit = getUnit(decl.prop, opts);
size = opts.viewportWidth;
}
var value = decl.value.replace(pxRegex, createPxReplace(opts, unit, size));
if (declarationExists(decl.parent, decl.prop, value)) return;
@ -82,29 +105,24 @@ module.exports = postcss.plugin('postcss-px-to-viewport', function (options) {
if (landscapeRules.length > 0) {
var landscapeRoot = new postcss.atRule({ params: '(orientation: landscape)', name: 'media' });
landscapeRules.forEach(rule => landscapeRoot.append(rule));
landscapeRules.forEach(function(rule) {
landscapeRoot.append(rule);
});
css.append(landscapeRoot);
}
};
});
function handleExclude (reg, file) {
if (Object.prototype.toString.call(reg) !== '[object RegExp]') {
throw new Error('options.exclude should be RegExp.');
}
return file.match(reg) === null;
}
function getUnit(prop, opts) {
return prop.indexOf('font') === -1 ? opts.viewportUnit : opts.fontViewportUnit;
}
function createPxReplace(opts, viewportUnit) {
function createPxReplace(opts, viewportUnit, viewportSize) {
return function (m, $1) {
if (!$1) return m;
var pixels = parseFloat($1);
if (pixels <= opts.minPixelValue) return m;
var parsedVal = toFixed((pixels / opts.viewportWidth * 100), opts.unitPrecision);
var parsedVal = toFixed((pixels / viewportSize * 100), opts.unitPrecision);
return parsedVal === 0 ? '0' : parsedVal + viewportUnit;
};
}
@ -123,6 +141,13 @@ 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 declarationExists(decls, prop, value) {
return decls.some(function (decl) {
return (decl.prop === prop && decl.value === value);
@ -130,5 +155,5 @@ function declarationExists(decls, prop, value) {
}
function validateParams(params, mediaQuery) {
return !params || (params && mediaQuery && params.indexOf('landscape') === -1);
return !params || (params && mediaQuery);
}

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

@ -222,12 +222,13 @@ describe('mediaQuery', function () {
expect(processed).toBe(expected);
});
it('should not replace px inside media queries if it has params orientation landscape', function() {
it('should replace px inside media queries if it has params orientation landscape and landscape option', function() {
var options = {
mediaQuery: true
mediaQuery: true,
landscape: true
};
var processed = postcss(pxToViewport(options)).process('@media (orientation-landscape) and (min-width: 500px) { .rule { font-size: 16px } }').css;
var expected = '@media (orientation-landscape) and (min-width: 500px) { .rule { font-size: 16px } }';
var expected = '@media (orientation-landscape) and (min-width: 500px) { .rule { font-size: 2.8169vw } }';
expect(processed).toBe(expected);
});
@ -392,7 +393,7 @@ describe('filter-prop-list', function () {
describe('landscape', function() {
it('should add landscape atRule', function() {
var css = '.rule { font-size: 16px; margin: 16px; margin-left: 5px; padding: 5px; padding-right: 16px }';
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 } }';
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 } }';
var options = {
landscape: true
};
@ -403,10 +404,10 @@ describe('landscape', function() {
it('should add landscape atRule with specified landscapeUnits', function() {
var css = '.rule { font-size: 16px; margin: 16px; margin-left: 5px; padding: 5px; padding-right: 16px }';
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 } }';
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 } }';
var options = {
landscape: true,
landscapeUnit: 'vw'
landscapeUnit: 'vh'
};
var processed = postcss(pxToViewport(options)).process(css).css;
@ -425,13 +426,35 @@ describe('landscape', function() {
expect(processed).toBe(expected);
});
it('should not replace values inside landscape atRule', function() {
it('should replace values inside landscape atRule', function() {
var options = {
replace: false,
landscape: true
};
var processed = postcss(pxToViewport(options)).process(basicCSS).css;
var expected = '.rule { font-size: 15px; font-size: 4.6875vw }@media (orientation: landscape) {.rule { font-size: 4.6875vh } }';
var expected = '.rule { font-size: 15px; font-size: 4.6875vw }@media (orientation: landscape) {.rule { font-size: 15px; font-size: 2.64085vw } }';
expect(processed).toBe(expected);
});
it('should add landscape atRule with specified landscapeWidth', function() {
var options = {
landscape: true,
landscapeWidth: 768
};
var processed = postcss(pxToViewport(options)).process(basicCSS).css;
var expected = '.rule { font-size: 4.6875vw }@media (orientation: landscape) {.rule { font-size: 1.95313vw } }';
expect(processed).toBe(expected);
});
it('should not add landscape atRule if it has no nodes', function() {
var css = '.rule { font-size: 15vw }';
var options = {
landscape: true
};
var processed = postcss(pxToViewport(options)).process(css).css;
var expected = '.rule { font-size: 15vw }';
expect(processed).toBe(expected);
})

Loading…
Cancel
Save