diff --git a/README.md b/README.md index a714d7b..299809e 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ A plugin for [PostCSS](https://github.com/ai/postcss) that generates rem units f ## Install ```shell -$ npm install postcss-pxtorem --save-dev +$ npm install postcss postcss-pxtorem --save-dev ``` ## Usage @@ -79,7 +79,7 @@ Default: - Use wildcard `*` to enable all properties. Example: `['*']` - Use `*` at the start or end of a word. (`['*position*']` will match `background-position-y`) - Use `!` to not match a property. Example: `['*', '!letter-spacing']` - - Combine the "not" prefix with the other prefixes. Example: `['*', '!font*']` + - Combine the "not" prefix with the other prefixes. Example: `['*', '!font*']` - `selectorBlackList` (Array) The selectors to ignore and leave as px. - If value is string, it checks to see if selector contains the string. - `['body']` will match `.body-class` diff --git a/index.js b/index.js index d4e12fa..9b9f8a0 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,3 @@ -const postcss = require("postcss"); const pxRegex = require("./lib/pixel-unit-regex"); const filterPropList = require("./lib/filter-prop-list"); const type = require("./lib/type"); @@ -23,62 +22,6 @@ const legacyOptions = { propWhiteList: "propList" }; -module.exports = postcss.plugin("postcss-pxtorem", options => { - convertLegacyOptions(options); - const opts = Object.assign({}, defaults, options); - const satisfyPropList = createPropListMatcher(opts.propList); - - return css => { - const exclude = opts.exclude; - const filePath = css.source.input.file; - if ( - exclude && - ((type.isFunction(exclude) && exclude(filePath)) || - (type.isString(exclude) && filePath.indexOf(exclude) !== -1) || - filePath.match(exclude) !== null) - ) { - return; - } - - const rootValue = - typeof opts.rootValue === "function" - ? opts.rootValue(css.source.input) - : opts.rootValue; - const pxReplace = createPxReplace( - rootValue, - opts.unitPrecision, - opts.minPixelValue - ); - - css.walkDecls((decl, i) => { - if ( - decl.value.indexOf("px") === -1 || - !satisfyPropList(decl.prop) || - blacklistedSelector(opts.selectorBlackList, decl.parent.selector) - ) - return; - - const value = decl.value.replace(pxRegex, pxReplace); - - // if rem unit already exists, do not add or replace - if (declarationExists(decl.parent, decl.prop, value)) return; - - if (opts.replace) { - decl.value = value; - } else { - decl.parent.insertAfter(i, decl.clone({ value: value })); - } - }); - - if (opts.mediaQuery) { - css.walkAtRules("media", rule => { - if (rule.params.indexOf("px") === -1) return; - rule.params = rule.params.replace(pxRegex, pxReplace); - }); - } - }; -}); - function convertLegacyOptions(options) { if (typeof options !== "object") return; if ( @@ -172,3 +115,68 @@ function createPropListMatcher(propList) { ); }; } + +module.exports = (options = {}) => { + convertLegacyOptions(options); + const opts = Object.assign({}, defaults, options); + const satisfyPropList = createPropListMatcher(opts.propList); + const exclude = opts.exclude; + let isExcludeFile = false; + let pxReplace; + return { + postcssPlugin: "postcss-pxtorem", + Once(css) { + const filePath = css.source.input.file; + if ( + exclude && + ((type.isFunction(exclude) && exclude(filePath)) || + (type.isString(exclude) && filePath.indexOf(exclude) !== -1) || + filePath.match(exclude) !== null) + ) { + isExcludeFile = true; + } else { + isExcludeFile = false; + } + + const rootValue = + typeof opts.rootValue === "function" + ? opts.rootValue(css.source.input) + : opts.rootValue; + pxReplace = createPxReplace( + rootValue, + opts.unitPrecision, + opts.minPixelValue + ); + }, + Declaration(decl) { + if (isExcludeFile) return; + + if ( + decl.value.indexOf("px") === -1 || + !satisfyPropList(decl.prop) || + blacklistedSelector(opts.selectorBlackList, decl.parent.selector) + ) + return; + + const value = decl.value.replace(pxRegex, pxReplace); + + // if rem unit already exists, do not add or replace + if (declarationExists(decl.parent, decl.prop, value)) return; + + if (opts.replace) { + decl.value = value; + } else { + decl.cloneAfter({ value: value }); + } + }, + AtRule(atRule) { + if (isExcludeFile) return; + + if (opts.mediaQuery && atRule.name === "media") { + if (atRule.params.indexOf("px") === -1) return; + atRule.params = atRule.params.replace(pxRegex, pxReplace); + } + } + }; +}; +module.exports.postcss = true; diff --git a/package-lock.json b/package-lock.json index 7f18662..dbbd1fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -142,6 +142,7 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -202,6 +203,7 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -212,6 +214,7 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -299,6 +302,7 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, "requires": { "color-name": "1.1.3" } @@ -306,7 +310,14 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "colorette": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz", + "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==", + "dev": true }, "commander": { "version": "4.1.1", @@ -429,7 +440,8 @@ "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true }, "eslint": { "version": "6.8.0", @@ -868,7 +880,8 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true }, "human-signals": { "version": "1.1.1", @@ -1598,6 +1611,12 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, + "nanoid": { + "version": "3.1.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", + "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "dev": true + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -1795,13 +1814,14 @@ } }, "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.1.tgz", + "integrity": "sha512-RhsqOOAQzTgh1UB/IZdca7F9WDb7SUCR2Vnv1x7DbvuuggQIpoDwjK+q0rzoPffhYvWNKX5JSwS4so4K3UC6vA==", + "dev": true, "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" + "colorette": "^1.2.1", + "nanoid": "^3.1.20", + "source-map": "^0.6.1" } }, "prelude-ls": { @@ -2006,7 +2026,8 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true }, "sprintf-js": { "version": "1.0.3", @@ -2080,14 +2101,6 @@ "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", "dev": true }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "requires": { - "has-flag": "^3.0.0" - } - }, "symbol-observable": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", diff --git a/package.json b/package.json index 2be1fdb..fd5fa28 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "husky": "^4.2.3", "jasmine-node": "^3.0.0", "lint-staged": "^10.0.8", + "postcss": "^8.0.0", "prettier": "^1.19.1" }, "keywords": [ @@ -40,7 +41,7 @@ "postcss", "postcss-plugin" ], - "dependencies": { - "postcss": "^7.0.27" + "peerDependencies": { + "postcss": "^8.0.0" } }