123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- const pxRegex = require("./lib/pixel-unit-regex");
- const filterPropList = require("./lib/filter-prop-list");
- const type = require("./lib/type");
- const defaults = {
- rootValue: 16,
- unitPrecision: 5,
- selectorBlackList: [],
- propList: ["font", "font-size", "line-height", "letter-spacing"],
- replace: true,
- mediaQuery: false,
- minPixelValue: 0,
- exclude: null,
- unit: "px",
- };
- const legacyOptions = {
- root_value: "rootValue",
- unit_precision: "unitPrecision",
- selector_black_list: "selectorBlackList",
- prop_white_list: "propList",
- media_query: "mediaQuery",
- propWhiteList: "propList",
- };
- function convertLegacyOptions(options) {
- if (typeof options !== "object") return;
- if (
- ((typeof options["prop_white_list"] !== "undefined" &&
- options["prop_white_list"].length === 0) ||
- (typeof options.propWhiteList !== "undefined" &&
- options.propWhiteList.length === 0)) &&
- typeof options.propList === "undefined"
- ) {
- options.propList = ["*"];
- delete options["prop_white_list"];
- delete options.propWhiteList;
- }
- Object.keys(legacyOptions).forEach((key) => {
- if (Reflect.has(options, key)) {
- options[legacyOptions[key]] = options[key];
- delete options[key];
- }
- });
- }
- function createPxReplace(rootValue, unitPrecision, minPixelValue) {
- return (m, $1) => {
- if (!$1) return m;
- const pixels = parseFloat($1);
- if (pixels < minPixelValue) return m;
- const fixedVal = toFixed(pixels / rootValue, unitPrecision);
- return fixedVal === 0 ? "0" : fixedVal + "rem";
- };
- }
- function toFixed(number, precision) {
- const multiplier = Math.pow(10, precision + 1),
- wholeNumber = Math.floor(number * multiplier);
- return (Math.round(wholeNumber / 10) * 10) / multiplier;
- }
- function declarationExists(decls, prop, value) {
- return decls.some((decl) => decl.prop === prop && decl.value === value);
- }
- function blacklistedSelector(blacklist, selector) {
- if (typeof selector !== "string") return;
- return blacklist.some((regex) => {
- if (typeof regex === "string") {
- return selector.indexOf(regex) !== -1;
- }
- return selector.match(regex);
- });
- }
- function createPropListMatcher(propList) {
- const hasWild = propList.indexOf("*") > -1;
- const matchAll = hasWild && propList.length === 1;
- const lists = {
- exact: filterPropList.exact(propList),
- contain: filterPropList.contain(propList),
- startWith: filterPropList.startWith(propList),
- endWith: filterPropList.endWith(propList),
- notExact: filterPropList.notExact(propList),
- notContain: filterPropList.notContain(propList),
- notStartWith: filterPropList.notStartWith(propList),
- notEndWith: filterPropList.notEndWith(propList),
- };
- return (prop) => {
- if (matchAll) return true;
- return (
- (hasWild ||
- lists.exact.indexOf(prop) > -1 ||
- lists.contain.some(function (m) {
- return prop.indexOf(m) > -1;
- }) ||
- lists.startWith.some(function (m) {
- return prop.indexOf(m) === 0;
- }) ||
- lists.endWith.some(function (m) {
- return prop.indexOf(m) === prop.length - m.length;
- })) &&
- !(
- lists.notExact.indexOf(prop) > -1 ||
- lists.notContain.some(function (m) {
- return prop.indexOf(m) > -1;
- }) ||
- lists.notStartWith.some(function (m) {
- return prop.indexOf(m) === 0;
- }) ||
- lists.notEndWith.some(function (m) {
- return prop.indexOf(m) === prop.length - m.length;
- })
- )
- );
- };
- }
- 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(opts.unit) === -1 ||
- !satisfyPropList(decl.prop) ||
- blacklistedSelector(opts.selectorBlackList, decl.parent.selector)
- )
- return;
- const value = decl.value.replace(pxRegex(opts.unit), 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(opts.unit) === -1) return;
- atRule.params = atRule.params.replace(pxRegex(opts.unit), pxReplace);
- }
- },
- };
- };
- module.exports.postcss = true;
|