Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

pxtorem-css

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

pxtorem-css - npm Package Compare versions

Comparing version
1.0.6
to
2.0.1
+40
dist/cli.js
#!/usr/bin/env node
"use strict";var z=Object.create;var y=Object.defineProperty;var M=Object.getOwnPropertyDescriptor;var B=Object.getOwnPropertyNames;var I=Object.getPrototypeOf,T=Object.prototype.hasOwnProperty;var A=(t,e,i,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of B(e))!T.call(t,s)&&s!==i&&y(t,s,{get:()=>e[s],enumerable:!(r=M(e,s))||r.enumerable});return t};var L=(t,e,i)=>(i=t!=null?z(I(t)):{},A(e||!t||!t.__esModule?y(i,"default",{value:t,enumerable:!0}):i,t));var f=require("fs"),m=require("path"),F=L(require("postcss"));function h(t){return new RegExp(`"[^"]+"|'[^']+'|url\\([^)]+\\)|var\\([^)]+\\)|(\\d*\\.?\\d+)${t}`,"g")}function Q(t){return t.filter(e=>e.match(/^[^*!]+$/))}function j(t){return t.filter(e=>e.match(/^\*.+\*$/)).map(e=>e.slice(1,-1))}function q(t){return t.filter(e=>e.match(/^[^*!]+\*$/)).map(e=>e.slice(0,-1))}function J(t){return t.filter(e=>e.match(/^\*[^*]+$/)).map(e=>e.slice(1))}function _(t){return t.filter(e=>e.match(/^![^*].*$/)).map(e=>e.slice(1))}function H(t){return t.filter(e=>e.match(/^!\*.+\*$/)).map(e=>e.slice(2,-1))}function X(t){return t.filter(e=>e.match(/^!\*[^*]+$/)).map(e=>e.slice(2))}function G(t){return t.filter(e=>e.match(/^![^*]+\*$/)).map(e=>e.slice(1,-1))}var g={exact:Q,contain:j,startWith:q,endWith:J,notExact:_,notContain:H,notStartWith:X,notEndWith:G};function $(t){let e=t.indexOf("*")>-1,i=e&&t.length===1,r={exact:g.exact(t),contain:g.contain(t),startWith:g.startWith(t),endWith:g.endWith(t),notExact:g.notExact(t),notContain:g.notContain(t),notStartWith:g.notStartWith(t),notEndWith:g.notEndWith(t)};return s=>i?!0:(e||r.exact.indexOf(s)>-1||r.contain.some(n=>s.indexOf(n)>-1)||r.startWith.some(n=>s.indexOf(n)===0)||r.endWith.some(n=>s.indexOf(n)===s.length-n.length))&&!(r.notExact.indexOf(s)>-1||r.notContain.some(n=>s.indexOf(n)>-1)||r.notStartWith.some(n=>s.indexOf(n)===0)||r.notEndWith.some(n=>s.indexOf(n)===s.length-n.length))}function E(t){return typeof t=="string"}function C(t){return typeof t=="function"}function k(t,e){return t.text.trim().toLowerCase().includes(e.toLowerCase())}function K(t){if(!t.parent)return;let e=t.parent.index(t);if(!(e<=0))return t.parent.nodes?.[e-1]}function V(t,e,i,r,s){let n=t.source;if(n?.input?.css){let c=n.input.css.split(`
`),l=(n.start?.line??1)-1;if(l>=0&&l<c.length){let p=c[l];if(p.includes("/*")&&p.toLowerCase().includes(i.toLowerCase()))return!0}}let a=K(t);if(a?.type==="comment"&&k(a,e))return!0;let o=t,u=!1;for(;o?.parent;){let c=o.parent,l=c.index(o);for(let p=l-1;p>=0;p--){let d=c.nodes?.[p];if(d?.type==="comment"){let x=d;if(k(x,s)){u=!1;break}if(k(x,r)){u=!0;break}}}if(u)return!0;o=c}return u}var Y={baseSize:16,precision:5,skipSelectors:[],properties:["*"],replaceOriginal:!0,convertMediaQueries:!1,minValue:0,maxValue:1/0,excludeFiles:null,includeFiles:null,fromUnit:"px",toUnit:"rem",propertyBaseSize:{},disableNextLineComment:"pxtorem-disable-next-line",disableLineComment:"pxtorem-disable-line",disableBlockComment:"pxtorem-disable",enableBlockComment:"pxtorem-enable",convert:null,onConversionComplete:null,verbose:!1};function w(t,e){let i=Math.pow(10,e+1),r=Math.floor(t*i);return Math.round(r/10)*10/i}function Z(t,e,i){return t.some(r=>r.prop===e&&r.value===i)}function ee(t,e){return typeof e!="string"?!1:t.some(i=>typeof i=="string"?e.indexOf(i)!==-1:i.test(e))}function N(t,e){return!e||!t?!1:C(e)?e(t):E(e)?t.indexOf(e)!==-1:e instanceof RegExp?e.test(t):!1}function U(t,e,i,r,s,n,a,o,u,c,l){let p=o[n]??t;return(d,x)=>{if(!x)return d;let b=parseFloat(x);if(b<i||b>r)return c.skipped++,d;if(u){let v=u(b,n,a);if(v===!1)return c.skipped++,d;if(typeof v=="string")return c.converted++,l&&console.log(`[pxtorem-css] ${n}: ${d} \u2192 ${v} (custom)`),v;if(typeof v=="number"){let O=w(v,e);return c.converted++,l&&console.log(`[pxtorem-css] ${n}: ${d} \u2192 ${O}${s} (custom)`),O+s}}let S=w(b/p,e);return c.converted++,l&&console.log(`[pxtorem-css] ${n}: ${d} \u2192 ${S}${s}`),S+s}}function D(t={}){let e={...Y,...t},i=$(e.properties),r=!1,s,n,a={totalDeclarations:0,convertedDeclarations:0,skippedDeclarations:0,filesProcessed:[],details:new Map};return{postcssPlugin:"pxtorem-css",Once(o){n=o.source?.input?.file,e.includeFiles&&n?r=!N(n,e.includeFiles):e.excludeFiles&&n?r=N(n,e.excludeFiles):r=!1,!r&&(n&&!a.filesProcessed.includes(n)&&(a.filesProcessed.push(n),a.details.set(n,{converted:0,skipped:0})),s=C(e.baseSize)?e.baseSize(o.source.input):e.baseSize)},Declaration(o){if(r)return;if(a.totalDeclarations++,o.value.indexOf(e.fromUnit)===-1){a.skippedDeclarations++;return}if(!i(o.prop)){a.skippedDeclarations++;return}let u=o.parent?.type==="rule"?o.parent.selector:void 0;if(ee(e.skipSelectors,u)){a.skippedDeclarations++;return}if(V(o,e.disableNextLineComment,e.disableLineComment,e.disableBlockComment,e.enableBlockComment)){a.skippedDeclarations++,e.verbose&&console.log(`[pxtorem-css] Skipped (disabled): ${o.prop}: ${o.value}`);return}let c=n?a.details.get(n)??{converted:0,skipped:0}:{converted:0,skipped:0},l=h(e.fromUnit),p=U(s,e.precision,e.minValue,e.maxValue,e.toUnit,o.prop,u??"",e.propertyBaseSize,e.convert,c,e.verbose),d=o.value.replace(l,p);n&&a.details.set(n,c),a.convertedDeclarations+=c.converted,a.skippedDeclarations+=c.skipped,d!==o.value&&(o.parent&&Z(o.parent.nodes?.filter(x=>x.type==="decl")||[],o.prop,d)||(e.replaceOriginal?o.value=d:o.cloneAfter({value:d})))},AtRule(o){if(!r&&e.convertMediaQueries&&o.name==="media"){if(o.params.indexOf(e.fromUnit)===-1)return;let u=n?a.details.get(n)??{converted:0,skipped:0}:{converted:0,skipped:0},c=h(e.fromUnit),l=U(s,e.precision,e.minValue,e.maxValue,e.toUnit,"@media","",e.propertyBaseSize,e.convert,u,e.verbose);o.params=o.params.replace(c,l),n&&a.details.set(n,u)}},OnceExit(){e.onConversionComplete&&e.onConversionComplete(a),e.verbose&&(console.log(`
[pxtorem-css] Conversion Report:`),console.log(` Files: ${a.filesProcessed.length}`),console.log(` Total: ${a.totalDeclarations}`),console.log(` Converted: ${a.convertedDeclarations}`),console.log(` Skipped: ${a.skippedDeclarations}
`))}}}D.postcss=!0;var R=D;var te="2.0.0",ne=`
pxtorem-css - Convert px to rem/em/vw/vh in CSS files
Usage:
pxtorem [options] <input>
Options:
-i, --input <path> Input CSS file or directory
-o, --output <path> Output file or directory (default: overwrite input)
-c, --config <path> Path to config file (JSON)
-b, --base-size <n> Base font size (default: 16)
-u, --to-unit <unit> Target unit: rem, em, vw, vh, vmin, vmax, % (default: rem)
-f, --from-unit <unit> Source unit (default: px)
-p, --precision <n> Decimal precision (default: 5)
--properties <list> Comma-separated properties to convert (default: *)
--skip-selectors <list> Comma-separated selectors to skip
--min-value <n> Minimum px value to convert (default: 0)
--max-value <n> Maximum px value to convert (default: Infinity)
--media-queries Convert px in media queries
--no-replace Add rem as fallback instead of replacing
-v, --verbose Show conversion details
-h, --help Show this help message
--version Show version number
Examples:
pxtorem style.css
pxtorem style.css -b 16 -u rem -p 5
pxtorem -i src/styles -o dist/styles
pxtorem style.css --properties "font-size,margin,padding"
pxtorem style.css --skip-selectors "body,.no-convert"
pxtorem style.css --min-value 2 --media-queries
`;function ie(t){let e={},i=0;for(;i<t.length;){let r=t[i];switch(r){case"-i":case"--input":e.input=t[++i];break;case"-o":case"--output":e.output=t[++i];break;case"-c":case"--config":e.config=t[++i];break;case"-b":case"--base-size":e.baseSize=parseFloat(t[++i]);break;case"-u":case"--to-unit":e.toUnit=t[++i];break;case"-p":case"--precision":e.precision=parseInt(t[++i],10);break;case"-f":case"--from-unit":e.fromUnit=t[++i];break;case"--properties":e.properties=t[++i].split(",").map(s=>s.trim());break;case"--skip-selectors":e.skipSelectors=t[++i].split(",").map(s=>s.trim());break;case"--min-value":e.minValue=parseFloat(t[++i]);break;case"--max-value":e.maxValue=parseFloat(t[++i]);break;case"--media-queries":e.convertMediaQueries=!0;break;case"--no-replace":e.replaceOriginal=!1;break;case"-v":case"--verbose":e.verbose=!0;break;case"-h":case"--help":e.help=!0;break;case"--version":e.version=!0;break;default:!r.startsWith("-")&&!e.input?e.input=r:r.startsWith("-")&&(console.error(`Error: Unknown option "${r}"`),console.log("Use --help to see available options."),process.exit(1));break}i++}return e}var W=["rem","em","vw","vh","vmin","vmax","%"];function re(t){let e=[];t.toUnit&&!W.includes(t.toUnit)&&e.push(`Invalid --to-unit "${t.toUnit}". Valid values: ${W.join(", ")}`),t.baseSize!==void 0&&(isNaN(t.baseSize)||t.baseSize<=0)&&e.push("--base-size must be a positive number"),t.precision!==void 0&&(isNaN(t.precision)||t.precision<0||!Number.isInteger(t.precision))&&e.push("--precision must be a non-negative integer"),t.minValue!==void 0&&isNaN(t.minValue)&&e.push("--min-value must be a number"),t.maxValue!==void 0&&isNaN(t.maxValue)&&e.push("--max-value must be a number"),t.minValue!==void 0&&t.maxValue!==void 0&&t.minValue>t.maxValue&&e.push("--min-value cannot be greater than --max-value"),t.config&&!(0,f.existsSync)(t.config)&&e.push(`Config file not found: ${t.config}`),e.length>0&&(console.error("Validation errors:"),e.forEach(i=>console.error(` \u2717 ${i}`)),process.exit(1))}function se(t){try{let e=(0,f.readFileSync)(t,"utf-8");return JSON.parse(e)}catch(e){console.error(`Error loading config file: ${t}`,e),process.exit(1)}}function oe(){let t=["pxtorem.config.json","pxtorem.json",".pxtoremrc.json"];for(let e of t){let i=(0,m.resolve)(process.cwd(),e);if((0,f.existsSync)(i))return i}return null}function P(t){let e=(0,m.resolve)(process.cwd(),t);(0,f.existsSync)(e)||(console.error(`Error: Path not found: ${t}`),process.exit(1));let i=(0,f.statSync)(e);if(i.isFile())return[e];if(i.isDirectory()){let r=[],s=(0,f.readdirSync)(e,{withFileTypes:!0});for(let n of s)n.isFile()&&/\.(css|scss|sass|less)$/.test(n.name)?r.push((0,m.join)(e,n.name)):n.isDirectory()&&r.push(...P((0,m.join)(e,n.name)));return r}return[]}async function ae(t,e,i){let r=(0,f.readFileSync)(t,"utf-8"),s={converted:0,skipped:0},n=await(0,F.default)([R({...i,onConversionComplete:a=>{s={converted:a.convertedDeclarations,skipped:a.skippedDeclarations}}})]).process(r,{from:t,to:e});return(0,f.writeFileSync)(e,n.css),s}async function le(){let t=process.argv.slice(2),e=ie(t);e.version&&(console.log(`pxtorem-css v${te}`),process.exit(0)),(e.help||!e.input)&&(console.log(ne),process.exit(e.help?0:1)),re(e);let i={},r=e.config||oe();r&&(i=se(r),e.verbose&&console.log(`Using config: ${r}`));let s={...i,...e.baseSize!==void 0&&{baseSize:e.baseSize},...e.toUnit!==void 0&&{toUnit:e.toUnit},...e.fromUnit!==void 0&&{fromUnit:e.fromUnit},...e.precision!==void 0&&{precision:e.precision},...e.properties!==void 0&&{properties:e.properties},...e.skipSelectors!==void 0&&{skipSelectors:e.skipSelectors},...e.minValue!==void 0&&{minValue:e.minValue},...e.maxValue!==void 0&&{maxValue:e.maxValue},...e.convertMediaQueries!==void 0&&{convertMediaQueries:e.convertMediaQueries},...e.replaceOriginal!==void 0&&{replaceOriginal:e.replaceOriginal},...e.verbose!==void 0&&{verbose:e.verbose}},n=P(e.input);n.length===0&&(console.error("No CSS files found."),process.exit(1)),console.log(`
Processing ${n.length} file(s)...
`);let a=0,o=0;for(let u of n){let c;if(e.output){let l=(0,m.resolve)(process.cwd(),e.output),p=(0,f.existsSync)(l)&&(0,f.statSync)(l);p&&p.isDirectory()?c=(0,m.join)(l,(0,m.basename)(u)):n.length===1?c=l:c=(0,m.join)(l,(0,m.basename)(u))}else c=u;try{let l=await ae(u,c,s);a+=l.converted,o+=l.skipped;let p=u.replace(process.cwd(),".");console.log(`\u2713 ${p} (${l.converted} converted, ${l.skipped} skipped)`)}catch(l){console.error(`\u2717 ${u}: ${l.message}`)}}console.log(`
Done! Converted: ${a}, Skipped: ${o}
`)}le().catch(t=>{console.error(t),process.exit(1)});
import { Input, Plugin } from 'postcss';
/**
* Supported target units for conversion
*/
type TargetUnit = 'rem' | 'em' | 'vw' | 'vh' | 'vmin' | 'vmax' | '%';
/**
* Conversion report generated after processing
*/
interface ConversionReport {
/** Total number of declarations processed */
totalDeclarations: number;
/** Number of declarations converted */
convertedDeclarations: number;
/** Number of declarations skipped */
skippedDeclarations: number;
/** List of files processed */
filesProcessed: string[];
/** Conversion details per file */
details: Map<string, {
converted: number;
skipped: number;
}>;
}
/**
* Options for the pxtorem-css plugin
*/
interface Options {
/**
* Base font size for conversion calculation
* @default 16
*/
baseSize?: number | ((input: Input) => number);
/**
* Decimal precision for converted values
* @default 5
*/
precision?: number;
/**
* Properties to convert. Supports wildcards and negation.
* - `['*']` - all properties
* - `['font*']` - properties starting with font
* - `['*size']` - properties ending with size
* - `['!border*']` - exclude properties starting with border
* @default ['*']
*/
properties?: string[];
/**
* Selectors to skip. Strings check for containment, RegExp for matches.
* @default []
*/
skipSelectors?: (string | RegExp)[];
/**
* Replace values instead of adding fallbacks
* @default true
*/
replaceOriginal?: boolean;
/**
* Convert px in media queries
* @default false
*/
convertMediaQueries?: boolean;
/**
* Minimum px value to convert. Values below this are skipped.
* @default 0
*/
minValue?: number;
/**
* Maximum px value to convert. Values above this are skipped.
* @default Infinity
*/
maxValue?: number;
/**
* File paths to exclude from conversion
*/
excludeFiles?: string | RegExp | ((file: string) => boolean) | null;
/**
* File paths to include for conversion (overrides excludeFiles)
*/
includeFiles?: string | RegExp | ((file: string) => boolean) | null;
/**
* Source unit to convert from
* @default 'px'
*/
fromUnit?: string;
/**
* Target unit to convert to
* @default 'rem'
*/
toUnit?: TargetUnit;
/**
* Property-specific base sizes. Overrides baseSize for specified properties.
* @example { 'font-size': 14, 'line-height': 20 }
*/
propertyBaseSize?: Record<string, number>;
/**
* Comment pattern to disable conversion for next line
* @default 'pxtorem-disable-next-line'
*/
disableNextLineComment?: string;
/**
* Comment pattern to disable conversion for current line
* @default 'pxtorem-disable-line'
*/
disableLineComment?: string;
/**
* Comment pattern to disable conversion for block
* @default 'pxtorem-disable'
*/
disableBlockComment?: string;
/**
* Comment pattern to re-enable conversion after disable
* @default 'pxtorem-enable'
*/
enableBlockComment?: string;
/**
* Custom conversion function.
* Return a number for calculated value, string for custom output, or false to skip.
* @param pixelValue - The original pixel value
* @param property - The CSS property name
* @param selector - The CSS selector
* @returns Custom value or false to skip
*/
convert?: (pixelValue: number, property: string, selector: string) => number | string | false;
/**
* Callback when processing is complete with conversion report
*/
onConversionComplete?: (report: ConversionReport) => void;
/**
* Log conversion details to console
* @default false
*/
verbose?: boolean;
}
/**
* PostCSS plugin that converts px to rem/em/vw/vh units
*
* @example
* ```js
* import pxtorem from 'pxtorem-css';
*
* postcss([
* pxtorem({
* baseSize: 16,
* properties: ['*'],
* toUnit: 'rem'
* })
* ])
* ```
*/
declare function pxtorem(options?: Options): Plugin;
declare namespace pxtorem {
var postcss: boolean;
}
export { type ConversionReport, type Options, type TargetUnit, pxtorem as default, pxtorem };
import { Input, Plugin } from 'postcss';
/**
* Supported target units for conversion
*/
type TargetUnit = 'rem' | 'em' | 'vw' | 'vh' | 'vmin' | 'vmax' | '%';
/**
* Conversion report generated after processing
*/
interface ConversionReport {
/** Total number of declarations processed */
totalDeclarations: number;
/** Number of declarations converted */
convertedDeclarations: number;
/** Number of declarations skipped */
skippedDeclarations: number;
/** List of files processed */
filesProcessed: string[];
/** Conversion details per file */
details: Map<string, {
converted: number;
skipped: number;
}>;
}
/**
* Options for the pxtorem-css plugin
*/
interface Options {
/**
* Base font size for conversion calculation
* @default 16
*/
baseSize?: number | ((input: Input) => number);
/**
* Decimal precision for converted values
* @default 5
*/
precision?: number;
/**
* Properties to convert. Supports wildcards and negation.
* - `['*']` - all properties
* - `['font*']` - properties starting with font
* - `['*size']` - properties ending with size
* - `['!border*']` - exclude properties starting with border
* @default ['*']
*/
properties?: string[];
/**
* Selectors to skip. Strings check for containment, RegExp for matches.
* @default []
*/
skipSelectors?: (string | RegExp)[];
/**
* Replace values instead of adding fallbacks
* @default true
*/
replaceOriginal?: boolean;
/**
* Convert px in media queries
* @default false
*/
convertMediaQueries?: boolean;
/**
* Minimum px value to convert. Values below this are skipped.
* @default 0
*/
minValue?: number;
/**
* Maximum px value to convert. Values above this are skipped.
* @default Infinity
*/
maxValue?: number;
/**
* File paths to exclude from conversion
*/
excludeFiles?: string | RegExp | ((file: string) => boolean) | null;
/**
* File paths to include for conversion (overrides excludeFiles)
*/
includeFiles?: string | RegExp | ((file: string) => boolean) | null;
/**
* Source unit to convert from
* @default 'px'
*/
fromUnit?: string;
/**
* Target unit to convert to
* @default 'rem'
*/
toUnit?: TargetUnit;
/**
* Property-specific base sizes. Overrides baseSize for specified properties.
* @example { 'font-size': 14, 'line-height': 20 }
*/
propertyBaseSize?: Record<string, number>;
/**
* Comment pattern to disable conversion for next line
* @default 'pxtorem-disable-next-line'
*/
disableNextLineComment?: string;
/**
* Comment pattern to disable conversion for current line
* @default 'pxtorem-disable-line'
*/
disableLineComment?: string;
/**
* Comment pattern to disable conversion for block
* @default 'pxtorem-disable'
*/
disableBlockComment?: string;
/**
* Comment pattern to re-enable conversion after disable
* @default 'pxtorem-enable'
*/
enableBlockComment?: string;
/**
* Custom conversion function.
* Return a number for calculated value, string for custom output, or false to skip.
* @param pixelValue - The original pixel value
* @param property - The CSS property name
* @param selector - The CSS selector
* @returns Custom value or false to skip
*/
convert?: (pixelValue: number, property: string, selector: string) => number | string | false;
/**
* Callback when processing is complete with conversion report
*/
onConversionComplete?: (report: ConversionReport) => void;
/**
* Log conversion details to console
* @default false
*/
verbose?: boolean;
}
/**
* PostCSS plugin that converts px to rem/em/vw/vh units
*
* @example
* ```js
* import pxtorem from 'pxtorem-css';
*
* postcss([
* pxtorem({
* baseSize: 16,
* properties: ['*'],
* toUnit: 'rem'
* })
* ])
* ```
*/
declare function pxtorem(options?: Options): Plugin;
declare namespace pxtorem {
var postcss: boolean;
}
// @ts-ignore
export = pxtorem;
export { type ConversionReport, type Options, type TargetUnit, pxtorem };
"use strict";var h=Object.defineProperty;var N=Object.getOwnPropertyDescriptor;var P=Object.getOwnPropertyNames;var F=Object.prototype.hasOwnProperty;var w=(t,e)=>{for(var l in e)h(t,l,{get:e[l],enumerable:!0})},M=(t,e,l,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of P(e))!F.call(t,o)&&o!==l&&h(t,o,{get:()=>e[o],enumerable:!(r=N(e,o))||r.enumerable});return t};var U=t=>M(h({},"__esModule",{value:!0}),t);var K={};w(K,{default:()=>J,pxtorem:()=>k});module.exports=U(K);function v(t){return new RegExp(`"[^"]+"|'[^']+'|url\\([^)]+\\)|var\\([^)]+\\)|(\\d*\\.?\\d+)${t}`,"g")}function V(t){return t.filter(e=>e.match(/^[^*!]+$/))}function z(t){return t.filter(e=>e.match(/^\*.+\*$/)).map(e=>e.slice(1,-1))}function B(t){return t.filter(e=>e.match(/^[^*!]+\*$/)).map(e=>e.slice(0,-1))}function A(t){return t.filter(e=>e.match(/^\*[^*]+$/)).map(e=>e.slice(1))}function L(t){return t.filter(e=>e.match(/^![^*].*$/)).map(e=>e.slice(1))}function T(t){return t.filter(e=>e.match(/^!\*.+\*$/)).map(e=>e.slice(2,-1))}function I(t){return t.filter(e=>e.match(/^!\*[^*]+$/)).map(e=>e.slice(2))}function Q(t){return t.filter(e=>e.match(/^![^*]+\*$/)).map(e=>e.slice(1,-1))}var p={exact:V,contain:z,startWith:B,endWith:A,notExact:L,notContain:T,notStartWith:I,notEndWith:Q};function $(t){let e=t.indexOf("*")>-1,l=e&&t.length===1,r={exact:p.exact(t),contain:p.contain(t),startWith:p.startWith(t),endWith:p.endWith(t),notExact:p.notExact(t),notContain:p.notContain(t),notStartWith:p.notStartWith(t),notEndWith:p.notEndWith(t)};return o=>l?!0:(e||r.exact.indexOf(o)>-1||r.contain.some(n=>o.indexOf(n)>-1)||r.startWith.some(n=>o.indexOf(n)===0)||r.endWith.some(n=>o.indexOf(n)===o.length-n.length))&&!(r.notExact.indexOf(o)>-1||r.notContain.some(n=>o.indexOf(n)>-1)||r.notStartWith.some(n=>o.indexOf(n)===0)||r.notEndWith.some(n=>o.indexOf(n)===o.length-n.length))}function E(t){return typeof t=="string"}function b(t){return typeof t=="function"}function C(t,e){return t.text.trim().toLowerCase().includes(e.toLowerCase())}function j(t){if(!t.parent)return;let e=t.parent.index(t);if(!(e<=0))return t.parent.nodes?.[e-1]}function O(t,e,l,r,o){let n=t.source;if(n?.input?.css){let a=n.input.css.split(`
`),f=(n.start?.line??1)-1;if(f>=0&&f<a.length){let d=a[f];if(d.includes("/*")&&d.toLowerCase().includes(l.toLowerCase()))return!0}}let s=j(t);if(s?.type==="comment"&&C(s,e))return!0;let i=t,u=!1;for(;i?.parent;){let a=i.parent,f=a.index(i);for(let d=f-1;d>=0;d--){let c=a.nodes?.[d];if(c?.type==="comment"){let m=c;if(C(m,o)){u=!1;break}if(C(m,r)){u=!0;break}}}if(u)return!0;i=a}return u}var q={baseSize:16,precision:5,skipSelectors:[],properties:["*"],replaceOriginal:!0,convertMediaQueries:!1,minValue:0,maxValue:1/0,excludeFiles:null,includeFiles:null,fromUnit:"px",toUnit:"rem",propertyBaseSize:{},disableNextLineComment:"pxtorem-disable-next-line",disableLineComment:"pxtorem-disable-line",disableBlockComment:"pxtorem-disable",enableBlockComment:"pxtorem-enable",convert:null,onConversionComplete:null,verbose:!1};function W(t,e){let l=Math.pow(10,e+1),r=Math.floor(t*l);return Math.round(r/10)*10/l}function G(t,e,l){return t.some(r=>r.prop===e&&r.value===l)}function H(t,e){return typeof e!="string"?!1:t.some(l=>typeof l=="string"?e.indexOf(l)!==-1:l.test(e))}function D(t,e){return!e||!t?!1:b(e)?e(t):E(e)?t.indexOf(e)!==-1:e instanceof RegExp?e.test(t):!1}function y(t,e,l,r,o,n,s,i,u,a,f){let d=i[n]??t;return(c,m)=>{if(!m)return c;let x=parseFloat(m);if(x<l||x>r)return a.skipped++,c;if(u){let g=u(x,n,s);if(g===!1)return a.skipped++,c;if(typeof g=="string")return a.converted++,f&&console.log(`[pxtorem-css] ${n}: ${c} \u2192 ${g} (custom)`),g;if(typeof g=="number"){let R=W(g,e);return a.converted++,f&&console.log(`[pxtorem-css] ${n}: ${c} \u2192 ${R}${o} (custom)`),R+o}}let S=W(x/d,e);return a.converted++,f&&console.log(`[pxtorem-css] ${n}: ${c} \u2192 ${S}${o}`),S+o}}function k(t={}){let e={...q,...t},l=$(e.properties),r=!1,o,n,s={totalDeclarations:0,convertedDeclarations:0,skippedDeclarations:0,filesProcessed:[],details:new Map};return{postcssPlugin:"pxtorem-css",Once(i){n=i.source?.input?.file,e.includeFiles&&n?r=!D(n,e.includeFiles):e.excludeFiles&&n?r=D(n,e.excludeFiles):r=!1,!r&&(n&&!s.filesProcessed.includes(n)&&(s.filesProcessed.push(n),s.details.set(n,{converted:0,skipped:0})),o=b(e.baseSize)?e.baseSize(i.source.input):e.baseSize)},Declaration(i){if(r)return;if(s.totalDeclarations++,i.value.indexOf(e.fromUnit)===-1){s.skippedDeclarations++;return}if(!l(i.prop)){s.skippedDeclarations++;return}let u=i.parent?.type==="rule"?i.parent.selector:void 0;if(H(e.skipSelectors,u)){s.skippedDeclarations++;return}if(O(i,e.disableNextLineComment,e.disableLineComment,e.disableBlockComment,e.enableBlockComment)){s.skippedDeclarations++,e.verbose&&console.log(`[pxtorem-css] Skipped (disabled): ${i.prop}: ${i.value}`);return}let a=n?s.details.get(n)??{converted:0,skipped:0}:{converted:0,skipped:0},f=v(e.fromUnit),d=y(o,e.precision,e.minValue,e.maxValue,e.toUnit,i.prop,u??"",e.propertyBaseSize,e.convert,a,e.verbose),c=i.value.replace(f,d);n&&s.details.set(n,a),s.convertedDeclarations+=a.converted,s.skippedDeclarations+=a.skipped,c!==i.value&&(i.parent&&G(i.parent.nodes?.filter(m=>m.type==="decl")||[],i.prop,c)||(e.replaceOriginal?i.value=c:i.cloneAfter({value:c})))},AtRule(i){if(!r&&e.convertMediaQueries&&i.name==="media"){if(i.params.indexOf(e.fromUnit)===-1)return;let u=n?s.details.get(n)??{converted:0,skipped:0}:{converted:0,skipped:0},a=v(e.fromUnit),f=y(o,e.precision,e.minValue,e.maxValue,e.toUnit,"@media","",e.propertyBaseSize,e.convert,u,e.verbose);i.params=i.params.replace(a,f),n&&s.details.set(n,u)}},OnceExit(){e.onConversionComplete&&e.onConversionComplete(s),e.verbose&&(console.log(`
[pxtorem-css] Conversion Report:`),console.log(` Files: ${s.filesProcessed.length}`),console.log(` Total: ${s.totalDeclarations}`),console.log(` Converted: ${s.convertedDeclarations}`),console.log(` Skipped: ${s.skippedDeclarations}
`))}}}k.postcss=!0;var J=k;0&&(module.exports={pxtorem});
module.exports = module.exports.default;
function h(t){return new RegExp(`"[^"]+"|'[^']+'|url\\([^)]+\\)|var\\([^)]+\\)|(\\d*\\.?\\d+)${t}`,"g")}function y(t){return t.filter(e=>e.match(/^[^*!]+$/))}function N(t){return t.filter(e=>e.match(/^\*.+\*$/)).map(e=>e.slice(1,-1))}function P(t){return t.filter(e=>e.match(/^[^*!]+\*$/)).map(e=>e.slice(0,-1))}function F(t){return t.filter(e=>e.match(/^\*[^*]+$/)).map(e=>e.slice(1))}function w(t){return t.filter(e=>e.match(/^![^*].*$/)).map(e=>e.slice(1))}function M(t){return t.filter(e=>e.match(/^!\*.+\*$/)).map(e=>e.slice(2,-1))}function U(t){return t.filter(e=>e.match(/^!\*[^*]+$/)).map(e=>e.slice(2))}function V(t){return t.filter(e=>e.match(/^![^*]+\*$/)).map(e=>e.slice(1,-1))}var p={exact:y,contain:N,startWith:P,endWith:F,notExact:w,notContain:M,notStartWith:U,notEndWith:V};function S(t){let e=t.indexOf("*")>-1,a=e&&t.length===1,r={exact:p.exact(t),contain:p.contain(t),startWith:p.startWith(t),endWith:p.endWith(t),notExact:p.notExact(t),notContain:p.notContain(t),notStartWith:p.notStartWith(t),notEndWith:p.notEndWith(t)};return s=>a?!0:(e||r.exact.indexOf(s)>-1||r.contain.some(n=>s.indexOf(n)>-1)||r.startWith.some(n=>s.indexOf(n)===0)||r.endWith.some(n=>s.indexOf(n)===s.length-n.length))&&!(r.notExact.indexOf(s)>-1||r.notContain.some(n=>s.indexOf(n)>-1)||r.notStartWith.some(n=>s.indexOf(n)===0)||r.notEndWith.some(n=>s.indexOf(n)===s.length-n.length))}function R(t){return typeof t=="string"}function v(t){return typeof t=="function"}function b(t,e){return t.text.trim().toLowerCase().includes(e.toLowerCase())}function z(t){if(!t.parent)return;let e=t.parent.index(t);if(!(e<=0))return t.parent.nodes?.[e-1]}function $(t,e,a,r,s){let n=t.source;if(n?.input?.css){let l=n.input.css.split(`
`),f=(n.start?.line??1)-1;if(f>=0&&f<l.length){let d=l[f];if(d.includes("/*")&&d.toLowerCase().includes(a.toLowerCase()))return!0}}let o=z(t);if(o?.type==="comment"&&b(o,e))return!0;let i=t,u=!1;for(;i?.parent;){let l=i.parent,f=l.index(i);for(let d=f-1;d>=0;d--){let c=l.nodes?.[d];if(c?.type==="comment"){let m=c;if(b(m,s)){u=!1;break}if(b(m,r)){u=!0;break}}}if(u)return!0;i=l}return u}var B={baseSize:16,precision:5,skipSelectors:[],properties:["*"],replaceOriginal:!0,convertMediaQueries:!1,minValue:0,maxValue:1/0,excludeFiles:null,includeFiles:null,fromUnit:"px",toUnit:"rem",propertyBaseSize:{},disableNextLineComment:"pxtorem-disable-next-line",disableLineComment:"pxtorem-disable-line",disableBlockComment:"pxtorem-disable",enableBlockComment:"pxtorem-enable",convert:null,onConversionComplete:null,verbose:!1};function E(t,e){let a=Math.pow(10,e+1),r=Math.floor(t*a);return Math.round(r/10)*10/a}function A(t,e,a){return t.some(r=>r.prop===e&&r.value===a)}function L(t,e){return typeof e!="string"?!1:t.some(a=>typeof a=="string"?e.indexOf(a)!==-1:a.test(e))}function O(t,e){return!e||!t?!1:v(e)?e(t):R(e)?t.indexOf(e)!==-1:e instanceof RegExp?e.test(t):!1}function W(t,e,a,r,s,n,o,i,u,l,f){let d=i[n]??t;return(c,m)=>{if(!m)return c;let x=parseFloat(m);if(x<a||x>r)return l.skipped++,c;if(u){let g=u(x,n,o);if(g===!1)return l.skipped++,c;if(typeof g=="string")return l.converted++,f&&console.log(`[pxtorem-css] ${n}: ${c} \u2192 ${g} (custom)`),g;if(typeof g=="number"){let k=E(g,e);return l.converted++,f&&console.log(`[pxtorem-css] ${n}: ${c} \u2192 ${k}${s} (custom)`),k+s}}let C=E(x/d,e);return l.converted++,f&&console.log(`[pxtorem-css] ${n}: ${c} \u2192 ${C}${s}`),C+s}}function D(t={}){let e={...B,...t},a=S(e.properties),r=!1,s,n,o={totalDeclarations:0,convertedDeclarations:0,skippedDeclarations:0,filesProcessed:[],details:new Map};return{postcssPlugin:"pxtorem-css",Once(i){n=i.source?.input?.file,e.includeFiles&&n?r=!O(n,e.includeFiles):e.excludeFiles&&n?r=O(n,e.excludeFiles):r=!1,!r&&(n&&!o.filesProcessed.includes(n)&&(o.filesProcessed.push(n),o.details.set(n,{converted:0,skipped:0})),s=v(e.baseSize)?e.baseSize(i.source.input):e.baseSize)},Declaration(i){if(r)return;if(o.totalDeclarations++,i.value.indexOf(e.fromUnit)===-1){o.skippedDeclarations++;return}if(!a(i.prop)){o.skippedDeclarations++;return}let u=i.parent?.type==="rule"?i.parent.selector:void 0;if(L(e.skipSelectors,u)){o.skippedDeclarations++;return}if($(i,e.disableNextLineComment,e.disableLineComment,e.disableBlockComment,e.enableBlockComment)){o.skippedDeclarations++,e.verbose&&console.log(`[pxtorem-css] Skipped (disabled): ${i.prop}: ${i.value}`);return}let l=n?o.details.get(n)??{converted:0,skipped:0}:{converted:0,skipped:0},f=h(e.fromUnit),d=W(s,e.precision,e.minValue,e.maxValue,e.toUnit,i.prop,u??"",e.propertyBaseSize,e.convert,l,e.verbose),c=i.value.replace(f,d);n&&o.details.set(n,l),o.convertedDeclarations+=l.converted,o.skippedDeclarations+=l.skipped,c!==i.value&&(i.parent&&A(i.parent.nodes?.filter(m=>m.type==="decl")||[],i.prop,c)||(e.replaceOriginal?i.value=c:i.cloneAfter({value:c})))},AtRule(i){if(!r&&e.convertMediaQueries&&i.name==="media"){if(i.params.indexOf(e.fromUnit)===-1)return;let u=n?o.details.get(n)??{converted:0,skipped:0}:{converted:0,skipped:0},l=h(e.fromUnit),f=W(s,e.precision,e.minValue,e.maxValue,e.toUnit,"@media","",e.propertyBaseSize,e.convert,u,e.verbose);i.params=i.params.replace(l,f),n&&o.details.set(n,u)}},OnceExit(){e.onConversionComplete&&e.onConversionComplete(o),e.verbose&&(console.log(`
[pxtorem-css] Conversion Report:`),console.log(` Files: ${o.filesProcessed.length}`),console.log(` Total: ${o.totalDeclarations}`),console.log(` Converted: ${o.convertedDeclarations}`),console.log(` Skipped: ${o.skippedDeclarations}
`))}}}D.postcss=!0;var K=D;export{K as default,D as pxtorem};
MIT License
Copyright (c) 2024 Rashed Iqbal
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+69
-28
{
"name": "pxtorem-css",
"version": "1.0.6",
"description": "A nodejs cli that convert css unit px to rem",
"main": "app.js",
"author": "Rashed Iqbal",
"license": "MIT",
"bin": {
"pxtorem": "./bin/pxtorem"
},
"repository": {
"type": "git",
"url": "https://github.com/iqbal-rashed/pxtorem-css"
},
"bugs": {
"url": "https://github.com/iqbal-rashed/pxtorem-css/issues"
},
"keywords": [
"pxtorem",
"css",
"unit",
"converter",
"px",
"rem"
],
"dependencies": {
"chalk": "^4.1.2",
"commander": "^9.3.0",
"ora": "^5.4.1"
"name": "pxtorem-css",
"version": "2.0.1",
"description": "A PostCSS plugin and CLI tool that converts px to rem/em/vw/vh units",
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"bin": {
"pxtorem": "./dist/cli.js"
},
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.js",
"default": "./dist/index.js"
}
},
"files": [
"dist"
],
"scripts": {
"build": "tsup",
"dev": "tsup --watch",
"test": "vitest run",
"test:watch": "vitest",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"format": "prettier --write .",
"format:check": "prettier --check .",
"prepublishOnly": "npm run lint && npm run test && npm run build"
},
"keywords": [
"postcss",
"postcss-plugin",
"css",
"rem",
"em",
"vw",
"vh",
"pixel",
"px",
"pxtorem",
"converter",
"cli"
],
"author": "Rashed Iqbal",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/iqbal-rashed/pxtorem-css"
},
"bugs": {
"url": "https://github.com/iqbal-rashed/pxtorem-css/issues"
},
"peerDependencies": {
"postcss": "^8.0.0"
},
"dependencies": {
"postcss": "^8.4.49"
},
"devDependencies": {
"@eslint/js": "^9.17.0",
"@types/node": "^22.10.2",
"eslint": "^9.17.0",
"prettier": "^3.4.2",
"tsup": "^8.3.5",
"typescript": "^5.7.2",
"typescript-eslint": "^8.18.2",
"vitest": "^2.1.8"
}
}
+279
-57

@@ -1,92 +0,314 @@

# pxtorem-css
### A nodejs cli that convert px to rem in any css file
<h1 align="center">pxtorem-css</h1>
<br>
<p align="center">
<strong>A modern PostCSS plugin & CLI to convert px → rem, em, vw, vh and more</strong>
</p>
<p align="center">
<img src="https://img.shields.io/npm/v/pxtorem-css?style=flat-square&color=blue" alt="npm version" />
<img src="https://img.shields.io/npm/dm/pxtorem-css?style=flat-square&color=green" alt="downloads" />
<img src="https://img.shields.io/npm/l/pxtorem-css?style=flat-square" alt="license" />
<img src="https://img.shields.io/badge/TypeScript-Ready-blue?style=flat-square&logo=typescript" alt="typescript" />
</p>
## Description
---
pxtorem-css is a command line interface tool that converts pixel values to rem values in any CSS file. This tool is built using pure Node.js and comes with several advanced features to help you save time when writing CSS code.
## ✨ Features
Features:
- 🎯 **Multiple Units** — Convert to `rem`, `em`, `vw`, `vh`, `vmin`, `vmax`, `%`
- ⚡ **Fast & Lightweight** — Zero dependencies (except postcss)
- 🔧 **Highly Configurable** — Per-property settings, custom transforms
- 💬 **Comment Control** — Disable conversion with inline comments
- 📊 **Conversion Reports** — Track what was converted
- 🖥️ **CLI Included** — Convert files from command line
- � **TypeScript** — Full type definitions included
- Converts px to rem in CSS files quickly and easily
- Allows you to choose the CSS directory and output directory
- Enables you to include and exclude specific CSS files for conversion
- Allows you to ignore specific CSS attributes that you don't want to convert
- You can customize the tool's options with a pxtorem.config.json file in your project
- Can be installed both locally and globally using npm/
---
## Installation
## 📦 Installation
Locally:
```bash
# npm
npm install pxtorem-css postcss --save-dev
```bash
npm i pxtorem-css
# yarn
yarn add pxtorem-css postcss -D
# pnpm
pnpm add pxtorem-css postcss -D
```
Globally:
---
```bash
npm i -g pxtorem-css
## 🚀 Quick Start
### PostCSS Config
```js
// postcss.config.js
module.exports = {
plugins: [
require('pxtorem-css')({
baseSize: 16,
properties: ['*'],
}),
],
};
```
## Usage
### CLI
```bash
$ pxtorem [options]
# Convert a file
npx pxtorem style.css
Options:
-init,--init [type] Init pxtorem options json (preset: "pxtorem.config.json")
-s, --size [type] Select html size (default: "16", preset: "16")
-d, --dir [type...] Select css directory (default: ["/"], preset: "/")
-t, --type [type] Select css ext type example: .scss (default: ".css", preset: ".css")
-i, --ignore [type...] Ignore css attribute (default: [], preset: [])
-r, --replace [type] For replace file name (default: false, preset: false)
-o, --output [type] Output directory (default: "", preset: "")
-in, --include [type...] For include css file path (default: [], preset: [])
-ex, --exclude [type...] For exclue css file path (default: [], preset: [])
-c, --config [type] For json config file (default: "", preset: "")
-h, --help display help for command
# With options
npx pxtorem style.css -b 16 -u rem --min-value 2
```
---
## 📖 Usage Examples
<details>
<summary><strong>Vite</strong></summary>
```js
// vite.config.js
import { defineConfig } from 'vite';
import pxtorem from 'pxtorem-css';
export default defineConfig({
css: {
postcss: {
plugins: [
pxtorem({
baseSize: 16,
properties: ['*'],
}),
],
},
},
});
```
### Example
</details>
`$ pxtorem` : change all directories css file. <br>
<details>
<summary><strong>Next.js</strong></summary>
`$ pxtorem -d public/css` : change all css file inside public/css dir.<br>
```js
// postcss.config.js
module.exports = {
plugins: {
'pxtorem-css': {
baseSize: 16,
properties: ['*'],
},
},
};
```
`$ pxtorem -d public/css -t .scss` : change all .scss extname file inside public/css dir.<br>
</details>
`$ pxtorem -d public/css -t .scss -o public/remcss` : change all .scss extname file inside public/css dir and write file to public/remcss dir.<br>
<details>
<summary><strong>Webpack</strong></summary>
`$ pxtorem -d public/css -i box-shadow margin-left padding-left` : change all css file inside public/css dir except box-shadow margin-left padding-left attribute px.<br>
```js
// postcss.config.js
module.exports = {
plugins: [
require('pxtorem-css')({
baseSize: 16,
properties: ['*'],
minValue: 2,
}),
require('autoprefixer'),
],
};
```
`$ pxtorem -d public/css -r my/name/rem/.ext` : change all css filename example: style.css to mystylerem.css and you must follow this pattern {your custom text before name}/name/{your custom text after name}/.ext<br>
</details>
`$ pxtorem -c pxtorem.json` : Customize your options with json file in your project folder<br>
<details>
<summary><strong>Node.js Script</strong></summary>
`$ pxtorem -init` : generate pxtorem.config.json (or you can give custom name by passing value after -init) into your project folder<br>
```js
const fs = require('fs');
const postcss = require('postcss');
const pxtorem = require('pxtorem-css');
### pxtorem.json Example
const css = fs.readFileSync('input.css', 'utf8');
```bash
{
"size": "16",
"dir": ["public/css"],
"type": ".css",
"ignore": ["margin", "padding", "box-shadow"],
"replace": "{your custom word}/name/{your custom word}/.ext",
"output": "",
"include": [],
"exclude": []
postcss([pxtorem({ baseSize: 16 })])
.process(css)
.then((result) => {
fs.writeFileSync('output.css', result.css);
});
```
</details>
---
## ⚙️ Options
| Option | Type | Default | Description |
| --------------------- | ---------------------- | ---------- | ---------------------------------------------------------- |
| `baseSize` | `number \| function` | `16` | Base font size for conversion |
| `toUnit` | `string` | `'rem'` | Target unit (`rem`, `em`, `vw`, `vh`, `vmin`, `vmax`, `%`) |
| `fromUnit` | `string` | `'px'` | Source unit to convert |
| `precision` | `number` | `5` | Decimal precision |
| `properties` | `string[]` | `['*']` | Properties to convert (supports wildcards) |
| `skipSelectors` | `(string \| RegExp)[]` | `[]` | Selectors to skip |
| `minValue` | `number` | `0` | Skip values below this |
| `maxValue` | `number` | `Infinity` | Skip values above this |
| `convertMediaQueries` | `boolean` | `false` | Convert in media queries |
| `replaceOriginal` | `boolean` | `true` | Replace vs add fallback |
| `propertyBaseSize` | `object` | `{}` | Per-property base sizes |
| `convert` | `function` | `null` | Custom conversion function |
| `verbose` | `boolean` | `false` | Log conversions |
---
## 🎨 Advanced Examples
### Property Wildcards
```js
pxtorem({
properties: ['font*', '*margin*', '!border*'],
// ✓ font-size, font-weight, margin, margin-top
// ✗ border, border-width
});
```
### Per-Property Base Size
```js
pxtorem({
baseSize: 16,
propertyBaseSize: {
'font-size': 14,
'line-height': 20,
},
});
```
### Custom Transform
```js
pxtorem({
convert: (px, property, selector) => {
// Skip small values
if (px < 4) return false;
// Use CSS variable
if (px === 16) return 'var(--base-size)';
// Round to 0.25rem
return Math.round((px / 16) * 4) / 4;
},
});
```
### Viewport Units (Mobile-First)
```js
pxtorem({
toUnit: 'vw',
baseSize: 3.75, // 375px / 100vw
properties: ['*'],
});
```
---
## 💬 Comment Control
Disable conversion with inline comments:
```css
.element {
font-size: 16px; /* → 1rem */
padding: 20px; /* pxtorem-disable-line */ /* → 20px (skipped) */
/* pxtorem-disable */
margin: 32px; /* → 32px (skipped) */
border: 1px solid; /* → 1px (skipped) */
/* pxtorem-enable */
width: 100px; /* → 6.25rem */
}
```
## Contribution
| Comment | Effect |
| --------------------------------- | -------------------- |
| `/* pxtorem-disable-line */` | Skip current line |
| `/* pxtorem-disable-next-line */` | Skip next line |
| `/* pxtorem-disable */` | Disable until enable |
| `/* pxtorem-enable */` | Re-enable |
If you want to contribute or report any bug, you welcome
---
<br>
Don't forget to give a star 😍
## 🖥️ CLI Reference
```bash
pxtorem [options] <input>
```
| Option | Description |
| ------------------------- | --------------------------------- |
| `-o, --output <path>` | Output file/directory |
| `-b, --base-size <n>` | Base font size |
| `-u, --to-unit <unit>` | Target unit |
| `-p, --precision <n>` | Decimal precision |
| `--properties <list>` | Comma-separated properties |
| `--skip-selectors <list>` | Comma-separated selectors to skip |
| `--min-value <n>` | Min px value |
| `--max-value <n>` | Max px value |
| `--media-queries` | Convert in media queries |
| `--no-replace` | Add fallback instead of replacing |
| `-v, --verbose` | Verbose output |
| `-h, --help` | Show help |
### CLI Examples
```bash
# Basic conversion
pxtorem style.css
# Custom options
pxtorem style.css -b 16 -u rem -p 5 --min-value 2
# Different output
pxtorem -o dist/styles.css src/styles.css
# Directory conversion
pxtorem -o dist/css src/css
# Filter properties
pxtorem style.css --properties "font-size,margin,padding"
```
---
## 📘 TypeScript
```ts
import pxtorem, { Options, ConversionReport, TargetUnit } from 'pxtorem-css';
const options: Options = {
baseSize: 16,
toUnit: 'rem',
onConversionComplete: (report: ConversionReport) => {
console.log(`Converted: ${report.convertedDeclarations}`);
},
};
```
---
## 📄 License
MIT © [Rashed Iqbal](https://github.com/iqbal-rashed)
-156
const chalk = require("chalk");
const fs = require("fs");
const path = require("path");
function getListOfFile(dir, type, fileList) {
let files = fs.readdirSync(dir);
fileList = fileList || [];
files.forEach((f) => {
if (!f.startsWith(".")) {
let filePath = path.join(dir, f);
if (fs.statSync(filePath).isDirectory()) {
fileList = getListOfFile(filePath, type, fileList);
} else {
if (f.endsWith(type)) {
fileList.push(filePath);
}
}
}
});
return fileList;
}
function pxtorem(
{ size, dir, type, ignore, replace, output, include, exclude },
spinner
) {
let finalArr = [];
dir.forEach((v) => {
const finalDir = path.join(process.cwd(), v);
finalArr = finalArr.concat(getListOfFile(finalDir, type));
});
let finalPathArr = finalArr.map((v) => path.resolve(v)) || [];
if (include.length > 0) {
include.forEach((v) => {
if (finalPathArr.indexOf(v) === -1) {
finalPathArr.push(v);
}
});
}
if (exclude.length > 0) {
exclude.forEach((v) => {
if (finalPathArr.indexOf(v) !== -1) {
finalPathArr.splice(finalPathArr.indexOf(v), 1);
}
});
}
if (finalPathArr.length === 0) {
spinner.fail(chalk.red("At the end no css file found"));
process.exit(1);
}
finalPathArr.forEach((v) => {
try {
let fileName = path.basename(v);
if (replace) {
fileName = fileName.replace(
new RegExp(path.extname(v), "g"),
""
);
fileName = replace.replace(new RegExp("/name/", "g"), fileName);
fileName = fileName.replace(
new RegExp("/.ext", "g"),
path.extname(v)
);
console.log(fileName);
}
const readFileData = fs.readFileSync(v, "utf-8");
if (!readFileData) {
throw new Error("Css file empty");
}
if (!size) {
throw new Error("Html size not valid");
}
const changeData = changePxToRem(readFileData, size, ignore);
if (output) {
const destination = path.join(output, fileName);
fs.writeFileSync(destination, changeData, {
encoding: "utf-8",
flag: "w",
});
} else {
const destination = path.join(path.dirname(v), fileName);
fs.writeFileSync(destination, changeData, {
encoding: "utf-8",
flag: "w",
});
}
} catch (error) {
spinner.fail(chalk.red("Something went wrong", error.message));
}
});
}
function changePxToRem(data, size, ignore) {
const myRegex = /[-]?([a-z]*[-])?[a-z]*?\:.*?.*?px(;)?.*/g;
const finalRegex =
/[-]?([a-z]*[-])?[a-z]*?\:.*?([0-9]*[.])?[0-9]*?px+(\s+([0-9]*[.])?[0-9]*?px)*/g;
const attributeValueRegex =
/[-]?([a-z]*[-])?[a-z]*?\:.*?([0-9]*[.])?[0-9]*?px/g;
const valueRegex = /([0-9]*[.])?[0-9]*?px/g;
let result = data.match(finalRegex);
if (!result) {
console.log(chalk.red("Match result not found"));
process.exit(1);
}
let filterResult = [];
if (Array.isArray(ignore) && ignore.length > 0) {
filterResult = result.filter((res) => {
for (let i = 0; i < ignore.length; i++) {
const element = ignore[i];
if (res.includes(element + ":")) {
return res;
}
}
});
}
let finalResult = result.filter((v) => !filterResult.includes(v)) || [];
let valueResult = finalResult.map((v) => {
return v.match(valueRegex);
});
// result.forEach((v) => {
// const pxValue = v.slice(0, -2);
// const valueRegex = new RegExp(`${pxValue}px`, "g");
// finalData = finalData.replace(
// valueRegex,
// `${pxValue / parseFloat(size)}rem`
// );
// });
let finalData = data;
for (let i = 0; i < finalResult.length; i++) {
const element = finalResult[i];
const valueArr = valueResult[i];
let replaceElement = element;
for (let j = 0; j < valueArr.length; j++) {
const value = valueArr[j];
const pxValue = value.slice(0, -2);
replaceElement = replaceElement.replace(
value,
`${parseFloat(pxValue) / parseFloat(size)}rem`
);
}
// console.log(replaceElement);
finalData = finalData.replace(element, replaceElement);
}
return finalData;
}
module.exports = pxtorem;

Sorry, the diff of this file is not supported yet