diff --git a/README.md b/README.md index 0e5edb8..154f9d8 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,8 @@ Default: selectorBlackList: [], replace: true, mediaQuery: false, + containerQuery: false, + supportsQuery: false, minPixelValue: 0, exclude: /node_modules/i } @@ -87,6 +89,8 @@ Default: - `[/^body$/]` will match `body` but not `.body` - `replace` (Boolean) Replaces rules containing rems instead of adding fallbacks. - `mediaQuery` (Boolean) Allow px to be converted in media queries. +- `containerQuery` (Boolean) Allow px to be converted in container queries. +- `supportsQuery` (Boolean) Allow px to be converted in supports queries. - `minPixelValue` (Number) Set the minimum pixel value to replace. - `exclude` (String, Regexp, Function) The file path to ignore and leave as px. - If value is string, it checks to see if file path contains the string. diff --git a/index.js b/index.js index 538c1db..dbcbe2f 100644 --- a/index.js +++ b/index.js @@ -6,12 +6,20 @@ const defaults = { rootValue: 16, unitPrecision: 5, selectorBlackList: [], - propList: ["font", "font-size", "line-height", "letter-spacing", "word-spacing"], + propList: [ + "font", + "font-size", + "line-height", + "letter-spacing", + "word-spacing" + ], replace: true, mediaQuery: false, + containerQuery: false, + supportsQuery: false, minPixelValue: 0, exclude: null, - unit: "px", + unit: "px" }; const legacyOptions = { @@ -20,7 +28,7 @@ const legacyOptions = { selector_black_list: "selectorBlackList", prop_white_list: "propList", media_query: "mediaQuery", - propWhiteList: "propList", + propWhiteList: "propList" }; function convertLegacyOptions(options) { @@ -36,7 +44,7 @@ function convertLegacyOptions(options) { delete options["prop_white_list"]; delete options.propWhiteList; } - Object.keys(legacyOptions).forEach((key) => { + Object.keys(legacyOptions).forEach(key => { if (Reflect.has(options, key)) { options[legacyOptions[key]] = options[key]; delete options[key]; @@ -61,12 +69,12 @@ function toFixed(number, precision) { } function declarationExists(decls, prop, value) { - return decls.some((decl) => decl.prop === prop && decl.value === value); + return decls.some(decl => decl.prop === prop && decl.value === value); } function blacklistedSelector(blacklist, selector) { if (typeof selector !== "string") return; - return blacklist.some((regex) => { + return blacklist.some(regex => { if (typeof regex === "string") { return selector.indexOf(regex) !== -1; } @@ -85,31 +93,31 @@ function createPropListMatcher(propList) { notExact: filterPropList.notExact(propList), notContain: filterPropList.notContain(propList), notStartWith: filterPropList.notStartWith(propList), - notEndWith: filterPropList.notEndWith(propList), + notEndWith: filterPropList.notEndWith(propList) }; - return (prop) => { + return prop => { if (matchAll) return true; return ( (hasWild || lists.exact.indexOf(prop) > -1 || - lists.contain.some(function (m) { + lists.contain.some(function(m) { return prop.indexOf(m) > -1; }) || - lists.startWith.some(function (m) { + lists.startWith.some(function(m) { return prop.indexOf(m) === 0; }) || - lists.endWith.some(function (m) { + lists.endWith.some(function(m) { return prop.indexOf(m) === prop.length - m.length; })) && !( lists.notExact.indexOf(prop) > -1 || - lists.notContain.some(function (m) { + lists.notContain.some(function(m) { return prop.indexOf(m) > -1; }) || - lists.notStartWith.some(function (m) { + lists.notStartWith.some(function(m) { return prop.indexOf(m) === 0; }) || - lists.notEndWith.some(function (m) { + lists.notEndWith.some(function(m) { return prop.indexOf(m) === prop.length - m.length; }) ) @@ -146,7 +154,7 @@ module.exports = (options = {}) => { pxReplace = createPxReplace( rootValue, opts.unitPrecision, - opts.minPixelValue, + opts.minPixelValue ); }, Declaration(decl) { @@ -177,7 +185,17 @@ module.exports = (options = {}) => { if (atRule.params.indexOf(opts.unit) === -1) return; atRule.params = atRule.params.replace(pxRegex(opts.unit), pxReplace); } - }, + + if (opts.containerQuery && atRule.name === "container") { + if (atRule.params.indexOf(opts.unit) === -1) return; + atRule.params = atRule.params.replace(pxRegex(opts.unit), pxReplace); + } + + if (opts.supportsQuery && atRule.name === "supports") { + if (atRule.params.indexOf(opts.unit) === -1) return; + atRule.params = atRule.params.replace(pxRegex(opts.unit), pxReplace); + } + } }; }; module.exports.postcss = true; diff --git a/spec/pxtorem-spec.js b/spec/pxtorem-spec.js index 9e0f0b7..26c2303 100644 --- a/spec/pxtorem-spec.js +++ b/spec/pxtorem-spec.js @@ -79,7 +79,7 @@ describe("pxtorem", function() { }); it("should remain unitless if 0", function() { - var expected = ".rule { font-size: 0px; font-size: 0; }"; + var expected = ".rule { font-size: 0rem; font-size: 0; }"; var processed = postcss(pxtorem()).process(expected).css; expect(processed).toBe(expected); @@ -378,6 +378,35 @@ describe("mediaQuery", function() { }); }); +describe("containerQuery", function() { + it("should replace px in container queries", function() { + var options = { + containerQuery: true + }; + var processed = postcss(pxtorem(options)).process( + "@container (min-width: 500px) { .rule { font-size: 16px } }" + ).css; + var expected = + "@container (min-width: 31.25rem) { .rule { font-size: 1rem } }"; + + expect(processed).toBe(expected); + }); +}); + +describe("supportsQuery", function() { + it("should replace px in supports queries", function() { + var options = { + supportsQuery: true + }; + var processed = postcss(pxtorem(options)).process( + "@supports (top: max(24px)) { .rule { font-size: 16px } }" + ).css; + var expected = "@supports (top: max(1.5rem)) { .rule { font-size: 1rem } }"; + + expect(processed).toBe(expected); + }); +}); + describe("minPixelValue", function() { it("should not replace values below minPixelValue", function() { var options = {