Browse Source

add landscape orientation option

add-media-landscape
Ivan Bunin 7 years ago
parent
commit
df6516177a
  1. 48
      index.js
  2. 57
      spec/px-to-viewport.spec.js

48
index.js

@ -16,7 +16,9 @@ var defaults = {
propList: ['*'],
minPixelValue: 1,
mediaQuery: false,
replace: true
replace: true,
landscape: false,
landscapeUnit: 'vh'
};
module.exports = postcss.plugin('postcss-px-to-viewport', function (options) {
@ -24,7 +26,8 @@ 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 = [];
return function (css) {
css.walkRules(function (rule) {
// Add exclude option to ignore some files like 'node_modules'
@ -42,18 +45,32 @@ module.exports = postcss.plugin('postcss-px-to-viewport', function (options) {
}
}
if (rule.parent.params && !opts.mediaQuery) return;
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))
}));
});
}
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.viewportWidth, opts.minPixelValue, opts.unitPrecision, unit));
var value = decl.value.replace(pxRegex, createPxReplace(opts, unit));
if (declarationExists(decl.parent, decl.prop, value)) return;
if (opts.replace) {
decl.value = value;
} else {
@ -61,6 +78,13 @@ 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));
css.append(landscapeRoot);
}
};
});
@ -75,12 +99,12 @@ function getUnit(prop, opts) {
return prop.indexOf('font') === -1 ? opts.viewportUnit : opts.fontViewportUnit;
}
function createPxReplace(viewportSize, minPixelValue, unitPrecision, viewportUnit) {
function createPxReplace(opts, viewportUnit) {
return function (m, $1) {
if (!$1) return m;
var pixels = parseFloat($1);
if (pixels <= minPixelValue) return m;
var parsedVal = toFixed((pixels / viewportSize * 100), unitPrecision);
if (pixels <= opts.minPixelValue) return m;
var parsedVal = toFixed((pixels / opts.viewportWidth * 100), opts.unitPrecision);
return parsedVal === 0 ? '0' : parsedVal + viewportUnit;
};
}
@ -103,4 +127,8 @@ function declarationExists(decls, prop, value) {
return decls.some(function (decl) {
return (decl.prop === prop && decl.value === value);
});
}
}
function validateParams(params, mediaQuery) {
return !params || (params && mediaQuery && params.indexOf('landscape') === -1);
}

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

@ -221,6 +221,16 @@ describe('mediaQuery', function () {
expect(processed).toBe(expected);
});
it('should not replace px inside media queries if it has params orientation landscape', function() {
var options = {
mediaQuery: 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 } }';
expect(processed).toBe(expected);
});
});
describe('propList', function () {
@ -379,3 +389,50 @@ 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 options = {
landscape: true
};
var processed = postcss(pxToViewport(options)).process(css).css;
expect(processed).toBe(expected);
});
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 options = {
landscape: true,
landscapeUnit: 'vw'
};
var processed = postcss(pxToViewport(options)).process(css).css;
expect(processed).toBe(expected);
});
it('should not add landscape atRule in mediaQueries', function() {
var css = '@media (min-width: 500px) { .rule { font-size: 16px } }';
var expected = '@media (min-width: 500px) { .rule { font-size: 5vw } }';
var options = {
landscape: true,
mediaQuery: true
};
var processed = postcss(pxToViewport(options)).process(css).css;
expect(processed).toBe(expected);
});
it('should not 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 } }';
expect(processed).toBe(expected);
})
});
Loading…
Cancel
Save