- Notifications
You must be signed in to change notification settings - Fork0
TypeScript transformer for convert px to rem units of styled-components
License
xuyuanxiang/typescript-styled-components-px2rem
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
TypeScript transformer for convertpx
torem
units ofstyled-components
Usepostcss-plugin-px2rem to process all css text in template strings.
Add a runtime
px2rem
function polyfill to process expression embedded in template strings when enabletransformRuntime option.
Babel plugin with similar functionality:babel-plugin-styled-components-px2rem.
You need to install the followingpeerDependencies
of typescript-styled-components-px2rem into your project at the same time:
{"peerDependencies": {"typescript":"^3.0.0","postcss":"^7.0.0" }}
ttypescript compiler
seeexample
The use of React and styled-componentstest cases.
Integration withrollup-plugin-typescript2 andttypescript:
importtypescript2from'rollup-plugin-typescript2';importttsfrom'ttypescript';exportdefault{// ... other rollup configsplugins:[// ...other rollup pluginstypescript2({typescript:tts,objectHashIgnoreUnknownHack:true,tsconfigOverride:{compilerOptions:{module:'ES2015',plugins:[{transform:'typescript-styled-components-px2rem',rootValue:100,unitPrecision:5,minPixelValue:0,multiplier:1,tags:['styled','css','createGlobalStyle','keyframes'],transformRuntime:false,},],},},}),// ...other rollup plugins],};
Integration withawesome-typescript-loader orts-loader:
constcreateCustomTransformer=require('typescript-styled-components-px2rem').default;constcustomTransformer=createCustomTransformer({rootValue:100,unitPrecision:5,minPixelValue:0,multiplier:1,tags:['styled','css','createGlobalStyle','keyframes'],transformRuntime:false,});module.exports={// ... other webpack configsmodule:{rules:[{test:/\.tsx?$/,// loader: 'awesome-typescript-loader',loader:'ts-loader',// ts-loader or awesome-typescript-loaderoptions:{// ... other loader optionsgetCustomTransformers:()=>({before:[customTransformer]}),},},],},};
Integration withts-jest andttypescript:
jest.config.js:
module.exports={// other jest configsglobals:{'ts-jest':{compiler:'ttypescript',},},};
tsconfig.json:
{"compilerOptions": {"plugins": [ {"transform":"typescript-styled-components-px2rem","type":"config","rootValue":100,"unitPrecision":5,"minPixelValue":0,"multiplier":1,"tags": ["styled","css","createGlobalStyle","keyframes"],"transformRuntime":false } ] }}
It should be put beforetypescript-plugin-styled-components
tsconfig.json:
{"compilerOptions": {"plugins": [ {"transform":"typescript-styled-components-px2rem","type":"config" }, {"transform":"typescript-plugin-styled-components","type":"config" } ] }}
name | type | required | default | description |
---|---|---|---|---|
rootValue | number | false | 100 | The root element font size |
unitPrecision | number | false | 5 | The decimal numbers to allow the REM units to grow to |
minPixelValue | number | false | 0 | Set the minimum pixel value to replace |
multiplier | number | false | 1 | The multiplier of input value |
tags | string[] | false | ["styled", "css", "createGlobalStyle", "keyframes"] | styled-components template literaltagged |
transformRuntime | boolean | false | false | since 1.1.0,enable transformation of all expressions that embedded in template strings |
Simple version of the formula:
constinput='32px';// the value in css textconstpixels=parseFloat(input);if(pixels<minPixelValue){returninput;}constfixedVal=toFixed((pixels*multiplier)/rootValue,unitPrecision);return`${fixedVal}rem`;
Remaining options are consistent withpostcss-plugin-px2rem.
If enabledtransformRuntime
option, all supported expressions embedded in template strings are processed as follows:
Note: Only expression that end withpx
will be processed.
source code:
importstyledfrom'styled-components';exportconstFunctionExpression=styled.button<{width?:number|string}>` width:${function(props){returnprops.width;}}px; /* Block Body */${props=>(props.disabled ?'height: 400px' :'height: 200px')};`;
compiled:
importstyledfrom'styled-components';exportconstFunctionExpression=styled.button` width:${(...args)=>px2rem_1(function(props){returnprops.width;}, ...args)}; /* Block Body */${props=>(props.disabled ?'height: 4rem' :'height: 2rem')};`;functionpx2rem_1(input, ...args){if(typeofinput==='function')returnpx2rem_1(input(...args), ...args);varvalue=parseFloat(input);varpixels=Number.isNaN(value) ?0 :value;if(Math.abs(pixels)<0)return`${pixels}px`;varmultiplier=Math.pow(10,5+1);varwholeNumber=Math.floor(((pixels*1)/100)*multiplier);return`${(Math.round(wholeNumber/10)*10)/multiplier}rem`;}
source code:
importstyledfrom'styled-components';constheight='44';exportconstArrowFunction=styled.input.attrs(props=>({type:'password',size:props.size||'16px',width:props.width||100,}))` color: palevioletred; font-size: 14px; border: 1px solid palevioletred; border-radius: 8px; width:${props=>props.width}px; /* PropertyAccess Body */ height:${()=>height}px; /* Identifier Body */ line-height:${()=>'44'}px; /* StringLiteral Body */ margin:${()=>32}px; /* NumericLiteral Body */ padding:${props=>props.size};`;exportconstArrowFunctionWithBlockBody=styled.button<{width?:number|string}>` width:${props=>{if(props.width){returnprops.width;}else{return0;}}}px; /* Block Body */${props=>(props.disabled ?'height: 400px' :'height: 200px')};`;exportconstArrowFunctionWithBinaryBody=styled.button<{height?:number}>`${props=>props.disabled&&` width: 200px; font-size: 14px; `}; height:${props=>!props.disabled&&props.height}px; /* Binary Body */`;exportconstArrowFunctionWithConditionalBody=styled.button<{height?:number}>` height:${props=>(props.height ?height :100)}px; /* Conditional Body */`;
compiled:
importstyledfrom'styled-components';constheight='44';exportconstArrowFunction=styled.input.attrs(props=>({type:'password',size:props.size||'0.16rem',width:props.width||100,}))` color: palevioletred; font-size: 0.14rem; border: 1px solid palevioletred; border-radius: 0.08rem; width:${props=>px2rem_1(props.width)}; /* PropertyAccess Body */ height:${()=>px2rem_1(height)}; /* Identifier Body */ line-height:${()=>px2rem_1('44')}; /* StringLiteral Body */ margin:${()=>px2rem_1(32)}; /* NumericLiteral Body */ padding:${props=>props.size};`;exportconstArrowFunctionWithBlockBody=styled.button` width:${props=>px2rem_1(()=>{if(props.width){returnprops.width;}else{return0;}})}; /* Block Body */${props=>(props.disabled ?'height: 4rem' :'height: 2rem')};`;exportconstArrowFunctionWithBinaryBody=styled.button`${props=>props.disabled&&` width: 2rem; font-size: 0.14rem; `}; height:${props=>px2rem_1(!props.disabled&&props.height)}; /* Binary Body */`;exportconstArrowFunctionWithConditionalBody=styled.button` height:${props=>(props.height ?px2rem_1(height) :px2rem_1(100))}; /* Conditional Body */`;functionpx2rem_1(input, ...args){if(typeofinput==='function')returnpx2rem_1(input(...args), ...args);varvalue=parseFloat(input);varpixels=Number.isNaN(value) ?0 :value;if(Math.abs(pixels)<0)return`${pixels}px`;varmultiplier=Math.pow(10,5+1);varwholeNumber=Math.floor(((pixels*1)/100)*multiplier);return`${(Math.round(wholeNumber/10)*10)/multiplier}rem`;}
source code:
importstyledfrom'styled-components';exportconstPropertyAccessExpression=styled.button<{width:number;height:string}>(props=>` width:${props.width}px; height:${props.height}; /* Note: Only expression end with 'px' will be processed. */`,);
compiled:
importstyledfrom'styled-components';exportconstPropertyAccessExpression=styled.button(props=>` width:${px2rem_1(props.width)}; height:${props.height}; /* Note: Only expression end with 'px' will be processed. */`,);functionpx2rem_1(input, ...args){if(typeofinput==='function')returnpx2rem_1(input(...args), ...args);varvalue=parseFloat(input);varpixels=Number.isNaN(value) ?0 :value;if(Math.abs(pixels)<0)return`${pixels}px`;varmultiplier=Math.pow(10,5+1);varwholeNumber=Math.floor(((pixels*1)/100)*multiplier);return`${(Math.round(wholeNumber/10)*10)/multiplier}rem`;}
source code:
importReactfrom'react';importstyledfrom'styled-components';exportconstConditionalExpression=function({ fontSize}:{fontSize?:unknown}){constStyledButton=styled.button` font-size:${typeoffontSize==='number' ?fontSize :props=>props?.theme.fontSize}px; `;return<StyledButton/>;};exportconstConditionalExpressionWhenTrue=function({ fontSize}:{fontSize?:unknown}){constStyledButton=styled.button` font-size:${typeoffontSize!=='number' ?props=>props?.theme.fontSize :fontSize}px; `;return<StyledButton/>;};
compiled:
importReactfrom'react';importstyledfrom'styled-components';exportconstConditionalExpression=function({ fontSize}){constStyledButton=styled.button` font-size:${typeoffontSize==='number' ?px2rem_1(fontSize) :props=>px2rem_1(props?.theme.fontSize)}; `;returnReact.createElement(StyledButton,null);};exportconstConditionalExpressionWhenTrue=function({ fontSize}){constStyledButton=styled.button` font-size:${typeoffontSize!=='number' ?props=>px2rem_1(props?.theme.fontSize) :px2rem_1(fontSize)}; `;returnReact.createElement(StyledButton,null);};functionpx2rem_1(input, ...args){if(typeofinput==='function')returnpx2rem_1(input(...args), ...args);varvalue=parseFloat(input);varpixels=Number.isNaN(value) ?0 :value;if(Math.abs(pixels)<0)return`${pixels}px`;varmultiplier=Math.pow(10,5+1);varwholeNumber=Math.floor(((pixels*1)/100)*multiplier);return`${(Math.round(wholeNumber/10)*10)/multiplier}rem`;}
Identifier, CallExpression, BinaryExpression, ...
source code:
importstyled,{css,createGlobalStyle}from'styled-components';constfontSize=18;exportconstGlobalStyle=createGlobalStyle` html body { font-size:${fontSize}px; }`;functiongetHeight(){constheight=100;returnheight/2;}constmixins=css` padding: 0 16px;`;exportconstMixinsButton=styled.button`${mixins}; height:${getHeight()}px;`;constcondition=false;functioncalc(){return20;}exportconstBinaryExpression=styled.button`${condition||` width: 200px; `}; height:${condition||100}px; padding:${40+50}px 8px${4}px 16px; line-height:${calc()-2}px;`;
compiled:
importstyled,{css,createGlobalStyle}from'styled-components';constfontSize=18;exportconstGlobalStyle=createGlobalStyle` html body { font-size:${px2rem_1(fontSize)}; }`;functiongetHeight(){constheight=100;returnheight/2;}constmixins=css` padding: 0 0.16rem;`;exportconstMixinsButton=styled.button`${mixins}; height:${px2rem_1(getHeight())};`;constcondition=false;functioncalc(){return20;}exportconstBinaryExpression=styled.button`${condition||` width: 2rem; `}; height:${px2rem_1(condition||100)}; padding:${px2rem_1(40+50)} 0.08rem${px2rem_1(4)} 0.16rem; line-height:${px2rem_1(calc()-2)};`;functionpx2rem_1(input, ...args){if(typeofinput==='function')returnpx2rem_1(input(...args), ...args);varvalue=parseFloat(input);varpixels=Number.isNaN(value) ?0 :value;if(Math.abs(pixels)<0)return`${pixels}px`;varmultiplier=Math.pow(10,5+1);varwholeNumber=Math.floor(((pixels*1)/100)*multiplier);return`${(Math.round(wholeNumber/10)*10)/multiplier}rem`;}
Maybe you need import some polyfills fromcore-js
only once in your entry file to support outdated user agent like:iOS 7.x
,iOS 8.x
andandroid 4.x
.
import'core-js/es/number/is-nan';import'core-js/es/parse-float';
About
TypeScript transformer for convert px to rem units of styled-components
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Uh oh!
There was an error while loading.Please reload this page.