Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

TypeScript transformer for convert px to rem units of styled-components

License

NotificationsYou must be signed in to change notification settings

xuyuanxiang/typescript-styled-components-px2rem

Repository files navigation

npm versionNPM DownloadsBuild Statuscodecov

TypeScript transformer for convertpx torem units ofstyled-components

  1. Usepostcss-plugin-px2rem to process all css text in template strings.

  2. Add a runtimepx2rem function polyfill to process expression embedded in template strings when enabletransformRuntime option.

Babel plugin with similar functionality:babel-plugin-styled-components-px2rem.

Table of Contents

Requirement

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"  }}

Usage

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      }    ]  }}

Composition

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"      }    ]  }}

Options

nametyperequireddefaultdescription
rootValuenumberfalse100The root element font size
unitPrecisionnumberfalse5The decimal numbers to allow the REM units to grow to
minPixelValuenumberfalse0Set the minimum pixel value to replace
multipliernumberfalse1The multiplier of input value
tagsstring[]false["styled", "css", "createGlobalStyle", "keyframes"]styled-components template literaltagged
transformRuntimebooleanfalsefalsesince 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.

Transform Runtime

If enabledtransformRuntime option, all supported expressions embedded in template strings are processed as follows:

Note: Only expression that end withpx will be processed.

FunctionExpression

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`;}

ArrowFunctionExpression

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`;}

PropertyAccessExpression

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`;}

ConditionalExpression

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`;}

Other Expressions

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`;}

Polyfill

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

Stars

Watchers

Forks

Packages

No packages published

[8]ページ先頭

©2009-2025 Movatter.jp