diff --git a/.github/ISSUE_TEMPLATE/css-issue.yml b/.github/ISSUE_TEMPLATE/css-issue.yml index 9e5322213..1916f6fac 100644 --- a/.github/ISSUE_TEMPLATE/css-issue.yml +++ b/.github/ISSUE_TEMPLATE/css-issue.yml @@ -87,6 +87,8 @@ body: - PostCSS Is Pseudo Class - PostCSS Lab Function - PostCSS Logical + - PostCSS Logical Float and Clear + - PostCSS Logical Resize - PostCSS Logical Viewport Units - PostCSS Media Queries Aspect-Ratio Number Values - PostCSS Media Query Ranges diff --git a/.github/ISSUE_TEMPLATE/plugin-issue.yml b/.github/ISSUE_TEMPLATE/plugin-issue.yml index c3fb620c3..8be051246 100644 --- a/.github/ISSUE_TEMPLATE/plugin-issue.yml +++ b/.github/ISSUE_TEMPLATE/plugin-issue.yml @@ -89,6 +89,8 @@ body: - PostCSS Is Pseudo Class - PostCSS Lab Function - PostCSS Logical + - PostCSS Logical Float and Clear + - PostCSS Logical Resize - PostCSS Logical Viewport Units - PostCSS Media Queries Aspect-Ratio Number Values - PostCSS Media Query Ranges diff --git a/.github/labeler.yml b/.github/labeler.yml index c762356b6..324126e82 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -136,6 +136,14 @@ - plugins/postcss-logical/** - experimental/postcss-logical/** +"plugins/postcss-logical-float-and-clear": + - plugins/postcss-logical-float-and-clear/** + - experimental/postcss-logical-float-and-clear/** + +"plugins/postcss-logical-resize": + - plugins/postcss-logical-resize/** + - experimental/postcss-logical-resize/** + "plugins/postcss-logical-viewport-units": - plugins/postcss-logical-viewport-units/** - experimental/postcss-logical-viewport-units/** diff --git a/cli/csstools-cli/CHANGELOG.md b/cli/csstools-cli/CHANGELOG.md index 1f2f27648..776da5d71 100644 --- a/cli/csstools-cli/CHANGELOG.md +++ b/cli/csstools-cli/CHANGELOG.md @@ -5,6 +5,9 @@ - Updated: Support for Node v14+ (major). - Remove `postcss-env-function` (breaking). - Remove `importFrom` and `exportTo` plugin options (breaking). +- Added `@csstools/postcss-logical-float-and-clear` +- Added `@csstools/postcss-logical-resize` +- Added `@csstools/postcss-logical-viewport-units` ### 1.4.0 (June 3, 2022) diff --git a/cli/csstools-cli/dist/cli.cjs b/cli/csstools-cli/dist/cli.cjs index 0d6c333b5..a36cfaf02 100755 --- a/cli/csstools-cli/dist/cli.cjs +++ b/cli/csstools-cli/dist/cli.cjs @@ -1,3 +1,3 @@ #!/usr/bin/env node -"use strict";var s,e=require("css-blank-pseudo"),o=require("postcss"),t=require("fs"),r=require("path"),i=require("css-has-pseudo"),c=require("css-prefers-color-scheme"),n=require("postcss-attribute-case-insensitive"),l=require("@csstools/postcss-cascade-layers"),p=require("@csstools/postcss-color-function"),a=require("postcss-color-functional-notation"),u=require("postcss-color-hex-alpha"),d=require("postcss-color-rebeccapurple"),g=require("postcss-custom-media"),S=require("postcss-custom-properties"),f=require("postcss-custom-selectors"),v=require("postcss-dir-pseudo-class"),h=require("postcss-double-position-gradients"),m=require("postcss-focus-visible"),w=require("postcss-focus-within"),C=require("@csstools/postcss-font-format-keywords"),b=require("postcss-gap-properties"),y=require("@csstools/postcss-hwb-function"),P=require("@csstools/postcss-ic-unit"),L=require("postcss-image-set-function"),x=require("@csstools/postcss-is-pseudo-class"),T=require("postcss-lab-function"),q=require("postcss-logical"),k=require("postcss-nesting"),I=require("@csstools/postcss-normalize-display-values"),M=require("@csstools/postcss-oklab-function"),O=require("postcss-overflow-shorthand"),F=require("postcss-place"),N=require("postcss-preset-env"),A=require("postcss-pseudo-class-any-link"),D=require("postcss-selector-not"),$=require("@csstools/postcss-stepped-value-functions"),j=require("@csstools/postcss-trigonometric-functions"),V=require("@csstools/postcss-unset-value");function parseArguments(e,o,t){const r=e.map((s=>s.trim())).filter((s=>!!s)),i={stdin:!1,stdout:!1,output:null,outputDir:null,inputs:[],inlineMap:!0,externalMap:!1,replace:!1,pluginOptions:{},debug:!1};let c=null,n=!1;for(let e=0;e1&&i.output)return console.warn('[error] omit "--output" when processing multiple inputs\n'),t(),s.InvalidArguments;0===i.inputs.length&&(i.stdin=!0),i.output||i.outputDir||i.replace||(i.stdout=!0),i.stdout&&(i.externalMap=!1);let l={};if(c)try{l=JSON.parse(c)}catch(e){return console.warn("[error] plugin options must be valid JSON\n"),t(),s.InvalidArguments}for(const e in l){const r=l[e];if(!o.includes(e))return console.warn(`[error] unknown plugin option: ${e}\n`),t(),s.InvalidArguments;i.pluginOptions[e]=r}return i}async function getStdin(){return new Promise((s=>{let e="",o=!1;if(setTimeout((()=>{o=!0,s("")}),1e4),process.stdin.isTTY){if(o)return;s(e)}else process.stdin.setEncoding("utf8"),process.stdin.on("readable",(()=>{let s;for(;s=process.stdin.read();)e+=s})),process.stdin.on("end",(()=>{o||s(e)}))}))}async function stdinToStdout(s,e,t){let r="";try{const i=await getStdin();i||(t(),process.exit(1));const c=await o([s]).process(i,{from:"stdin",to:"stdout",map:!!e.inlineMap&&{inline:!0}});c.warnings().forEach((s=>{console.warn(s.toString())})),r=c.css}catch(s){console.error(e.debug?s:s.message),process.exit(1)}process.stdout.write(r+(e.inlineMap?"\n":"")),process.exit(0)}async function stdinToFs(s,e,i){let c=e.output;!c&&e.outputDir&&(c=r.join(e.outputDir,"output.css"));try{const r=await getStdin();r||(i(),process.exit(1));const n=await o([s]).process(r,{from:"stdin",to:c,map:!(!e.inlineMap&&!e.externalMap)&&{inline:e.inlineMap}});n.warnings().forEach((s=>{console.warn(s.toString())})),e.externalMap&&n.map?await Promise.all([await t.promises.writeFile(c,n.css+(e.inlineMap?"\n":"")),await t.promises.writeFile(`${c}.map`,n.map.toString())]):await t.promises.writeFile(c,n.css+(e.inlineMap?"\n":""))}catch(s){console.error(e.debug?s:s.message),process.exit(1)}console.log(`CSS was written to "${r.normalize(c)}"`),process.exit(0)}async function fsToStdout(s,e){let r=[];try{r=await Promise.all(e.inputs.map((async e=>{const r=await t.promises.readFile(e),i=await o([s]).process(r,{from:e,to:"stdout",map:!1});return i.warnings().forEach((s=>{console.warn(s.toString())})),i.css})))}catch(s){console.error(e.debug?s:s.message),process.exit(1)}for(const s of r)process.stdout.write(s);process.exit(0)}async function fsToFs(s,e){try{await Promise.all(e.inputs.map((async i=>{let c=e.output;e.outputDir&&(c=r.join(e.outputDir,r.basename(i))),e.replace&&(c=i);const n=await t.promises.readFile(i),l=await o([s]).process(n,{from:i,to:c,map:!(!e.inlineMap&&!e.externalMap)&&{inline:e.inlineMap}});l.warnings().forEach((s=>{console.warn(s.toString())})),e.externalMap&&l.map?await Promise.all([await t.promises.writeFile(c,l.css+(e.inlineMap?"\n":"")),await t.promises.writeFile(`${c}.map`,l.map.toString())]):await t.promises.writeFile(c,l.css+(e.inlineMap?"\n":"")),console.log(`CSS was written to "${r.normalize(c)}"`)})))}catch(s){console.error(e.debug?s:s.message),process.exit(1)}process.exit(0)}function helpTextLogger(s,e,o,t=null){let r=[];if(t){const s=Math.max(...Object.keys(t).map((s=>s.length))),e=new Array(s).fill(" ").join("");e.length&&(r=["\nPlugin Options:",...Object.keys(t).map((s=>` ${(s+e).slice(0,e.length)} ${typeof t[s]}`))],r.push(`\n ${JSON.stringify(t,null,2).split("\n").join("\n ")}`))}const i=[`${e}\n`,` ${o}\n`,"Usage:",` ${s} [input.css] [OPTIONS] [-o|--output output.css]`,` ${s} ... [OPTIONS] --dir `,` ${s} ... [OPTIONS] --replace`,"\nOptions:"," -o, --output Output file"," -d, --dir Output directory"," -r, --replace Replace (overwrite) the input file"," -m, --map Create an external sourcemap"," --no-map Disable the default inline sourcemaps"," -p, --plugin-options Stringified JSON object with plugin options"];return r.length>0&&i.push(...r),()=>{console.warn(i.join("\n"))}}async function cli(e,o,t,r=!0){const i=parseArguments(process.argv.slice(r?2:3),o,t);i===s.InvalidArguments&&process.exit(1);const c=e(i.pluginOptions);i.stdin&&i.stdout?await stdinToStdout(c,i,t):i.stdin?await stdinToFs(c,i,t):i.stdout?await fsToStdout(c,i):await fsToFs(c,i)}!function(s){s.InvalidArguments="INVALID_ARGUMENTS"}(s||(s={})),function main(){switch(process.argv[2]??!1){case"css-blank-pseudo":return void cli(e,["preserve","replaceWith"],helpTextLogger("@csstools/cli css-blank-pseudo","PostCSS Blank Pseudo","Lets you style form elements when they are empty, following the Selectors Level 4 specification.",{preserve:!0,replaceWith:".css-blank"}),!1);case"css-has-pseudo":return void cli(i,["preserve"],helpTextLogger("@csstools/cli css-has-pseudo","PostCSS Has Pseudo","Transforms CSS with :has {}",{preserve:!0}),!1);case"css-prefers-color-scheme":return void cli(c,["preserve","mediaQuery"],helpTextLogger("@csstools/cli css-prefers-color-scheme","Prefers Color Scheme","Lets you use light and dark color schemes in all browsers, following the Media Queries specification.",{preserve:!0,mediaQuery:"color|color-index"}),!1);case"postcss-attribute-case-insensitive":return void cli(n,[],helpTextLogger("@csstools/cli postcss-attribute-case-insensitive","PostCSS Attribute Case Insensitive","Enables support for Case Insensitive Attribute matching in selectors"),!1);case"postcss-cascade-layers":return void cli(l,[],helpTextLogger("@csstools/cli postcss-cascade-layers","PostCSS Cascade Layers","Lets you use `@layer` following the Cascade Layers Specification."),!1);case"postcss-color-function":return void cli(p,["preserve","enableProgressiveCustomProperties"],helpTextLogger("@csstools/cli postcss-color-function","PostCSS Color Function","Lets you use the color() function in CSS.",{preserve:!0,enableProgressiveCustomProperties:!1}),!1);case"postcss-color-functional-notation":return void cli(a,["preserve"],helpTextLogger("@csstools/cli postcss-color-functional-notation","PostCSS Color Functional Notation","Lets you use space and slash separated color notation in CSS, following the CSS Color specification.",{preserve:!0}),!1);case"postcss-color-hex-alpha":return void cli(u,["preserve"],helpTextLogger("@csstools/cli postcss-color-hex-alpha","PostCSS Color Hex Alpha","Lets you use 4 & 8 character hex color notation in CSS, following the CSS Color Module specification.",{preserve:!0}),!1);case"postcss-color-rebeccapurple":return void cli(d,["preserve"],helpTextLogger("@csstools/cli postcss-color-rebeccapurple","PostCSS RebeccaPurple","Lets you use the rebeccapurple color keyword in CSS.",{preserve:!0}),!1);case"postcss-custom-media":return void cli(g,["preserve"],helpTextLogger("@csstools/cli postcss-custom-media","PostCSS Custom Media","Lets you define @custom-media in CSS following the Custom Media Specification",{preserve:!0}),!1);case"postcss-custom-properties":return void cli(S,["preserve"],helpTextLogger("@csstools/cli postcss-custom-properties","PostCSS Custom Properties","Lets you use Custom Properties in CSS, following the CSS Custom Properties specification.",{preserve:!0}),!1);case"postcss-custom-selectors":return void cli(f,["preserve"],helpTextLogger("@csstools/cli postcss-custom-selectors","PostCSS Custom Selectors","Lets you define @custom-selector in CSS following the Custom Selectors Specification",{preserve:!0}),!1);case"postcss-dir-pseudo-class":return void cli(v,["dir","preserve","shadow"],helpTextLogger("@csstools/cli postcss-dir-pseudo-class","PostCSS Dir Pseudo Class","Lets you style by directionality using the `:dir()` pseudo-class in CSS",{dir:"ltr",preserve:!0,shadow:!0}),!1);case"postcss-double-position-gradients":return void cli(h,["preserve","enableProgressiveCustomProperties"],helpTextLogger("@csstools/cli postcss-double-position-gradients","PostCSS Double Position Gradients","Lets you use double-position gradients in CSS, following the CSS Image Values and Replaced Content specification",{preserve:!0,enableProgressiveCustomProperties:!1}),!1);case"postcss-focus-visible":return void cli(m,["preserve","replaceWith"],helpTextLogger("@csstools/cli postcss-focus-visible","PostCSS Focus Visible","Lets you use the `:focus-visible` pseudo-class in CSS, following the Selectors Level 4 specification.",{preserve:!0,replaceWith:".focus-visible"}),!1);case"postcss-focus-within":return void cli(w,["preserve","replaceWith"],helpTextLogger("@csstools/cli postcss-focus-within","PostCSS Focus Within","Lets you use the `:focus-within` pseudo-class in CSS, following the Selectors Level 4 specification.",{preserve:!0,replaceWith:".focus-within"}),!1);case"postcss-font-format-keywords":return void cli(C,["preserve"],helpTextLogger("@csstools/cli postcss-font-format-keywords","PostCSS Font Format Keyword","Lets you use unquoted format on @font-face CSS definitions.",{preserve:!0}),!1);case"postcss-gap-properties":return void cli(b,["preserve"],helpTextLogger("@csstools/cli postcss-gap-properties","PostCSS Gap Properties","Lets you use the gap, column-gap, and row-gap shorthand properties in CSS, following the CSS Grid Layout specification.",{preserve:!0}),!1);case"postcss-hwb-function":return void cli(y,["preserve"],helpTextLogger("@csstools/cli postcss-hwb-function","PostCSS HWB function","Convert hwb() to rgb()",{preserve:!0}),!1);case"postcss-ic-unit":return void cli(P,["preserve","enableProgressiveCustomProperties"],helpTextLogger("@csstools/cli postcss-ic-unit","PostCSS IC Unit","Lets you use the ic length unit.",{preserve:!0,enableProgressiveCustomProperties:!1}),!1);case"postcss-image-set-function":return void cli(L,["oninvalid","preserve"],helpTextLogger("@csstools/cli postcss-image-set-function","PostCSS Image Set Function","Lets you display resolution-dependent images using the image-set() function in CSS, following the CSS Images specification.",{preserve:!0,oninvalid:"ignore|warn|throw"}),!1);case"postcss-is-pseudo-class":return void cli(x,["onComplexSelector","preserve","specificityMatchingName"],helpTextLogger("@csstools/cli postcss-is-pseudo-class","PostCSS Is Pseudo Class","Lets you use the :is pseudo class function, following the CSS Selector specification.",{onComplexSelector:"warning",preserve:!0,specificityMatchingName:"does-not-exist"}),!1);case"postcss-lab-function":return void cli(T,["preserve","enableProgressiveCustomProperties","subFeatures"],helpTextLogger("@csstools/cli postcss-lab-function","PostCSS Lab function","Convert lab() to rgb()",{preserve:!0,enableProgressiveCustomProperties:!1,subFeatures:{displayP3:!1}}),!1);case"postcss-logical":return void cli(q,["dir","preserve"],helpTextLogger("@csstools/cli postcss-logical","PostCSS Logical","Lets you use logical, rather than physical, direction and dimension mappings in CSS, following the CSS Logical Properties and Values specification.",{dir:"ltr|rtl",preserve:!0}),!1);case"postcss-nesting":return void cli(k,["noIsPseudoSelector"],helpTextLogger("@csstools/cli postcss-nesting","PostCSS Nesting","Lets you nest style rules inside each other, following the CSS Nesting specification.",{noIsPseudoSelector:!0}),!1);case"postcss-normalize-display-values":return void cli(I,["preserve"],helpTextLogger("@csstools/cli postcss-normalize-display-values","PostCSS Normalize Display Values","Lets you use two values display syntax for inner and outer display types.",{preserve:!0}),!1);case"postcss-oklab-function":return void cli(M,["preserve","enableProgressiveCustomProperties","subFeatures"],helpTextLogger("@csstools/cli postcss-oklab-function","PostCSS OKLab Function","Lets you use oklab() and oklch() color functions in CSS.",{preserve:!0,enableProgressiveCustomProperties:!1,subFeatures:{displayP3:!1}}),!1);case"postcss-overflow-shorthand":return void cli(O,["preserve"],helpTextLogger("@csstools/cli postcss-overflow-shorthand","PostCSS Overflow Shorthand","Lets you use the `overflow` shorthand in CSS, following the CSS Overflow specification.",{preserve:!0}),!1);case"postcss-place":return void cli(F,["preserve"],helpTextLogger("@csstools/cli postcss-place","PostCSS Place","Lets you use place-* properties as shorthands for align-* and justify-*, following the CSS Box Alignment specification.",{preserve:!0}),!1);case"postcss-preset-env":return void cli(N,["stage","minimumVendorImplementations","features","browsers","autoprefixer","preserve","enableClientSidePolyfills","debug"],helpTextLogger("@csstools/cli postcss-preset-env","PostCSS Preset Env","Lets you convert modern CSS into something most browsers can understand, determining the polyfills you need based on your targeted browsers or runtime environments.",{stage:0,minimumVendorImplementations:2,features:{"blank-pseudo-class":{preserve:!1},"color-functional-notation":{preserve:!0}},browsers:"last 2 versions",autoprefixer:{grid:!0},preserve:!1,enableClientSidePolyfills:!1,debug:!1}),!1);case"postcss-pseudo-class-any-link":return void cli(A,["preserve"],helpTextLogger("@csstools/cli postcss-pseudo-class-any-link","PostCSS Pseudo Class Any Link","Lets you :any-link pseudo-class in CSS, following the Selectors specification.",{preserve:!0}),!1);case"postcss-selector-not":return void cli(D,[],helpTextLogger("@csstools/cli postcss-selector-not","PostCSS Selector Not","Transforms :not() W3C CSS level 4 pseudo classes to :not() CSS level 3 selectors following the Selectors 4 Specification"),!1);case"postcss-stepped-value-functions":return void cli($,["preserve","onInvalid"],helpTextLogger("@csstools/cli postcss-stepped-value-functions","PostCSS Stepped Value Functions","Lets you use round(), mod() and rem() functions.",{preserve:!1,onInvalid:"warn"}),!1);case"postcss-trigonometric-functions":return void cli(j,["preserve"],helpTextLogger("@csstools/cli postcss-trigonometric-functions","PostCSS Trigonometric Functions","Lets you use `sin`, `cos`, `tan`, `asin`, `acos`, `atan` and `atan2` to be able to compute trigonometric relationships following the CSS Values 4 specification.",{preserve:!0}),!1);case"postcss-unset-value":return void cli(V,["preserve"],helpTextLogger("@csstools/cli postcss-unset-value","PostCSS Stepped Unset Value","Use the unset keyword in CSS.",{preserve:!1}),!1);default:{const s=["CSSTools CLI\n"," Transform CSS with any plugin from https://github.com/csstools/postcss-plugins\n","Usage:"," @csstools/csstools-cli postcss-preset-env [input.css] [OPTIONS] [-o|--output output.css]"," @csstools/csstools-cli postcss-preset-env ... [OPTIONS] --dir "," @csstools/csstools-cli postcss-preset-env ... [OPTIONS] --replace","\nAvailable Plugins:"," css-blank-pseudo"," css-has-pseudo"," css-prefers-color-scheme"," postcss-attribute-case-insensitive"," postcss-cascade-layers"," postcss-color-function"," postcss-color-functional-notation"," postcss-color-hex-alpha"," postcss-color-rebeccapurple"," postcss-custom-media"," postcss-custom-properties"," postcss-custom-selectors"," postcss-dir-pseudo-class"," postcss-double-position-gradients"," postcss-env-function"," postcss-focus-visible"," postcss-focus-within"," postcss-font-format-keywords"," postcss-gap-properties"," postcss-hwb-function"," postcss-ic-unit"," postcss-image-set-function"," postcss-is-pseudo-class"," postcss-lab-function"," postcss-logical"," postcss-nesting"," postcss-normalize-display-values"," postcss-oklab-function"," postcss-overflow-shorthand"," postcss-place"," postcss-pseudo-class-any-link"," postcss-selector-not"," postcss-stepped-value-functions"," postcss-trigonometric-functions"," postcss-unset-value","\nPlugin Help:"," @csstools/csstools-cli "," @csstools/csstools-cli postcss-preset-env"];console.warn(s.join("\n"))}}}(); +"use strict";var s,e=require("css-blank-pseudo"),o=require("postcss"),t=require("fs"),i=require("path"),r=require("css-has-pseudo"),c=require("css-prefers-color-scheme"),n=require("postcss-attribute-case-insensitive"),l=require("@csstools/postcss-cascade-layers"),a=require("@csstools/postcss-color-function"),p=require("postcss-color-functional-notation"),u=require("postcss-color-hex-alpha"),d=require("postcss-color-rebeccapurple"),g=require("postcss-custom-media"),S=require("postcss-custom-properties"),f=require("postcss-custom-selectors"),v=require("postcss-dir-pseudo-class"),h=require("postcss-double-position-gradients"),m=require("postcss-focus-visible"),w=require("postcss-focus-within"),C=require("@csstools/postcss-font-format-keywords"),b=require("postcss-gap-properties"),y=require("@csstools/postcss-hwb-function"),P=require("@csstools/postcss-ic-unit"),L=require("postcss-image-set-function"),x=require("@csstools/postcss-is-pseudo-class"),T=require("postcss-lab-function"),q=require("postcss-logical"),k=require("@csstools/postcss-logical-float-and-clear"),M=require("@csstools/postcss-logical-resize"),I=require("@csstools/postcss-logical-viewport-units"),O=require("postcss-nesting"),F=require("@csstools/postcss-normalize-display-values"),D=require("@csstools/postcss-oklab-function"),A=require("postcss-overflow-shorthand"),N=require("postcss-place"),V=require("postcss-preset-env"),$=require("postcss-pseudo-class-any-link"),z=require("postcss-selector-not"),j=require("@csstools/postcss-stepped-value-functions"),W=require("@csstools/postcss-trigonometric-functions"),E=require("@csstools/postcss-unset-value");function parseArguments(e,o,t){const i=e.map((s=>s.trim())).filter((s=>!!s)),r={stdin:!1,stdout:!1,output:null,outputDir:null,inputs:[],inlineMap:!0,externalMap:!1,replace:!1,pluginOptions:{},debug:!1};let c=null,n=!1;for(let e=0;e1&&r.output)return console.warn('[error] omit "--output" when processing multiple inputs\n'),t(),s.InvalidArguments;0===r.inputs.length&&(r.stdin=!0),r.output||r.outputDir||r.replace||(r.stdout=!0),r.stdout&&(r.externalMap=!1);let l={};if(c)try{l=JSON.parse(c)}catch(e){return console.warn("[error] plugin options must be valid JSON\n"),t(),s.InvalidArguments}for(const e in l){const i=l[e];if(!o.includes(e))return console.warn(`[error] unknown plugin option: ${e}\n`),t(),s.InvalidArguments;r.pluginOptions[e]=i}return r}async function getStdin(){return new Promise((s=>{let e="",o=!1;if(setTimeout((()=>{o=!0,s("")}),1e4),process.stdin.isTTY){if(o)return;s(e)}else process.stdin.setEncoding("utf8"),process.stdin.on("readable",(()=>{let s;for(;s=process.stdin.read();)e+=s})),process.stdin.on("end",(()=>{o||s(e)}))}))}async function stdinToStdout(s,e,t){let i="";try{const r=await getStdin();r||(t(),process.exit(1));const c=await o([s]).process(r,{from:"stdin",to:"stdout",map:!!e.inlineMap&&{inline:!0}});c.warnings().forEach((s=>{console.warn(s.toString())})),i=c.css}catch(s){console.error(e.debug?s:s.message),process.exit(1)}process.stdout.write(i+(e.inlineMap?"\n":"")),process.exit(0)}async function stdinToFs(s,e,r){let c=e.output;!c&&e.outputDir&&(c=i.join(e.outputDir,"output.css"));try{const i=await getStdin();i||(r(),process.exit(1));const n=await o([s]).process(i,{from:"stdin",to:c,map:!(!e.inlineMap&&!e.externalMap)&&{inline:e.inlineMap}});n.warnings().forEach((s=>{console.warn(s.toString())})),e.externalMap&&n.map?await Promise.all([await t.promises.writeFile(c,n.css+(e.inlineMap?"\n":"")),await t.promises.writeFile(`${c}.map`,n.map.toString())]):await t.promises.writeFile(c,n.css+(e.inlineMap?"\n":""))}catch(s){console.error(e.debug?s:s.message),process.exit(1)}console.log(`CSS was written to "${i.normalize(c)}"`),process.exit(0)}async function fsToStdout(s,e){let i=[];try{i=await Promise.all(e.inputs.map((async e=>{const i=await t.promises.readFile(e),r=await o([s]).process(i,{from:e,to:"stdout",map:!1});return r.warnings().forEach((s=>{console.warn(s.toString())})),r.css})))}catch(s){console.error(e.debug?s:s.message),process.exit(1)}for(const s of i)process.stdout.write(s);process.exit(0)}async function fsToFs(s,e){try{await Promise.all(e.inputs.map((async r=>{let c=e.output;e.outputDir&&(c=i.join(e.outputDir,i.basename(r))),e.replace&&(c=r);const n=await t.promises.readFile(r),l=await o([s]).process(n,{from:r,to:c,map:!(!e.inlineMap&&!e.externalMap)&&{inline:e.inlineMap}});l.warnings().forEach((s=>{console.warn(s.toString())})),e.externalMap&&l.map?await Promise.all([await t.promises.writeFile(c,l.css+(e.inlineMap?"\n":"")),await t.promises.writeFile(`${c}.map`,l.map.toString())]):await t.promises.writeFile(c,l.css+(e.inlineMap?"\n":"")),console.log(`CSS was written to "${i.normalize(c)}"`)})))}catch(s){console.error(e.debug?s:s.message),process.exit(1)}process.exit(0)}function helpTextLogger(s,e,o,t=null){let i=[];if(t){const s=Math.max(...Object.keys(t).map((s=>s.length))),e=new Array(s).fill(" ").join("");e.length&&(i=["\nPlugin Options:",...Object.keys(t).map((s=>` ${(s+e).slice(0,e.length)} ${typeof t[s]}`))],i.push(`\n ${JSON.stringify(t,null,2).split("\n").join("\n ")}`))}const r=[`${e}\n`,` ${o}\n`,"Usage:",` ${s} [input.css] [OPTIONS] [-o|--output output.css]`,` ${s} ... [OPTIONS] --dir `,` ${s} ... [OPTIONS] --replace`,"\nOptions:"," -o, --output Output file"," -d, --dir Output directory"," -r, --replace Replace (overwrite) the input file"," -m, --map Create an external sourcemap"," --no-map Disable the default inline sourcemaps"," -p, --plugin-options Stringified JSON object with plugin options"];return i.length>0&&r.push(...i),()=>{console.warn(r.join("\n"))}}async function cli(e,o,t,i=!0){const r=parseArguments(process.argv.slice(i?2:3),o,t);r===s.InvalidArguments&&process.exit(1);const c=e(r.pluginOptions);r.stdin&&r.stdout?await stdinToStdout(c,r,t):r.stdin?await stdinToFs(c,r,t):r.stdout?await fsToStdout(c,r):await fsToFs(c,r)}!function(s){s.InvalidArguments="INVALID_ARGUMENTS"}(s||(s={})),function main(){switch(process.argv[2]??!1){case"css-blank-pseudo":return void cli(e,["preserve","replaceWith"],helpTextLogger("@csstools/cli css-blank-pseudo","PostCSS Blank Pseudo","Lets you style form elements when they are empty, following the Selectors Level 4 specification.",{preserve:!0,replaceWith:".css-blank"}),!1);case"css-has-pseudo":return void cli(r,["preserve"],helpTextLogger("@csstools/cli css-has-pseudo","PostCSS Has Pseudo","Transforms CSS with :has {}",{preserve:!0}),!1);case"css-prefers-color-scheme":return void cli(c,["preserve","mediaQuery"],helpTextLogger("@csstools/cli css-prefers-color-scheme","Prefers Color Scheme","Lets you use light and dark color schemes in all browsers, following the Media Queries specification.",{preserve:!0,mediaQuery:"color|color-index"}),!1);case"postcss-attribute-case-insensitive":return void cli(n,[],helpTextLogger("@csstools/cli postcss-attribute-case-insensitive","PostCSS Attribute Case Insensitive","Enables support for Case Insensitive Attribute matching in selectors"),!1);case"postcss-cascade-layers":return void cli(l,[],helpTextLogger("@csstools/cli postcss-cascade-layers","PostCSS Cascade Layers","Lets you use `@layer` following the Cascade Layers Specification."),!1);case"postcss-color-function":return void cli(a,["preserve","enableProgressiveCustomProperties"],helpTextLogger("@csstools/cli postcss-color-function","PostCSS Color Function","Lets you use the color() function in CSS.",{preserve:!0,enableProgressiveCustomProperties:!1}),!1);case"postcss-color-functional-notation":return void cli(p,["preserve"],helpTextLogger("@csstools/cli postcss-color-functional-notation","PostCSS Color Functional Notation","Lets you use space and slash separated color notation in CSS, following the CSS Color specification.",{preserve:!0}),!1);case"postcss-color-hex-alpha":return void cli(u,["preserve"],helpTextLogger("@csstools/cli postcss-color-hex-alpha","PostCSS Color Hex Alpha","Lets you use 4 & 8 character hex color notation in CSS, following the CSS Color Module specification.",{preserve:!0}),!1);case"postcss-color-rebeccapurple":return void cli(d,["preserve"],helpTextLogger("@csstools/cli postcss-color-rebeccapurple","PostCSS RebeccaPurple","Lets you use the rebeccapurple color keyword in CSS.",{preserve:!0}),!1);case"postcss-custom-media":return void cli(g,["preserve"],helpTextLogger("@csstools/cli postcss-custom-media","PostCSS Custom Media","Lets you define @custom-media in CSS following the Custom Media Specification",{preserve:!0}),!1);case"postcss-custom-properties":return void cli(S,["preserve"],helpTextLogger("@csstools/cli postcss-custom-properties","PostCSS Custom Properties","Lets you use Custom Properties in CSS, following the CSS Custom Properties specification.",{preserve:!0}),!1);case"postcss-custom-selectors":return void cli(f,["preserve"],helpTextLogger("@csstools/cli postcss-custom-selectors","PostCSS Custom Selectors","Lets you define @custom-selector in CSS following the Custom Selectors Specification",{preserve:!0}),!1);case"postcss-dir-pseudo-class":return void cli(v,["dir","preserve","shadow"],helpTextLogger("@csstools/cli postcss-dir-pseudo-class","PostCSS Dir Pseudo Class","Lets you style by directionality using the `:dir()` pseudo-class in CSS",{dir:"ltr",preserve:!0,shadow:!0}),!1);case"postcss-double-position-gradients":return void cli(h,["preserve","enableProgressiveCustomProperties"],helpTextLogger("@csstools/cli postcss-double-position-gradients","PostCSS Double Position Gradients","Lets you use double-position gradients in CSS, following the CSS Image Values and Replaced Content specification",{preserve:!0,enableProgressiveCustomProperties:!1}),!1);case"postcss-focus-visible":return void cli(m,["preserve","replaceWith"],helpTextLogger("@csstools/cli postcss-focus-visible","PostCSS Focus Visible","Lets you use the `:focus-visible` pseudo-class in CSS, following the Selectors Level 4 specification.",{preserve:!0,replaceWith:".focus-visible"}),!1);case"postcss-focus-within":return void cli(w,["preserve","replaceWith"],helpTextLogger("@csstools/cli postcss-focus-within","PostCSS Focus Within","Lets you use the `:focus-within` pseudo-class in CSS, following the Selectors Level 4 specification.",{preserve:!0,replaceWith:".focus-within"}),!1);case"postcss-font-format-keywords":return void cli(C,["preserve"],helpTextLogger("@csstools/cli postcss-font-format-keywords","PostCSS Font Format Keyword","Lets you use unquoted format on @font-face CSS definitions.",{preserve:!0}),!1);case"postcss-gap-properties":return void cli(b,["preserve"],helpTextLogger("@csstools/cli postcss-gap-properties","PostCSS Gap Properties","Lets you use the gap, column-gap, and row-gap shorthand properties in CSS, following the CSS Grid Layout specification.",{preserve:!0}),!1);case"postcss-hwb-function":return void cli(y,["preserve"],helpTextLogger("@csstools/cli postcss-hwb-function","PostCSS HWB function","Convert hwb() to rgb()",{preserve:!0}),!1);case"postcss-ic-unit":return void cli(P,["preserve","enableProgressiveCustomProperties"],helpTextLogger("@csstools/cli postcss-ic-unit","PostCSS IC Unit","Lets you use the ic length unit.",{preserve:!0,enableProgressiveCustomProperties:!1}),!1);case"postcss-image-set-function":return void cli(L,["oninvalid","preserve"],helpTextLogger("@csstools/cli postcss-image-set-function","PostCSS Image Set Function","Lets you display resolution-dependent images using the image-set() function in CSS, following the CSS Images specification.",{preserve:!0,oninvalid:"ignore|warn|throw"}),!1);case"postcss-is-pseudo-class":return void cli(x,["onComplexSelector","preserve","specificityMatchingName"],helpTextLogger("@csstools/cli postcss-is-pseudo-class","PostCSS Is Pseudo Class","Lets you use the :is pseudo class function, following the CSS Selector specification.",{onComplexSelector:"warning",preserve:!0,specificityMatchingName:"does-not-exist"}),!1);case"postcss-lab-function":return void cli(T,["preserve","enableProgressiveCustomProperties","subFeatures"],helpTextLogger("@csstools/cli postcss-lab-function","PostCSS Lab function","Convert lab() to rgb()",{preserve:!0,enableProgressiveCustomProperties:!1,subFeatures:{displayP3:!1}}),!1);case"postcss-logical":return void cli(q,["inlineDirection","blockDirection"],helpTextLogger("@csstools/cli postcss-logical","PostCSS Logical","Lets you use logical, rather than physical, direction and dimension mappings in CSS, following the CSS Logical Properties and Values specification.",{inlineDirection:"left-to-right",blockDirection:"top-to-bottom"}),!1);case"postcss-logical-float-and-clear":return void cli(k,["inlineDirection","blockDirection"],helpTextLogger("@csstools/cli postcss-logical-float-and-clear","PostCSS Logical Float And Clear","Lets you use flow-relative (inline-start and inline-end) values for float and clear, following the CSS Logical Properties and Values specification.",{inlineDirection:"left-to-right"}),!1);case"postcss-logical-resize":return void cli(M,["inlineDirection"],helpTextLogger("@csstools/cli postcss-logical-resize","PostCSS Logical Resize","Lets you use logical values in the resize property, following the CSS Logical Properties and Values specification.",{inlineDirection:"left-to-right"}),!1);case"postcss-logical-viewport-units":return void cli(I,["inlineDirection","preserve"],helpTextLogger("@csstools/cli postcss-viewport-units","PostCSS Logical Viewport Units","Lets you use vb and vi length units in CSS, following the CSS Values and Units Module Level 4 specification.",{inlineDirection:"left-to-right",preserve:!0}),!1);case"postcss-nesting":return void cli(O,["noIsPseudoSelector"],helpTextLogger("@csstools/cli postcss-nesting","PostCSS Nesting","Lets you nest style rules inside each other, following the CSS Nesting specification.",{noIsPseudoSelector:!0}),!1);case"postcss-normalize-display-values":return void cli(F,["preserve"],helpTextLogger("@csstools/cli postcss-normalize-display-values","PostCSS Normalize Display Values","Lets you use two values display syntax for inner and outer display types.",{preserve:!0}),!1);case"postcss-oklab-function":return void cli(D,["preserve","enableProgressiveCustomProperties","subFeatures"],helpTextLogger("@csstools/cli postcss-oklab-function","PostCSS OKLab Function","Lets you use oklab() and oklch() color functions in CSS.",{preserve:!0,enableProgressiveCustomProperties:!1,subFeatures:{displayP3:!1}}),!1);case"postcss-overflow-shorthand":return void cli(A,["preserve"],helpTextLogger("@csstools/cli postcss-overflow-shorthand","PostCSS Overflow Shorthand","Lets you use the `overflow` shorthand in CSS, following the CSS Overflow specification.",{preserve:!0}),!1);case"postcss-place":return void cli(N,["preserve"],helpTextLogger("@csstools/cli postcss-place","PostCSS Place","Lets you use place-* properties as shorthands for align-* and justify-*, following the CSS Box Alignment specification.",{preserve:!0}),!1);case"postcss-preset-env":return void cli(V,["stage","minimumVendorImplementations","features","browsers","autoprefixer","preserve","enableClientSidePolyfills","debug"],helpTextLogger("@csstools/cli postcss-preset-env","PostCSS Preset Env","Lets you convert modern CSS into something most browsers can understand, determining the polyfills you need based on your targeted browsers or runtime environments.",{stage:0,minimumVendorImplementations:2,features:{"blank-pseudo-class":{preserve:!1},"color-functional-notation":{preserve:!0}},browsers:"last 2 versions",autoprefixer:{grid:!0},preserve:!1,enableClientSidePolyfills:!1,debug:!1}),!1);case"postcss-pseudo-class-any-link":return void cli($,["preserve"],helpTextLogger("@csstools/cli postcss-pseudo-class-any-link","PostCSS Pseudo Class Any Link","Lets you :any-link pseudo-class in CSS, following the Selectors specification.",{preserve:!0}),!1);case"postcss-selector-not":return void cli(z,[],helpTextLogger("@csstools/cli postcss-selector-not","PostCSS Selector Not","Transforms :not() W3C CSS level 4 pseudo classes to :not() CSS level 3 selectors following the Selectors 4 Specification"),!1);case"postcss-stepped-value-functions":return void cli(j,["preserve","onInvalid"],helpTextLogger("@csstools/cli postcss-stepped-value-functions","PostCSS Stepped Value Functions","Lets you use round(), mod() and rem() functions.",{preserve:!1,onInvalid:"warn"}),!1);case"postcss-trigonometric-functions":return void cli(W,["preserve"],helpTextLogger("@csstools/cli postcss-trigonometric-functions","PostCSS Trigonometric Functions","Lets you use `sin`, `cos`, `tan`, `asin`, `acos`, `atan` and `atan2` to be able to compute trigonometric relationships following the CSS Values 4 specification.",{preserve:!0}),!1);case"postcss-unset-value":return void cli(E,["preserve"],helpTextLogger("@csstools/cli postcss-unset-value","PostCSS Stepped Unset Value","Use the unset keyword in CSS.",{preserve:!1}),!1);default:{const s=["CSSTools CLI\n"," Transform CSS with any plugin from https://github.com/csstools/postcss-plugins\n","Usage:"," @csstools/csstools-cli postcss-preset-env [input.css] [OPTIONS] [-o|--output output.css]"," @csstools/csstools-cli postcss-preset-env ... [OPTIONS] --dir "," @csstools/csstools-cli postcss-preset-env ... [OPTIONS] --replace","\nAvailable Plugins:"," css-blank-pseudo"," css-has-pseudo"," css-prefers-color-scheme"," postcss-attribute-case-insensitive"," postcss-cascade-layers"," postcss-color-function"," postcss-color-functional-notation"," postcss-color-hex-alpha"," postcss-color-rebeccapurple"," postcss-custom-media"," postcss-custom-properties"," postcss-custom-selectors"," postcss-dir-pseudo-class"," postcss-double-position-gradients"," postcss-env-function"," postcss-focus-visible"," postcss-focus-within"," postcss-font-format-keywords"," postcss-gap-properties"," postcss-hwb-function"," postcss-ic-unit"," postcss-image-set-function"," postcss-is-pseudo-class"," postcss-lab-function"," postcss-logical"," postcss-nesting"," postcss-normalize-display-values"," postcss-oklab-function"," postcss-overflow-shorthand"," postcss-place"," postcss-pseudo-class-any-link"," postcss-selector-not"," postcss-stepped-value-functions"," postcss-trigonometric-functions"," postcss-unset-value","\nPlugin Help:"," @csstools/csstools-cli "," @csstools/csstools-cli postcss-preset-env"];console.warn(s.join("\n"))}}}(); diff --git a/cli/csstools-cli/package.json b/cli/csstools-cli/package.json index d7a24f810..68ed14fbd 100644 --- a/cli/csstools-cli/package.json +++ b/cli/csstools-cli/package.json @@ -38,6 +38,9 @@ "@csstools/postcss-hwb-function": "^1.0.1", "@csstools/postcss-ic-unit": "^1.0.0", "@csstools/postcss-is-pseudo-class": "^2.0.4", + "@csstools/postcss-logical-float-and-clear": "^1.0.0", + "@csstools/postcss-logical-resize": "^1.0.0", + "@csstools/postcss-logical-viewport-units": "^1.0.0", "@csstools/postcss-normalize-display-values": "^1.0.0", "@csstools/postcss-oklab-function": "^1.1.0", "@csstools/postcss-stepped-value-functions": "^1.0.0", diff --git a/cli/csstools-cli/src/cli.ts b/cli/csstools-cli/src/cli.ts index 0a485dd8e..9b1bc251c 100644 --- a/cli/csstools-cli/src/cli.ts +++ b/cli/csstools-cli/src/cli.ts @@ -22,6 +22,9 @@ import postcssImageSetFunction from './plugins/postcss-image-set-function'; import postcssIsPseudoClass from './plugins/postcss-is-pseudo-class'; import postcssLabFunction from './plugins/postcss-lab-function'; import postcssLogical from './plugins/postcss-logical'; +import postcssLogicalFloatAndClear from './plugins/postcss-logical-float-and-clear'; +import postcssLogicalResize from './plugins/postcss-logical-resize'; +import postcssLogicalViewportUnits from './plugins/postcss-logical-viewport-units'; import postcssNesting from './plugins/postcss-nesting'; import postcssNormalizeDisplayValues from './plugins/postcss-normalize-display-values'; import postcssOKLabFunction from './plugins/postcss-oklab-function'; @@ -109,6 +112,15 @@ function main() { case 'postcss-logical': postcssLogical(); return; + case 'postcss-logical-float-and-clear': + postcssLogicalFloatAndClear(); + return; + case 'postcss-logical-resize': + postcssLogicalResize(); + return; + case 'postcss-logical-viewport-units': + postcssLogicalViewportUnits(); + return; case 'postcss-nesting': postcssNesting(); return; diff --git a/cli/csstools-cli/src/plugins/postcss-logical-float-and-clear.ts b/cli/csstools-cli/src/plugins/postcss-logical-float-and-clear.ts new file mode 100644 index 000000000..9255a67de --- /dev/null +++ b/cli/csstools-cli/src/plugins/postcss-logical-float-and-clear.ts @@ -0,0 +1,18 @@ +import plugin from '@csstools/postcss-logical-float-and-clear'; +import { cli, helpTextLogger } from '@csstools/base-cli'; + +export default function postcssLogical() { + cli( + plugin, + ['inlineDirection', 'blockDirection'], + helpTextLogger( + '@csstools/cli postcss-logical-float-and-clear', + 'PostCSS Logical Float And Clear', + 'Lets you use flow-relative (inline-start and inline-end) values for float and clear, following the CSS Logical Properties and Values specification.', + { + inlineDirection: 'left-to-right', + }, + ), + false, + ); +} diff --git a/cli/csstools-cli/src/plugins/postcss-logical-resize.ts b/cli/csstools-cli/src/plugins/postcss-logical-resize.ts new file mode 100644 index 000000000..9b056dc07 --- /dev/null +++ b/cli/csstools-cli/src/plugins/postcss-logical-resize.ts @@ -0,0 +1,18 @@ +import plugin from '@csstools/postcss-logical-resize'; +import { cli, helpTextLogger } from '@csstools/base-cli'; + +export default function postcssLogicalResize() { + cli( + plugin, + ['inlineDirection'], + helpTextLogger( + '@csstools/cli postcss-logical-resize', + 'PostCSS Logical Resize', + 'Lets you use logical values in the resize property, following the CSS Logical Properties and Values specification.', + { + inlineDirection: 'left-to-right', + }, + ), + false, + ); +} diff --git a/cli/csstools-cli/src/plugins/postcss-logical-viewport-units.ts b/cli/csstools-cli/src/plugins/postcss-logical-viewport-units.ts new file mode 100644 index 000000000..6aaf05af6 --- /dev/null +++ b/cli/csstools-cli/src/plugins/postcss-logical-viewport-units.ts @@ -0,0 +1,19 @@ +import plugin from '@csstools/postcss-logical-viewport-units'; +import { cli, helpTextLogger } from '@csstools/base-cli'; + +export default function postcssLogicalViewportUnits() { + cli( + plugin, + ['inlineDirection', 'preserve'], + helpTextLogger( + '@csstools/cli postcss-viewport-units', + 'PostCSS Logical Viewport Units', + 'Lets you use vb and vi length units in CSS, following the CSS Values and Units Module Level 4 specification.', + { + inlineDirection: 'left-to-right', + preserve: true, + }, + ), + false, + ); +} diff --git a/cli/csstools-cli/src/plugins/postcss-logical.ts b/cli/csstools-cli/src/plugins/postcss-logical.ts index b8a33aa14..489941d5a 100644 --- a/cli/csstools-cli/src/plugins/postcss-logical.ts +++ b/cli/csstools-cli/src/plugins/postcss-logical.ts @@ -4,14 +4,14 @@ import { cli, helpTextLogger } from '@csstools/base-cli'; export default function postcssLogical() { cli( plugin, - ['dir', 'preserve'], + ['inlineDirection', 'blockDirection'], helpTextLogger( '@csstools/cli postcss-logical', 'PostCSS Logical', 'Lets you use logical, rather than physical, direction and dimension mappings in CSS, following the CSS Logical Properties and Values specification.', { - dir: 'ltr|rtl', - preserve: true, + inlineDirection: 'left-to-right', + blockDirection: 'top-to-bottom', }, ), false, diff --git a/package-lock.json b/package-lock.json index edd3b39c4..6a2c315c1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -51,6 +51,9 @@ "@csstools/postcss-hwb-function": "^1.0.1", "@csstools/postcss-ic-unit": "^1.0.0", "@csstools/postcss-is-pseudo-class": "^2.0.4", + "@csstools/postcss-logical-float-and-clear": "^1.0.0", + "@csstools/postcss-logical-resize": "^1.0.0", + "@csstools/postcss-logical-viewport-units": "^1.0.0", "@csstools/postcss-normalize-display-values": "^1.0.0", "@csstools/postcss-oklab-function": "^1.1.0", "@csstools/postcss-stepped-value-functions": "^1.0.0", @@ -1888,6 +1891,14 @@ "resolved": "plugins/postcss-is-pseudo-class", "link": true }, + "node_modules/@csstools/postcss-logical-float-and-clear": { + "resolved": "plugins/postcss-logical-float-and-clear", + "link": true + }, + "node_modules/@csstools/postcss-logical-resize": { + "resolved": "plugins/postcss-logical-resize", + "link": true + }, "node_modules/@csstools/postcss-logical-viewport-units": { "resolved": "plugins/postcss-logical-viewport-units", "link": true @@ -7110,6 +7121,9 @@ "@csstools/postcss-hwb-function": "^1.0.2", "@csstools/postcss-ic-unit": "^1.0.1", "@csstools/postcss-is-pseudo-class": "^2.0.7", + "@csstools/postcss-logical-float-and-clear": "^1.0.0", + "@csstools/postcss-logical-resize": "^1.0.0", + "@csstools/postcss-logical-viewport-units": "^1.0.0", "@csstools/postcss-media-queries-aspect-ratio-number-values": "^1.0.0", "@csstools/postcss-nested-calc": "^1.0.0", "@csstools/postcss-normalize-display-values": "^1.0.1", @@ -7131,7 +7145,7 @@ "postcss-color-functional-notation": "^4.2.4", "postcss-color-hex-alpha": "^8.0.4", "postcss-color-rebeccapurple": "^7.1.1", - "postcss-custom-media": "^9.0.0", + "postcss-custom-media": "^9.0.1", "postcss-custom-properties": "^13.0.0", "postcss-custom-selectors": "^7.0.0", "postcss-dir-pseudo-class": "^6.0.5", @@ -7146,7 +7160,7 @@ "postcss-logical": "^5.0.4", "postcss-media-minmax": "^5.0.0", "postcss-nesting": "^10.2.0", - "postcss-opacity-percentage": "^1.1.2", + "postcss-opacity-percentage": "^1.1.3", "postcss-overflow-shorthand": "^3.0.4", "postcss-page-break": "^3.0.4", "postcss-place": "^7.0.5", @@ -7156,7 +7170,7 @@ "postcss-value-parser": "^4.2.0" }, "devDependencies": { - "postcss-simple-vars": "^7.0.0" + "postcss-simple-vars": "^7.0.1" }, "engines": { "node": "^14 || ^16 || >=18" @@ -7717,6 +7731,42 @@ "plugins/postcss-logical": { "version": "5.0.4", "license": "CC0-1.0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "plugins/postcss-logical-float-and-clear": { + "name": "@csstools/postcss-logical-float-and-clear", + "version": "1.0.0", + "license": "CC0-1.0", + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "plugins/postcss-logical-resize": { + "name": "@csstools/postcss-logical-resize", + "version": "1.0.0", + "license": "CC0-1.0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, "engines": { "node": "^14 || ^16 || >=18" }, @@ -9215,6 +9265,9 @@ "@csstools/postcss-hwb-function": "^1.0.1", "@csstools/postcss-ic-unit": "^1.0.0", "@csstools/postcss-is-pseudo-class": "^2.0.4", + "@csstools/postcss-logical-float-and-clear": "^1.0.0", + "@csstools/postcss-logical-resize": "^1.0.0", + "@csstools/postcss-logical-viewport-units": "^1.0.0", "@csstools/postcss-normalize-display-values": "^1.0.0", "@csstools/postcss-oklab-function": "^1.1.0", "@csstools/postcss-stepped-value-functions": "^1.0.0", @@ -9334,6 +9387,16 @@ "puppeteer": "^19.5.2" } }, + "@csstools/postcss-logical-float-and-clear": { + "version": "file:plugins/postcss-logical-float-and-clear", + "requires": {} + }, + "@csstools/postcss-logical-resize": { + "version": "file:plugins/postcss-logical-resize", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, "@csstools/postcss-logical-viewport-units": { "version": "file:plugins/postcss-logical-viewport-units", "requires": { @@ -12074,7 +12137,9 @@ }, "postcss-logical": { "version": "file:plugins/postcss-logical", - "requires": {} + "requires": { + "postcss-value-parser": "^4.2.0" + } }, "postcss-media-minmax": { "version": "5.0.0", @@ -12131,6 +12196,9 @@ "@csstools/postcss-hwb-function": "^1.0.2", "@csstools/postcss-ic-unit": "^1.0.1", "@csstools/postcss-is-pseudo-class": "^2.0.7", + "@csstools/postcss-logical-float-and-clear": "^1.0.0", + "@csstools/postcss-logical-resize": "^1.0.0", + "@csstools/postcss-logical-viewport-units": "^1.0.0", "@csstools/postcss-media-queries-aspect-ratio-number-values": "^1.0.0", "@csstools/postcss-nested-calc": "^1.0.0", "@csstools/postcss-normalize-display-values": "^1.0.1", @@ -12152,7 +12220,7 @@ "postcss-color-functional-notation": "^4.2.4", "postcss-color-hex-alpha": "^8.0.4", "postcss-color-rebeccapurple": "^7.1.1", - "postcss-custom-media": "^9.0.0", + "postcss-custom-media": "^9.0.1", "postcss-custom-properties": "^13.0.0", "postcss-custom-selectors": "^7.0.0", "postcss-dir-pseudo-class": "^6.0.5", @@ -12167,14 +12235,14 @@ "postcss-logical": "^5.0.4", "postcss-media-minmax": "^5.0.0", "postcss-nesting": "^10.2.0", - "postcss-opacity-percentage": "^1.1.2", + "postcss-opacity-percentage": "^1.1.3", "postcss-overflow-shorthand": "^3.0.4", "postcss-page-break": "^3.0.4", "postcss-place": "^7.0.5", "postcss-pseudo-class-any-link": "^7.1.6", "postcss-replace-overflow-wrap": "^4.0.0", "postcss-selector-not": "^6.0.1", - "postcss-simple-vars": "^7.0.0", + "postcss-simple-vars": "^7.0.1", "postcss-value-parser": "^4.2.0" } }, diff --git a/plugin-packs/postcss-preset-env/.tape.mjs b/plugin-packs/postcss-preset-env/.tape.mjs index c17472043..5af350916 100644 --- a/plugin-packs/postcss-preset-env/.tape.mjs +++ b/plugin-packs/postcss-preset-env/.tape.mjs @@ -167,6 +167,15 @@ postcssTape(plugin)({ browsers: '> 0%' }, }, + 'basic:hebrew': { + message: 'supports { logical: { inlineDirection: "right-to-left" }, stage: 0, browsers: "> 0%" } usage', + options: { + stage: 0, + logical: { + inlineDirection: 'right-to-left' + } + }, + }, 'layers-basic': { message: 'supports layers usage', options: { @@ -268,9 +277,6 @@ postcssTape(plugin)({ message: 'supports { insertBefore } usage when looking for source', options: { stage: 0, - features: { - 'lab-function': true - }, features: { 'lab-function': true, 'color-function': false, @@ -288,9 +294,6 @@ postcssTape(plugin)({ message: 'supports { insertBefore } usage when looking for a result', options: { stage: 0, - features: { - 'lab-function': true - }, features: { 'lab-function': true, 'color-function': false, diff --git a/plugin-packs/postcss-preset-env/CHANGELOG.md b/plugin-packs/postcss-preset-env/CHANGELOG.md index 5ed3fe8ed..62e927355 100644 --- a/plugin-packs/postcss-preset-env/CHANGELOG.md +++ b/plugin-packs/postcss-preset-env/CHANGELOG.md @@ -4,7 +4,12 @@ - Added: TypeScript support. - Added `@csstools/postcss-media-queries-aspect-ratio-number-values` [Check the plugin README](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-media-queries-aspect-ratio-number-values#readme) for usage details. +- Added `@csstools/postcss-logical-float-and-clear` [Check the plugin README](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-logical-float-and-clear#readme) for usage details. +- Added `@csstools/postcss-logical-resize` [Check the plugin README](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-logical-resize#readme) for usage details. +- Added `@csstools/postcss-logical-viewport-units` [Check the plugin README](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-logical-viewport-units#readme) for usage details. +- Added `logical` option to control all logical plugins. - Fixed: `all-property` and `overflow-wrap-property` now follow the `preserve` plugin option +- Removed a workaround to consider `blank-pseudo-class` and `prefers-color-scheme-query` as `stage: 1` features when using default options. ### (8.0.0-alpha.1) (November 14, 2022) diff --git a/plugin-packs/postcss-preset-env/FEATURES.md b/plugin-packs/postcss-preset-env/FEATURES.md index 93010581d..d4a842bf0 100644 --- a/plugin-packs/postcss-preset-env/FEATURES.md +++ b/plugin-packs/postcss-preset-env/FEATURES.md @@ -19,6 +19,7 @@ The `ID` listed is the key for PostCSS Preset Env configuration in your project. | `dir-pseudo-class` | `:dir` Directionality Pseudo-Class | [example](https://preset-env.cssdb.org/features/#dir-pseudo-class) | [docs](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-dir-pseudo-class#readme) | | `display-two-values` | Two values syntax for `display` | [example](https://preset-env.cssdb.org/features/#display-two-values) | [docs](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-normalize-display-values#readme) | | `double-position-gradients` | Double Position Gradients | [example](https://preset-env.cssdb.org/features/#double-position-gradients) | [docs](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-double-position-gradients#readme) | +| `float-clear-logical-values` | Logical Values in float and clear | [example](https://preset-env.cssdb.org/features/#float-clear-logical-values) | [docs](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-logical#readme) | | `focus-visible-pseudo-class` | `:focus-visible` Focus-Indicated Pseudo-Class | [example](https://preset-env.cssdb.org/features/#focus-visible-pseudo-class) | [docs](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-focus-visible#readme) | | `focus-within-pseudo-class` | `:focus-within` Focus Container Pseudo-Class | [example](https://preset-env.cssdb.org/features/#focus-within-pseudo-class) | [docs](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-focus-within#readme) | | `font-format-keywords` | Font `format()` Keywords | [example](https://preset-env.cssdb.org/features/#font-format-keywords) | [docs](https://github.com/valtlai/postcss-font-format-keywords#readme) | diff --git a/plugin-packs/postcss-preset-env/README.md b/plugin-packs/postcss-preset-env/README.md index 13ca1f97a..594b2176d 100644 --- a/plugin-packs/postcss-preset-env/README.md +++ b/plugin-packs/postcss-preset-env/README.md @@ -218,7 +218,7 @@ postcssPresetEnv({ /* use stage 3 features + custom-selectors (preserving the original CSS) */ stage: 3, features: { - 'custom-selectors': { preserve: true } + 'custom-selectors': { preserve: true } } }) ``` @@ -337,6 +337,50 @@ The `enableClientSidePolyfills` enables any feature that would need an extra bro - Note that manually enabling/disabling features via the "feature" option overrides this flag. - This only controls if the PostCSS plugins are enabled. It does not cause the browsers libraries to be included in your bundle. +### logical + +The `logical` option can hold an object which lets you specify direction of the inline and block axes and will affect the +following features: + +- `logical-properties-and-values`: [PostCSS Logical](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-logical#readme) +- `float-clear-logical-values`: [PostCSS Logical Float And Clear](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-logical#readme) +- `logical-resize`: [PostCSS Logical Resize](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-logical-resize#readme) +- `logical-viewport-units`: [PostCSS Logical Viewport Units](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-logica-viewport-unitsl#readme) + +It should have `blockDirection` and/or `inlineDirection` which can be any of the following: + +- `top-to-bottom` +- `bottom-to-top` +- `left-to-right` +- `right-to-left` + +```js +postcssPresetEnv({ + logical: { // instruct all logical plugins to set inline axis to right to left + inlineDirection: 'right-to-left', + }, +}); +``` + +```pcss +.element { + float: inline-start; + padding-inline-end: 10px; +} +``` + +Becomes : + +``` +.element { + float: right; + padding-left: 10px; +} +``` + +You can't mix two vertical directions or two horizontal directions so for example `top-to-bottom` and `right-to-left` are valid, but `top-to-bottom` and `bottom-to-top` are not. + +You might want to tweak these values if you are using a different writing system, such as Arabic, Hebrew or Chinese for example. ## Stability and Portability diff --git a/plugin-packs/postcss-preset-env/dist/index.cjs b/plugin-packs/postcss-preset-env/dist/index.cjs index 738dc84cd..7f0a6011d 100644 --- a/plugin-packs/postcss-preset-env/dist/index.cjs +++ b/plugin-packs/postcss-preset-env/dist/index.cjs @@ -1 +1 @@ -"use strict";var s=require("autoprefixer"),e=require("cssdb"),o=require("@csstools/postcss-progressive-custom-properties"),t=require("browserslist"),r=require("postcss-initial"),i=require("postcss-pseudo-class-any-link"),a=require("css-blank-pseudo"),n=require("postcss-page-break"),c=require("@csstools/postcss-cascade-layers"),p=require("postcss-attribute-case-insensitive"),l=require("postcss-clamp"),u=require("@csstools/postcss-color-function"),m=require("postcss-color-functional-notation"),d=require("postcss-custom-media"),f=require("postcss-custom-properties"),g=require("postcss-custom-selectors"),b=require("postcss-dir-pseudo-class"),h=require("@csstools/postcss-normalize-display-values"),N=require("postcss-double-position-gradients"),y=require("postcss-focus-visible"),k=require("postcss-focus-within"),v=require("@csstools/postcss-font-format-keywords"),w=require("postcss-font-variant"),q=require("postcss-gap-properties"),S=require("css-has-pseudo"),F=require("postcss-color-hex-alpha"),O=require("@csstools/postcss-hwb-function"),$=require("@csstools/postcss-ic-unit"),x=require("postcss-image-set-function"),P=require("@csstools/postcss-is-pseudo-class"),E=require("postcss-lab-function"),C=require("postcss-logical"),I=require("@csstools/postcss-media-queries-aspect-ratio-number-values"),B=require("postcss-media-minmax"),U=require("@csstools/postcss-nested-calc"),_=require("postcss-nesting"),A=require("postcss-selector-not"),L=require("@csstools/postcss-oklab-function"),R=require("postcss-opacity-percentage"),j=require("postcss-overflow-shorthand"),M=require("postcss-replace-overflow-wrap"),D=require("postcss-place"),W=require("css-prefers-color-scheme"),V=require("postcss-color-rebeccapurple"),T=require("@csstools/postcss-scope-pseudo-class"),H=require("@csstools/postcss-stepped-value-functions"),z=require("@csstools/postcss-text-decoration-shorthand"),G=require("@csstools/postcss-trigonometric-functions"),J=require("@csstools/postcss-unset-value");const K={"blank-pseudo-class":"https://github.com/csstools/postcss-plugins/blob/main/plugins/css-blank-pseudo/README-BROWSER.md","focus-visible-pseudo-class":"https://github.com/WICG/focus-visible","focus-within-pseudo-class":"https://github.com/jsxtools/focus-within/blob/master/README-BROWSER.md","has-pseudo-class":"https://github.com/csstools/postcss-plugins/blob/main/plugins/css-has-pseudo/README-BROWSER.md","prefers-color-scheme-query":"https://github.com/csstools/postcss-plugins/blob/main/plugins/css-prefers-color-scheme/README-BROWSER.md"},Z=["blank-pseudo-class","focus-visible-pseudo-class","focus-within-pseudo-class","has-pseudo-class","prefers-color-scheme-query"];function logFeaturesList(s,e,o){if(e.debug){o.log("Enabling the following feature(s):");const t=[],r=[];!1!==e.autoprefixer&&r.push(" autoprefixer"),s.forEach((s=>{s.id.startsWith("before")||s.id.startsWith("after")?r.push(` ${s.id} (injected via options)`):r.push(` ${s.id}`),void 0!==K[s.id]&&t.push(s.id)})),r.sort(((s,e)=>s.localeCompare(e))),t.sort(((s,e)=>s.localeCompare(e))),r.forEach((s=>o.log(s))),t.length&&(o.log("These feature(s) need a browser library to work:"),t.forEach((s=>o.log(` ${s}: ${K[s]}`))))}}function initializeSharedOptions(s){if("preserve"in s){const e={};return"preserve"in s&&(e.preserve=s.preserve),e}return!1}function clamp(s,e,o){return Math.max(s,Math.min(e,o))}function stageFromOptions(s,e){let o=2;if(void 0===s.stage)return e.log(`Using features from Stage ${o} (default)`),o;if(!1===s.stage)o=5;else{let e=parseInt(s.stage,10);Number.isNaN(e)&&(e=0),o=clamp(0,e,5)}return 5===o?e.log('Stage has been disabled, features will be handled via the "features" option.'):e.log(`Using features from Stage ${o}`),o}const Q=Symbol("insertBefore"),X=Symbol("insertAfter"),Y=Symbol("insertOrder"),ss=Symbol("plugin");function getTransformedInsertions(s,e,o){if("insertBefore"!==o&&"insertAfter"!==o)return[];const t="insertBefore"===o?Q:X,r=[];for(const o in e){if(!Object.hasOwnProperty.call(e,o))continue;if(!s.find((s=>s.id===o)))continue;let i=e[o];Array.isArray(i)||(i=[i]);for(let s=0;sfeatureIsInsertedOrHasAPlugin(s))).sort(((s,e)=>featureIsLess(s,e)))}const cs=["and_chr","and_ff","and_qq","and_uc","android","baidu","chrome","edge","firefox","ie","ie_mob","ios_saf","kaios","op_mini","op_mob","opera","safari","samsung"];function getUnsupportedBrowsersByFeature(s){if(!s)return[];if(!("browser_support"in s))return["> 0%"];const e=[];return cs.forEach((o=>{if("op_mini"===o&&void 0===s.browser_support[o])return void e.push("op_mini all");const t=s.browser_support[o];"string"==typeof t&&/^[0-9|.]+$/.test(t)?e.push(`${o} < ${s.browser_support[o]}`):e.push(`${o} >= 1`)})),e}function getOptionsForBrowsersByFeature(s,e,o,r){const i=t(s,{ignoreUnknownVersions:!0});switch(e.id){case"is-pseudo-class":return{onComplexSelector:"warning"};case"nesting-rules":if(needsOptionFor(o.find((s=>"is-pseudo-class"===s.id)),i))return r.log('Disabling :is on "nesting-rules" due to lack of browser support.'),{noIsPseudoSelector:!0};return{};case"any-link-pseudo-class":if(i.find((s=>s.startsWith("ie ")||s.startsWith("edge "))))return r.log('Adding area[href] fallbacks for ":any-link" support in Edge and IE.'),{subFeatures:{areaHrefNeedsFixing:!0}};return{};default:return{}}}function needsOptionFor(s,e){const o=getUnsupportedBrowsersByFeature(s);return!!e.some((s=>t(o,{ignoreUnknownVersions:!0}).some((e=>e===s))))}function formatPolyfillableFeature(s){const e=getUnsupportedBrowsersByFeature(s);if(s[Q]||s[X]){let o=s.id;return o=s.insertBefore?`before-${o}`:`after-${o}`,{browsers:e,vendors_implementations:s.vendors_implementations,plugin:s[ss],id:o,stage:6}}return{browsers:e,vendors_implementations:s.vendors_implementations,plugin:ns.get(s.id),id:s.id,stage:s.stage}}function formatStagedFeature(s,e,o,t,r,i){let a,n;return a=getOptionsForBrowsersByFeature(e,t,s,i),!0===o[t.id]?r&&(a=Object.assign({},a,r)):a=r?Object.assign({},a,r,o[t.id]):Object.assign({},a,o[t.id]),a.enableProgressiveCustomProperties=!1,"all-property"===t.id&&"preserve"in a&&(a.replace=a.preserve),"overflow-wrap-property"===t.id&&"preserve"in a&&(a.method=a.preserve?"copy":"replace"),n=t.plugin.postcss&&"function"==typeof t.plugin?t.plugin(a):t.plugin&&t.plugin.default&&"function"==typeof t.plugin.default&&t.plugin.default.postcss?t.plugin.default(a):t.plugin,{browsers:t.browsers,vendors_implementations:t.vendors_implementations,plugin:n,pluginOptions:a,id:t.id}}function intOrZero(s){const e=parseInt(s,10);return Number.isNaN(e)?0:e}function listFeatures(s,e,o,r){const i=Object(e.features),a="enableClientSidePolyfills"in e&&e.enableClientSidePolyfills,n=Object(e.insertBefore),c=Object(e.insertAfter),p=e.browsers,l=clamp(0,intOrZero(e.minimumVendorImplementations),3);l>0&&r.log(`Using features with ${l} or more vendor implementations`);const u=stageFromOptions(e,r);2===u&&o&&!1===o.preserve&&(s=JSON.parse(JSON.stringify(s))).forEach((s=>{("blank-pseudo-class"===s.id||"prefers-color-scheme-query"===s.id)&&(s.stage=1)}));const m=prepareFeaturesList(s,n,c).map((s=>formatPolyfillableFeature(s))).filter((s=>0===l||(!(!s[Q]&&!s[X])||(l<=s.vendors_implementations||(i[s.id]?(r.log(` ${s.id} does not meet the required vendor implementations but has been enabled by options`),!0):(r.log(` ${s.id} with ${s.vendors_implementations} vendor implementations has been disabled`),!1)))))).filter((s=>{const e=s.stage>=u,o=a||!Z.includes(s.id),t=!1===i[s.id],n=i[s.id]?i[s.id]:e&&o;return t?r.log(` ${s.id} has been disabled by options`):e?o||r.log(` ${s.id} has been disabled by "enableClientSidePolyfills: false".`):n?r.log(` ${s.id} does not meet the required stage but has been enabled by options`):r.log(` ${s.id} with stage ${s.stage} has been disabled`),n})).map((e=>formatStagedFeature(s,p,i,e,o,r))),d=t(p,{ignoreUnknownVersions:!0});return m.filter((s=>{if(s.id in i)return i[s.id];const e=t(s.browsers,{ignoreUnknownVersions:!0}),o=d.some((s=>e.some((e=>e===s))));return o||r.log(`${s.id} disabled due to browser support`),o}))}class Logger{constructor(){this.logs=[]}log(s){this.logs.push(s)}resetLogger(){this.logs.length=0}dumpLogs(s){s&&this.logs.forEach((e=>s.warn(e))),this.resetLogger()}}var ps=[{packageName:"css-blank-pseudo",id:"blank-pseudo-class",importName:"postcssBlankPseudo"},{packageName:"css-has-pseudo",id:"has-pseudo-class",importName:"postcssHasPseudo"},{packageName:"css-prefers-color-scheme",id:"prefers-color-scheme-query",importName:"postcssPrefersColorScheme"},{packageName:"postcss-attribute-case-insensitive",id:"case-insensitive-attributes",importName:"postcssAttributeCaseInsensitive"},{packageName:"postcss-clamp",id:"clamp",importName:"postcssClamp"},{packageName:"@csstools/postcss-color-function",id:"color-function",importName:"postcssColorFunction"},{packageName:"postcss-color-functional-notation",id:"color-functional-notation",importName:"postcssColorFunctionalNotation"},{packageName:"postcss-color-hex-alpha",id:"hexadecimal-alpha-notation",importName:"postcssColorHexAlpha"},{packageName:"postcss-color-rebeccapurple",id:"rebeccapurple-color",importName:"postcssColorRebeccapurple"},{packageName:"postcss-custom-media",id:"custom-media-queries",importName:"postcssCustomMedia"},{packageName:"postcss-custom-properties",id:"custom-properties",importName:"postcssCustomProperties"},{packageName:"postcss-custom-selectors",id:"custom-selectors",importName:"postcssCustomSelectors"},{packageName:"postcss-dir-pseudo-class",id:"dir-pseudo-class",importName:"postcssDirPseudoClass"},{packageName:"postcss-double-position-gradients",id:"double-position-gradients",importName:"postcssDoublePositionGradients"},{packageName:"postcss-focus-visible",id:"focus-visible-pseudo-class",importName:"postcssFocusVisible"},{packageName:"postcss-focus-within",id:"focus-within-pseudo-class",importName:"postcssFocusWithin"},{packageName:"@csstools/postcss-font-format-keywords",id:"font-format-keywords",importName:"postcssFontFormatKeywords"},{packageName:"postcss-font-variant",id:"font-variant-property",importName:"postcssFontVariant"},{packageName:"postcss-gap-properties",id:"gap-properties",importName:"postcssGapProperties"},{packageName:"@csstools/postcss-hwb-function",id:"hwb-function",importName:"postcssHWBFunction"},{packageName:"@csstools/postcss-ic-unit",id:"ic-unit",importName:"postcssICUnit"},{packageName:"postcss-image-set-function",id:"image-set-function",importName:"postcssImageSetFunction"},{packageName:"postcss-initial",id:"all-property",importName:"postcssInitial"},{packageName:"@csstools/postcss-is-pseudo-class",id:"is-pseudo-class",importName:"postcssIsPseudoClass"},{packageName:"@csstools/postcss-scope-pseudo-class",id:"scope-pseudo-class",importName:"postcssScopePseudoClass"},{packageName:"postcss-lab-function",id:"lab-function",importName:"postcssLabFunction"},{packageName:"postcss-logical",id:"logical-properties-and-values",importName:"postcssLogical"},{packageName:"postcss-media-minmax",id:"media-query-ranges",importName:"postcssMediaMinmax"},{packageName:"@csstools/postcss-media-queries-aspect-ratio-number-values",id:"media-queries-aspect-ratio-number-values",importName:"postcssMediaQueriesAspectRatioNumberValues"},{packageName:"postcss-nesting",id:"nesting-rules",importName:"postcssNesting"},{packageName:"@csstools/postcss-normalize-display-values",id:"display-two-values",importName:"postcssNormalizeDisplayValues"},{packageName:"@csstools/postcss-oklab-function",id:"oklab-function",importName:"postcssOKLabFunction"},{packageName:"postcss-opacity-percentage",id:"opacity-percentage",importName:"postcssOpacityPercentage"},{packageName:"postcss-overflow-shorthand",id:"overflow-property",importName:"postcssOverflowShorthand"},{packageName:"postcss-page-break",id:"break-properties",importName:"postcssPageBreak"},{packageName:"postcss-place",id:"place-properties",importName:"postcssPlace"},{packageName:"postcss-pseudo-class-any-link",id:"any-link-pseudo-class",importName:"postcssPseudoClassAnyLink"},{packageName:"postcss-replace-overflow-wrap",id:"overflow-wrap-property",importName:"postcssReplaceOverflowWrap"},{packageName:"postcss-selector-not",id:"not-pseudo-class",importName:"postcssSelectorNot"},{packageName:"@csstools/postcss-stepped-value-functions",id:"stepped-value-functions",importName:"postcssSteppedValueFunctions"},{packageName:"postcss-system-ui-font-family",importedPackage:"../patch/postcss-system-ui-font-family.mjs",id:"system-ui-font-family",importName:"postcssFontFamilySystemUI"},{packageName:"@csstools/postcss-unset-value",id:"unset-value",importName:"postcssUnsetValue"},{packageName:"@csstools/postcss-cascade-layers",id:"cascade-layers",importName:"postcssCascadeLayers"},{packageName:"@csstools/postcss-trigonometric-functions",id:"trigonometric-functions",importName:"postcssTrigonometricFunctions"},{packageName:"@csstools/postcss-nested-calc",id:"nested-calc",importName:"postcssNestedCalc"},{packageName:"@csstools/postcss-text-decoration-shorthand",id:"text-decoration-shorthand",importName:"postcssTextDecorationShorthand"}];function getPackageNamesToIds(){const s={};return ps.forEach((e=>{s[e.packageName]=e.id})),s}function pluginIdHelp(s,e,o){const t=ps.map((s=>s.id)),r=ps.map((s=>s.packageName)),i=getPackageNamesToIds();s.forEach((s=>{if(t.includes(s))return;const a=mostSimilar(s,t),n=mostSimilar(s,r);Math.min(a.distance,n.distance)>10?e.warn(o`Unknown feature: "${s}", see the list of features https://github.com/csstools/postcss-plugins/blob/main/plugin-packs/postcss-preset-env/FEATURES.md`):a.distance{const r=new Logger,i=Object(t),a=Object.keys(Object(i.features)),n=i.browsers,c=initializeSharedOptions(i),p=listFeatures(e,i,c,r),l=p.map((s=>s.plugin));!1!==i.autoprefixer&&l.push(s(Object.assign({overrideBrowserslist:n},i.autoprefixer))),l.push(o()),logFeaturesList(p,i,r);const internalPlugin=()=>({postcssPlugin:"postcss-preset-env",OnceExit:function(s,{result:e}){pluginIdHelp(a,s,e),i.debug&&r.dumpLogs(e),r.resetLogger()}});return internalPlugin.postcss=!0,{postcssPlugin:"postcss-preset-env",plugins:[...l,internalPlugin()]}};creator.postcss=!0,module.exports=creator; +"use strict";var s=require("autoprefixer"),e=require("cssdb"),o=require("@csstools/postcss-progressive-custom-properties"),t=require("browserslist"),i=require("postcss-initial"),r=require("postcss-pseudo-class-any-link"),a=require("css-blank-pseudo"),c=require("postcss-page-break"),n=require("@csstools/postcss-cascade-layers"),p=require("postcss-attribute-case-insensitive"),l=require("postcss-clamp"),u=require("@csstools/postcss-color-function"),m=require("postcss-color-functional-notation"),d=require("postcss-custom-media"),g=require("postcss-custom-properties"),f=require("postcss-custom-selectors"),b=require("postcss-dir-pseudo-class"),h=require("@csstools/postcss-normalize-display-values"),N=require("postcss-double-position-gradients"),v=require("@csstools/postcss-logical-float-and-clear"),y=require("postcss-focus-visible"),k=require("postcss-focus-within"),w=require("@csstools/postcss-font-format-keywords"),q=require("postcss-font-variant"),F=require("postcss-gap-properties"),S=require("css-has-pseudo"),O=require("postcss-color-hex-alpha"),$=require("@csstools/postcss-hwb-function"),x=require("@csstools/postcss-ic-unit"),P=require("postcss-image-set-function"),C=require("@csstools/postcss-is-pseudo-class"),E=require("postcss-lab-function"),I=require("postcss-logical"),B=require("@csstools/postcss-logical-resize"),U=require("@csstools/postcss-logical-viewport-units"),_=require("@csstools/postcss-media-queries-aspect-ratio-number-values"),L=require("postcss-media-minmax"),A=require("@csstools/postcss-nested-calc"),R=require("postcss-nesting"),j=require("postcss-selector-not"),M=require("@csstools/postcss-oklab-function"),D=require("postcss-opacity-percentage"),V=require("postcss-overflow-shorthand"),W=require("postcss-replace-overflow-wrap"),z=require("postcss-place"),T=require("css-prefers-color-scheme"),H=require("postcss-color-rebeccapurple"),G=require("@csstools/postcss-scope-pseudo-class"),J=require("@csstools/postcss-stepped-value-functions"),K=require("@csstools/postcss-text-decoration-shorthand"),Z=require("@csstools/postcss-trigonometric-functions"),Q=require("@csstools/postcss-unset-value");const X={"blank-pseudo-class":"https://github.com/csstools/postcss-plugins/blob/main/plugins/css-blank-pseudo/README-BROWSER.md","focus-visible-pseudo-class":"https://github.com/WICG/focus-visible","focus-within-pseudo-class":"https://github.com/jsxtools/focus-within/blob/master/README-BROWSER.md","has-pseudo-class":"https://github.com/csstools/postcss-plugins/blob/main/plugins/css-has-pseudo/README-BROWSER.md","prefers-color-scheme-query":"https://github.com/csstools/postcss-plugins/blob/main/plugins/css-prefers-color-scheme/README-BROWSER.md"},Y=["blank-pseudo-class","focus-visible-pseudo-class","focus-within-pseudo-class","has-pseudo-class","prefers-color-scheme-query"];function logFeaturesList(s,e,o){if(e.debug){o.log("Enabling the following feature(s):");const t=[],i=[];!1!==e.autoprefixer&&i.push(" autoprefixer"),s.forEach((s=>{s.id.startsWith("before")||s.id.startsWith("after")?i.push(` ${s.id} (injected via options)`):i.push(` ${s.id}`),void 0!==X[s.id]&&t.push(s.id)})),i.sort(((s,e)=>s.localeCompare(e))),t.sort(((s,e)=>s.localeCompare(e))),i.forEach((s=>o.log(s))),t.length&&(o.log("These feature(s) need a browser library to work:"),t.forEach((s=>o.log(` ${s}: ${X[s]}`))))}}function initializeSharedOptions(s){if("preserve"in s){const e={};return e.preserve=s.preserve,e}return!1}function clamp(s,e,o){return Math.max(s,Math.min(e,o))}function stageFromOptions(s,e){let o=2;if(void 0===s.stage)return e.log(`Using features from Stage ${o} (default)`),o;if(!1===s.stage)o=5;else{let e=parseInt(s.stage,10);Number.isNaN(e)&&(e=0),o=clamp(0,e,5)}return 5===o?e.log('Stage has been disabled, features will be handled via the "features" option.'):e.log(`Using features from Stage ${o}`),o}const ss=Symbol("insertBefore"),es=Symbol("insertAfter"),os=Symbol("insertOrder"),ts=Symbol("plugin");function getTransformedInsertions(s,e,o){if("insertBefore"!==o&&"insertAfter"!==o)return[];const t="insertBefore"===o?ss:es,i=[];for(const o in e){if(!Object.hasOwnProperty.call(e,o))continue;if(!s.find((s=>s.id===o)))continue;let r=e[o];Array.isArray(r)||(r=[r]);for(let s=0;sfeatureIsInsertedOrHasAPlugin(s))).sort(((s,e)=>featureIsLess(s,e)))}const us=["and_chr","and_ff","and_qq","and_uc","android","baidu","chrome","edge","firefox","ie","ie_mob","ios_saf","kaios","op_mini","op_mob","opera","safari","samsung"];function getUnsupportedBrowsersByFeature(s){if(!s)return[];if(!("browser_support"in s))return["> 0%"];const e=[];return us.forEach((o=>{if("op_mini"===o&&void 0===s.browser_support[o])return void e.push("op_mini all");const t=s.browser_support[o];"string"==typeof t&&/^[0-9|.]+$/.test(t)?e.push(`${o} < ${s.browser_support[o]}`):e.push(`${o} >= 1`)})),e}function getOptionsForBrowsersByFeature(s,e,o,i,r){const a=t(s,{ignoreUnknownVersions:!0});switch(e.id){case"is-pseudo-class":return{onComplexSelector:"warning"};case"nesting-rules":if(needsOptionFor(o.find((s=>"is-pseudo-class"===s.id)),a))return r.log('Disabling :is on "nesting-rules" due to lack of browser support.'),{noIsPseudoSelector:!0};return{};case"any-link-pseudo-class":if(a.find((s=>s.startsWith("ie ")||s.startsWith("edge "))))return r.log('Adding area[href] fallbacks for ":any-link" support in Edge and IE.'),{subFeatures:{areaHrefNeedsFixing:!0}};return{};case"logical-properties-and-values":case"float-clear-logical-values":case"logical-resize":case"logical-viewport-units":return"logical"in i?i.logical:{};default:return{}}}function needsOptionFor(s,e){const o=getUnsupportedBrowsersByFeature(s);return!!e.some((s=>t(o,{ignoreUnknownVersions:!0}).some((e=>e===s))))}function formatPolyfillableFeature(s){const e=getUnsupportedBrowsersByFeature(s);if(s[ss]||s[es]){let o=s.id;return o=s.insertBefore?`before-${o}`:`after-${o}`,{browsers:e,vendors_implementations:s.vendors_implementations,plugin:s[ts],id:o,stage:6}}return{browsers:e,vendors_implementations:s.vendors_implementations,plugin:ls.get(s.id),id:s.id,stage:s.stage}}function formatStagedFeature(s,e,o,t,i,r,a){let c,n;return c=getOptionsForBrowsersByFeature(e,t,s,r,a),!0===o[t.id]?i&&(c=Object.assign({},c,i)):c=i?Object.assign({},c,i,o[t.id]):Object.assign({},c,o[t.id]),c.enableProgressiveCustomProperties=!1,"all-property"===t.id&&"preserve"in c&&(c.replace=c.preserve),"overflow-wrap-property"===t.id&&"preserve"in c&&(c.method=c.preserve?"copy":"replace"),n=t.plugin.postcss&&"function"==typeof t.plugin?t.plugin(c):t.plugin&&t.plugin.default&&"function"==typeof t.plugin.default&&t.plugin.default.postcss?t.plugin.default(c):t.plugin,{browsers:t.browsers,vendors_implementations:t.vendors_implementations,plugin:n,pluginOptions:c,id:t.id}}function intOrZero(s){const e=parseInt(s,10);return Number.isNaN(e)?0:e}function listFeatures(s,e,o,i){const r=Object(e.features),a="enableClientSidePolyfills"in e&&e.enableClientSidePolyfills,c=Object(e.insertBefore),n=Object(e.insertAfter),p=e.browsers,l=clamp(0,intOrZero(e.minimumVendorImplementations),3);l>0&&i.log(`Using features with ${l} or more vendor implementations`);const u=stageFromOptions(e,i);2===u&&o&&!1===o.preserve&&(s=JSON.parse(JSON.stringify(s))).forEach((s=>{("blank-pseudo-class"===s.id||"prefers-color-scheme-query"===s.id)&&(s.stage=1)}));const m=prepareFeaturesList(s,c,n).map((s=>formatPolyfillableFeature(s))).filter((s=>0===l||(!(!s[ss]&&!s[es])||(l<=s.vendors_implementations||(r[s.id]?(i.log(` ${s.id} does not meet the required vendor implementations but has been enabled by options`),!0):(i.log(` ${s.id} with ${s.vendors_implementations} vendor implementations has been disabled`),!1)))))).filter((s=>{const e=s.stage>=u,o=a||!Y.includes(s.id),t=!1===r[s.id],c=r[s.id]?r[s.id]:e&&o;return t?i.log(` ${s.id} has been disabled by options`):e?o||i.log(` ${s.id} has been disabled by "enableClientSidePolyfills: false".`):c?i.log(` ${s.id} does not meet the required stage but has been enabled by options`):i.log(` ${s.id} with stage ${s.stage} has been disabled`),c})).map((t=>formatStagedFeature(s,p,r,t,o,e,i))),d=t(p,{ignoreUnknownVersions:!0});return m.filter((s=>{if(s.id in r)return r[s.id];const e=t(s.browsers,{ignoreUnknownVersions:!0}),o=d.some((s=>e.some((e=>e===s))));return o||i.log(`${s.id} disabled due to browser support`),o}))}class Logger{constructor(){this.logs=[]}log(s){this.logs.push(s)}resetLogger(){this.logs.length=0}dumpLogs(s){s&&this.logs.forEach((e=>s.warn(e))),this.resetLogger()}}var ms=[{packageName:"css-blank-pseudo",id:"blank-pseudo-class",importName:"postcssBlankPseudo"},{packageName:"css-has-pseudo",id:"has-pseudo-class",importName:"postcssHasPseudo"},{packageName:"css-prefers-color-scheme",id:"prefers-color-scheme-query",importName:"postcssPrefersColorScheme"},{packageName:"postcss-attribute-case-insensitive",id:"case-insensitive-attributes",importName:"postcssAttributeCaseInsensitive"},{packageName:"postcss-clamp",id:"clamp",importName:"postcssClamp"},{packageName:"@csstools/postcss-color-function",id:"color-function",importName:"postcssColorFunction"},{packageName:"postcss-color-functional-notation",id:"color-functional-notation",importName:"postcssColorFunctionalNotation"},{packageName:"postcss-color-hex-alpha",id:"hexadecimal-alpha-notation",importName:"postcssColorHexAlpha"},{packageName:"postcss-color-rebeccapurple",id:"rebeccapurple-color",importName:"postcssColorRebeccapurple"},{packageName:"postcss-custom-media",id:"custom-media-queries",importName:"postcssCustomMedia"},{packageName:"postcss-custom-properties",id:"custom-properties",importName:"postcssCustomProperties"},{packageName:"postcss-custom-selectors",id:"custom-selectors",importName:"postcssCustomSelectors"},{packageName:"postcss-dir-pseudo-class",id:"dir-pseudo-class",importName:"postcssDirPseudoClass"},{packageName:"postcss-double-position-gradients",id:"double-position-gradients",importName:"postcssDoublePositionGradients"},{packageName:"postcss-focus-visible",id:"focus-visible-pseudo-class",importName:"postcssFocusVisible"},{packageName:"postcss-focus-within",id:"focus-within-pseudo-class",importName:"postcssFocusWithin"},{packageName:"@csstools/postcss-font-format-keywords",id:"font-format-keywords",importName:"postcssFontFormatKeywords"},{packageName:"postcss-font-variant",id:"font-variant-property",importName:"postcssFontVariant"},{packageName:"postcss-gap-properties",id:"gap-properties",importName:"postcssGapProperties"},{packageName:"@csstools/postcss-hwb-function",id:"hwb-function",importName:"postcssHWBFunction"},{packageName:"@csstools/postcss-ic-unit",id:"ic-unit",importName:"postcssICUnit"},{packageName:"postcss-image-set-function",id:"image-set-function",importName:"postcssImageSetFunction"},{packageName:"postcss-initial",id:"all-property",importName:"postcssInitial"},{packageName:"@csstools/postcss-is-pseudo-class",id:"is-pseudo-class",importName:"postcssIsPseudoClass"},{packageName:"@csstools/postcss-scope-pseudo-class",id:"scope-pseudo-class",importName:"postcssScopePseudoClass"},{packageName:"postcss-lab-function",id:"lab-function",importName:"postcssLabFunction"},{packageName:"postcss-logical",id:"logical-properties-and-values",importName:"postcssLogical"},{packageName:"@csstools/postcss-logical-float-and-clear",id:"float-clear-logical-values",importName:"postcssLogicalFloatAndClear"},{packageName:"@csstools/postcss-logical-resize",id:"logical-resize",importName:"postcssLogicalResize"},{packageName:"@csstools/postcss-logical-viewport-units",id:"logical-viewport-units",importName:"postcssLogicalViewportUnits"},{packageName:"postcss-media-minmax",id:"media-query-ranges",importName:"postcssMediaMinmax"},{packageName:"@csstools/postcss-media-queries-aspect-ratio-number-values",id:"media-queries-aspect-ratio-number-values",importName:"postcssMediaQueriesAspectRatioNumberValues"},{packageName:"postcss-nesting",id:"nesting-rules",importName:"postcssNesting"},{packageName:"@csstools/postcss-normalize-display-values",id:"display-two-values",importName:"postcssNormalizeDisplayValues"},{packageName:"@csstools/postcss-oklab-function",id:"oklab-function",importName:"postcssOKLabFunction"},{packageName:"postcss-opacity-percentage",id:"opacity-percentage",importName:"postcssOpacityPercentage"},{packageName:"postcss-overflow-shorthand",id:"overflow-property",importName:"postcssOverflowShorthand"},{packageName:"postcss-page-break",id:"break-properties",importName:"postcssPageBreak"},{packageName:"postcss-place",id:"place-properties",importName:"postcssPlace"},{packageName:"postcss-pseudo-class-any-link",id:"any-link-pseudo-class",importName:"postcssPseudoClassAnyLink"},{packageName:"postcss-replace-overflow-wrap",id:"overflow-wrap-property",importName:"postcssReplaceOverflowWrap"},{packageName:"postcss-selector-not",id:"not-pseudo-class",importName:"postcssSelectorNot"},{packageName:"@csstools/postcss-stepped-value-functions",id:"stepped-value-functions",importName:"postcssSteppedValueFunctions"},{packageName:"postcss-system-ui-font-family",importedPackage:"../patch/postcss-system-ui-font-family.mjs",id:"system-ui-font-family",importName:"postcssFontFamilySystemUI"},{packageName:"@csstools/postcss-unset-value",id:"unset-value",importName:"postcssUnsetValue"},{packageName:"@csstools/postcss-cascade-layers",id:"cascade-layers",importName:"postcssCascadeLayers"},{packageName:"@csstools/postcss-trigonometric-functions",id:"trigonometric-functions",importName:"postcssTrigonometricFunctions"},{packageName:"@csstools/postcss-nested-calc",id:"nested-calc",importName:"postcssNestedCalc"},{packageName:"@csstools/postcss-text-decoration-shorthand",id:"text-decoration-shorthand",importName:"postcssTextDecorationShorthand"}];function getPackageNamesToIds(){const s={};return ms.forEach((e=>{s[e.packageName]=e.id})),s}function pluginIdHelp(s,e,o){const t=ms.map((s=>s.id)),i=ms.map((s=>s.packageName)),r=getPackageNamesToIds();s.forEach((s=>{if(t.includes(s))return;const a=mostSimilar(s,t),c=mostSimilar(s,i);Math.min(a.distance,c.distance)>10?e.warn(o`Unknown feature: "${s}", see the list of features https://github.com/csstools/postcss-plugins/blob/main/plugin-packs/postcss-preset-env/FEATURES.md`):a.distance{const i=new Logger,r=Object(t),a=Object.keys(Object(r.features)),c=r.browsers,n=initializeSharedOptions(r),p=listFeatures(e,r,n,i),l=p.map((s=>s.plugin));!1!==r.autoprefixer&&l.push(s(Object.assign({overrideBrowserslist:c},r.autoprefixer))),l.push(o()),logFeaturesList(p,r,i);const internalPlugin=()=>({postcssPlugin:"postcss-preset-env",OnceExit:function(s,{result:e}){pluginIdHelp(a,s,e),r.debug&&i.dumpLogs(e),i.resetLogger()}});return internalPlugin.postcss=!0,{postcssPlugin:"postcss-preset-env",plugins:[...l,internalPlugin()]}};creator.postcss=!0,module.exports=creator; diff --git a/plugin-packs/postcss-preset-env/dist/index.mjs b/plugin-packs/postcss-preset-env/dist/index.mjs index 7021962d3..4f5593d99 100644 --- a/plugin-packs/postcss-preset-env/dist/index.mjs +++ b/plugin-packs/postcss-preset-env/dist/index.mjs @@ -1 +1 @@ -import s from"autoprefixer";import e from"cssdb";import o from"@csstools/postcss-progressive-custom-properties";import t from"browserslist";import r from"postcss-initial";import i from"postcss-pseudo-class-any-link";import a from"css-blank-pseudo";import p from"postcss-page-break";import n from"@csstools/postcss-cascade-layers";import c from"postcss-attribute-case-insensitive";import l from"postcss-clamp";import m from"@csstools/postcss-color-function";import u from"postcss-color-functional-notation";import d from"postcss-custom-media";import f from"postcss-custom-properties";import g from"postcss-custom-selectors";import b from"postcss-dir-pseudo-class";import h from"@csstools/postcss-normalize-display-values";import N from"postcss-double-position-gradients";import y from"postcss-focus-visible";import k from"postcss-focus-within";import v from"@csstools/postcss-font-format-keywords";import w from"postcss-font-variant";import S from"postcss-gap-properties";import F from"css-has-pseudo";import O from"postcss-color-hex-alpha";import $ from"@csstools/postcss-hwb-function";import x from"@csstools/postcss-ic-unit";import P from"postcss-image-set-function";import E from"@csstools/postcss-is-pseudo-class";import C from"postcss-lab-function";import I from"postcss-logical";import B from"@csstools/postcss-media-queries-aspect-ratio-number-values";import U from"postcss-media-minmax";import _ from"@csstools/postcss-nested-calc";import q from"postcss-nesting";import A from"postcss-selector-not";import L from"@csstools/postcss-oklab-function";import R from"postcss-opacity-percentage";import j from"postcss-overflow-shorthand";import M from"postcss-replace-overflow-wrap";import D from"postcss-place";import W from"css-prefers-color-scheme";import V from"postcss-color-rebeccapurple";import T from"@csstools/postcss-scope-pseudo-class";import H from"@csstools/postcss-stepped-value-functions";import z from"@csstools/postcss-text-decoration-shorthand";import G from"@csstools/postcss-trigonometric-functions";import J from"@csstools/postcss-unset-value";const K={"blank-pseudo-class":"https://github.com/csstools/postcss-plugins/blob/main/plugins/css-blank-pseudo/README-BROWSER.md","focus-visible-pseudo-class":"https://github.com/WICG/focus-visible","focus-within-pseudo-class":"https://github.com/jsxtools/focus-within/blob/master/README-BROWSER.md","has-pseudo-class":"https://github.com/csstools/postcss-plugins/blob/main/plugins/css-has-pseudo/README-BROWSER.md","prefers-color-scheme-query":"https://github.com/csstools/postcss-plugins/blob/main/plugins/css-prefers-color-scheme/README-BROWSER.md"},Z=["blank-pseudo-class","focus-visible-pseudo-class","focus-within-pseudo-class","has-pseudo-class","prefers-color-scheme-query"];function logFeaturesList(s,e,o){if(e.debug){o.log("Enabling the following feature(s):");const t=[],r=[];!1!==e.autoprefixer&&r.push(" autoprefixer"),s.forEach((s=>{s.id.startsWith("before")||s.id.startsWith("after")?r.push(` ${s.id} (injected via options)`):r.push(` ${s.id}`),void 0!==K[s.id]&&t.push(s.id)})),r.sort(((s,e)=>s.localeCompare(e))),t.sort(((s,e)=>s.localeCompare(e))),r.forEach((s=>o.log(s))),t.length&&(o.log("These feature(s) need a browser library to work:"),t.forEach((s=>o.log(` ${s}: ${K[s]}`))))}}function initializeSharedOptions(s){if("preserve"in s){const e={};return"preserve"in s&&(e.preserve=s.preserve),e}return!1}function clamp(s,e,o){return Math.max(s,Math.min(e,o))}function stageFromOptions(s,e){let o=2;if(void 0===s.stage)return e.log(`Using features from Stage ${o} (default)`),o;if(!1===s.stage)o=5;else{let e=parseInt(s.stage,10);Number.isNaN(e)&&(e=0),o=clamp(0,e,5)}return 5===o?e.log('Stage has been disabled, features will be handled via the "features" option.'):e.log(`Using features from Stage ${o}`),o}const Q=Symbol("insertBefore"),X=Symbol("insertAfter"),Y=Symbol("insertOrder"),ss=Symbol("plugin");function getTransformedInsertions(s,e,o){if("insertBefore"!==o&&"insertAfter"!==o)return[];const t="insertBefore"===o?Q:X,r=[];for(const o in e){if(!Object.hasOwnProperty.call(e,o))continue;if(!s.find((s=>s.id===o)))continue;let i=e[o];Array.isArray(i)||(i=[i]);for(let s=0;sfeatureIsInsertedOrHasAPlugin(s))).sort(((s,e)=>featureIsLess(s,e)))}const ns=["and_chr","and_ff","and_qq","and_uc","android","baidu","chrome","edge","firefox","ie","ie_mob","ios_saf","kaios","op_mini","op_mob","opera","safari","samsung"];function getUnsupportedBrowsersByFeature(s){if(!s)return[];if(!("browser_support"in s))return["> 0%"];const e=[];return ns.forEach((o=>{if("op_mini"===o&&void 0===s.browser_support[o])return void e.push("op_mini all");const t=s.browser_support[o];"string"==typeof t&&/^[0-9|.]+$/.test(t)?e.push(`${o} < ${s.browser_support[o]}`):e.push(`${o} >= 1`)})),e}function getOptionsForBrowsersByFeature(s,e,o,r){const i=t(s,{ignoreUnknownVersions:!0});switch(e.id){case"is-pseudo-class":return{onComplexSelector:"warning"};case"nesting-rules":if(needsOptionFor(o.find((s=>"is-pseudo-class"===s.id)),i))return r.log('Disabling :is on "nesting-rules" due to lack of browser support.'),{noIsPseudoSelector:!0};return{};case"any-link-pseudo-class":if(i.find((s=>s.startsWith("ie ")||s.startsWith("edge "))))return r.log('Adding area[href] fallbacks for ":any-link" support in Edge and IE.'),{subFeatures:{areaHrefNeedsFixing:!0}};return{};default:return{}}}function needsOptionFor(s,e){const o=getUnsupportedBrowsersByFeature(s);return!!e.some((s=>t(o,{ignoreUnknownVersions:!0}).some((e=>e===s))))}function formatPolyfillableFeature(s){const e=getUnsupportedBrowsersByFeature(s);if(s[Q]||s[X]){let o=s.id;return o=s.insertBefore?`before-${o}`:`after-${o}`,{browsers:e,vendors_implementations:s.vendors_implementations,plugin:s[ss],id:o,stage:6}}return{browsers:e,vendors_implementations:s.vendors_implementations,plugin:ps.get(s.id),id:s.id,stage:s.stage}}function formatStagedFeature(s,e,o,t,r,i){let a,p;return a=getOptionsForBrowsersByFeature(e,t,s,i),!0===o[t.id]?r&&(a=Object.assign({},a,r)):a=r?Object.assign({},a,r,o[t.id]):Object.assign({},a,o[t.id]),a.enableProgressiveCustomProperties=!1,"all-property"===t.id&&"preserve"in a&&(a.replace=a.preserve),"overflow-wrap-property"===t.id&&"preserve"in a&&(a.method=a.preserve?"copy":"replace"),p=t.plugin.postcss&&"function"==typeof t.plugin?t.plugin(a):t.plugin&&t.plugin.default&&"function"==typeof t.plugin.default&&t.plugin.default.postcss?t.plugin.default(a):t.plugin,{browsers:t.browsers,vendors_implementations:t.vendors_implementations,plugin:p,pluginOptions:a,id:t.id}}function intOrZero(s){const e=parseInt(s,10);return Number.isNaN(e)?0:e}function listFeatures(s,e,o,r){const i=Object(e.features),a="enableClientSidePolyfills"in e&&e.enableClientSidePolyfills,p=Object(e.insertBefore),n=Object(e.insertAfter),c=e.browsers,l=clamp(0,intOrZero(e.minimumVendorImplementations),3);l>0&&r.log(`Using features with ${l} or more vendor implementations`);const m=stageFromOptions(e,r);2===m&&o&&!1===o.preserve&&(s=JSON.parse(JSON.stringify(s))).forEach((s=>{("blank-pseudo-class"===s.id||"prefers-color-scheme-query"===s.id)&&(s.stage=1)}));const u=prepareFeaturesList(s,p,n).map((s=>formatPolyfillableFeature(s))).filter((s=>0===l||(!(!s[Q]&&!s[X])||(l<=s.vendors_implementations||(i[s.id]?(r.log(` ${s.id} does not meet the required vendor implementations but has been enabled by options`),!0):(r.log(` ${s.id} with ${s.vendors_implementations} vendor implementations has been disabled`),!1)))))).filter((s=>{const e=s.stage>=m,o=a||!Z.includes(s.id),t=!1===i[s.id],p=i[s.id]?i[s.id]:e&&o;return t?r.log(` ${s.id} has been disabled by options`):e?o||r.log(` ${s.id} has been disabled by "enableClientSidePolyfills: false".`):p?r.log(` ${s.id} does not meet the required stage but has been enabled by options`):r.log(` ${s.id} with stage ${s.stage} has been disabled`),p})).map((e=>formatStagedFeature(s,c,i,e,o,r))),d=t(c,{ignoreUnknownVersions:!0});return u.filter((s=>{if(s.id in i)return i[s.id];const e=t(s.browsers,{ignoreUnknownVersions:!0}),o=d.some((s=>e.some((e=>e===s))));return o||r.log(`${s.id} disabled due to browser support`),o}))}class Logger{constructor(){this.logs=[]}log(s){this.logs.push(s)}resetLogger(){this.logs.length=0}dumpLogs(s){s&&this.logs.forEach((e=>s.warn(e))),this.resetLogger()}}var cs=[{packageName:"css-blank-pseudo",id:"blank-pseudo-class",importName:"postcssBlankPseudo"},{packageName:"css-has-pseudo",id:"has-pseudo-class",importName:"postcssHasPseudo"},{packageName:"css-prefers-color-scheme",id:"prefers-color-scheme-query",importName:"postcssPrefersColorScheme"},{packageName:"postcss-attribute-case-insensitive",id:"case-insensitive-attributes",importName:"postcssAttributeCaseInsensitive"},{packageName:"postcss-clamp",id:"clamp",importName:"postcssClamp"},{packageName:"@csstools/postcss-color-function",id:"color-function",importName:"postcssColorFunction"},{packageName:"postcss-color-functional-notation",id:"color-functional-notation",importName:"postcssColorFunctionalNotation"},{packageName:"postcss-color-hex-alpha",id:"hexadecimal-alpha-notation",importName:"postcssColorHexAlpha"},{packageName:"postcss-color-rebeccapurple",id:"rebeccapurple-color",importName:"postcssColorRebeccapurple"},{packageName:"postcss-custom-media",id:"custom-media-queries",importName:"postcssCustomMedia"},{packageName:"postcss-custom-properties",id:"custom-properties",importName:"postcssCustomProperties"},{packageName:"postcss-custom-selectors",id:"custom-selectors",importName:"postcssCustomSelectors"},{packageName:"postcss-dir-pseudo-class",id:"dir-pseudo-class",importName:"postcssDirPseudoClass"},{packageName:"postcss-double-position-gradients",id:"double-position-gradients",importName:"postcssDoublePositionGradients"},{packageName:"postcss-focus-visible",id:"focus-visible-pseudo-class",importName:"postcssFocusVisible"},{packageName:"postcss-focus-within",id:"focus-within-pseudo-class",importName:"postcssFocusWithin"},{packageName:"@csstools/postcss-font-format-keywords",id:"font-format-keywords",importName:"postcssFontFormatKeywords"},{packageName:"postcss-font-variant",id:"font-variant-property",importName:"postcssFontVariant"},{packageName:"postcss-gap-properties",id:"gap-properties",importName:"postcssGapProperties"},{packageName:"@csstools/postcss-hwb-function",id:"hwb-function",importName:"postcssHWBFunction"},{packageName:"@csstools/postcss-ic-unit",id:"ic-unit",importName:"postcssICUnit"},{packageName:"postcss-image-set-function",id:"image-set-function",importName:"postcssImageSetFunction"},{packageName:"postcss-initial",id:"all-property",importName:"postcssInitial"},{packageName:"@csstools/postcss-is-pseudo-class",id:"is-pseudo-class",importName:"postcssIsPseudoClass"},{packageName:"@csstools/postcss-scope-pseudo-class",id:"scope-pseudo-class",importName:"postcssScopePseudoClass"},{packageName:"postcss-lab-function",id:"lab-function",importName:"postcssLabFunction"},{packageName:"postcss-logical",id:"logical-properties-and-values",importName:"postcssLogical"},{packageName:"postcss-media-minmax",id:"media-query-ranges",importName:"postcssMediaMinmax"},{packageName:"@csstools/postcss-media-queries-aspect-ratio-number-values",id:"media-queries-aspect-ratio-number-values",importName:"postcssMediaQueriesAspectRatioNumberValues"},{packageName:"postcss-nesting",id:"nesting-rules",importName:"postcssNesting"},{packageName:"@csstools/postcss-normalize-display-values",id:"display-two-values",importName:"postcssNormalizeDisplayValues"},{packageName:"@csstools/postcss-oklab-function",id:"oklab-function",importName:"postcssOKLabFunction"},{packageName:"postcss-opacity-percentage",id:"opacity-percentage",importName:"postcssOpacityPercentage"},{packageName:"postcss-overflow-shorthand",id:"overflow-property",importName:"postcssOverflowShorthand"},{packageName:"postcss-page-break",id:"break-properties",importName:"postcssPageBreak"},{packageName:"postcss-place",id:"place-properties",importName:"postcssPlace"},{packageName:"postcss-pseudo-class-any-link",id:"any-link-pseudo-class",importName:"postcssPseudoClassAnyLink"},{packageName:"postcss-replace-overflow-wrap",id:"overflow-wrap-property",importName:"postcssReplaceOverflowWrap"},{packageName:"postcss-selector-not",id:"not-pseudo-class",importName:"postcssSelectorNot"},{packageName:"@csstools/postcss-stepped-value-functions",id:"stepped-value-functions",importName:"postcssSteppedValueFunctions"},{packageName:"postcss-system-ui-font-family",importedPackage:"../patch/postcss-system-ui-font-family.mjs",id:"system-ui-font-family",importName:"postcssFontFamilySystemUI"},{packageName:"@csstools/postcss-unset-value",id:"unset-value",importName:"postcssUnsetValue"},{packageName:"@csstools/postcss-cascade-layers",id:"cascade-layers",importName:"postcssCascadeLayers"},{packageName:"@csstools/postcss-trigonometric-functions",id:"trigonometric-functions",importName:"postcssTrigonometricFunctions"},{packageName:"@csstools/postcss-nested-calc",id:"nested-calc",importName:"postcssNestedCalc"},{packageName:"@csstools/postcss-text-decoration-shorthand",id:"text-decoration-shorthand",importName:"postcssTextDecorationShorthand"}];function getPackageNamesToIds(){const s={};return cs.forEach((e=>{s[e.packageName]=e.id})),s}function pluginIdHelp(s,e,o){const t=cs.map((s=>s.id)),r=cs.map((s=>s.packageName)),i=getPackageNamesToIds();s.forEach((s=>{if(t.includes(s))return;const a=mostSimilar(s,t),p=mostSimilar(s,r);Math.min(a.distance,p.distance)>10?e.warn(o`Unknown feature: "${s}", see the list of features https://github.com/csstools/postcss-plugins/blob/main/plugin-packs/postcss-preset-env/FEATURES.md`):a.distance{const r=new Logger,i=Object(t),a=Object.keys(Object(i.features)),p=i.browsers,n=initializeSharedOptions(i),c=listFeatures(e,i,n,r),l=c.map((s=>s.plugin));!1!==i.autoprefixer&&l.push(s(Object.assign({overrideBrowserslist:p},i.autoprefixer))),l.push(o()),logFeaturesList(c,i,r);const internalPlugin=()=>({postcssPlugin:"postcss-preset-env",OnceExit:function(s,{result:e}){pluginIdHelp(a,s,e),i.debug&&r.dumpLogs(e),r.resetLogger()}});return internalPlugin.postcss=!0,{postcssPlugin:"postcss-preset-env",plugins:[...l,internalPlugin()]}};creator.postcss=!0;export{creator as default}; +import s from"autoprefixer";import e from"cssdb";import o from"@csstools/postcss-progressive-custom-properties";import t from"browserslist";import i from"postcss-initial";import a from"postcss-pseudo-class-any-link";import r from"css-blank-pseudo";import p from"postcss-page-break";import c from"@csstools/postcss-cascade-layers";import n from"postcss-attribute-case-insensitive";import l from"postcss-clamp";import m from"@csstools/postcss-color-function";import u from"postcss-color-functional-notation";import d from"postcss-custom-media";import f from"postcss-custom-properties";import g from"postcss-custom-selectors";import b from"postcss-dir-pseudo-class";import h from"@csstools/postcss-normalize-display-values";import N from"postcss-double-position-gradients";import v from"@csstools/postcss-logical-float-and-clear";import y from"postcss-focus-visible";import k from"postcss-focus-within";import w from"@csstools/postcss-font-format-keywords";import F from"postcss-font-variant";import S from"postcss-gap-properties";import O from"css-has-pseudo";import $ from"postcss-color-hex-alpha";import x from"@csstools/postcss-hwb-function";import P from"@csstools/postcss-ic-unit";import C from"postcss-image-set-function";import E from"@csstools/postcss-is-pseudo-class";import I from"postcss-lab-function";import B from"postcss-logical";import U from"@csstools/postcss-logical-resize";import _ from"@csstools/postcss-logical-viewport-units";import q from"@csstools/postcss-media-queries-aspect-ratio-number-values";import L from"postcss-media-minmax";import A from"@csstools/postcss-nested-calc";import R from"postcss-nesting";import j from"postcss-selector-not";import M from"@csstools/postcss-oklab-function";import D from"postcss-opacity-percentage";import V from"postcss-overflow-shorthand";import W from"postcss-replace-overflow-wrap";import z from"postcss-place";import T from"css-prefers-color-scheme";import H from"postcss-color-rebeccapurple";import G from"@csstools/postcss-scope-pseudo-class";import J from"@csstools/postcss-stepped-value-functions";import K from"@csstools/postcss-text-decoration-shorthand";import Z from"@csstools/postcss-trigonometric-functions";import Q from"@csstools/postcss-unset-value";const X={"blank-pseudo-class":"https://github.com/csstools/postcss-plugins/blob/main/plugins/css-blank-pseudo/README-BROWSER.md","focus-visible-pseudo-class":"https://github.com/WICG/focus-visible","focus-within-pseudo-class":"https://github.com/jsxtools/focus-within/blob/master/README-BROWSER.md","has-pseudo-class":"https://github.com/csstools/postcss-plugins/blob/main/plugins/css-has-pseudo/README-BROWSER.md","prefers-color-scheme-query":"https://github.com/csstools/postcss-plugins/blob/main/plugins/css-prefers-color-scheme/README-BROWSER.md"},Y=["blank-pseudo-class","focus-visible-pseudo-class","focus-within-pseudo-class","has-pseudo-class","prefers-color-scheme-query"];function logFeaturesList(s,e,o){if(e.debug){o.log("Enabling the following feature(s):");const t=[],i=[];!1!==e.autoprefixer&&i.push(" autoprefixer"),s.forEach((s=>{s.id.startsWith("before")||s.id.startsWith("after")?i.push(` ${s.id} (injected via options)`):i.push(` ${s.id}`),void 0!==X[s.id]&&t.push(s.id)})),i.sort(((s,e)=>s.localeCompare(e))),t.sort(((s,e)=>s.localeCompare(e))),i.forEach((s=>o.log(s))),t.length&&(o.log("These feature(s) need a browser library to work:"),t.forEach((s=>o.log(` ${s}: ${X[s]}`))))}}function initializeSharedOptions(s){if("preserve"in s){const e={};return e.preserve=s.preserve,e}return!1}function clamp(s,e,o){return Math.max(s,Math.min(e,o))}function stageFromOptions(s,e){let o=2;if(void 0===s.stage)return e.log(`Using features from Stage ${o} (default)`),o;if(!1===s.stage)o=5;else{let e=parseInt(s.stage,10);Number.isNaN(e)&&(e=0),o=clamp(0,e,5)}return 5===o?e.log('Stage has been disabled, features will be handled via the "features" option.'):e.log(`Using features from Stage ${o}`),o}const ss=Symbol("insertBefore"),es=Symbol("insertAfter"),os=Symbol("insertOrder"),ts=Symbol("plugin");function getTransformedInsertions(s,e,o){if("insertBefore"!==o&&"insertAfter"!==o)return[];const t="insertBefore"===o?ss:es,i=[];for(const o in e){if(!Object.hasOwnProperty.call(e,o))continue;if(!s.find((s=>s.id===o)))continue;let a=e[o];Array.isArray(a)||(a=[a]);for(let s=0;sfeatureIsInsertedOrHasAPlugin(s))).sort(((s,e)=>featureIsLess(s,e)))}const ms=["and_chr","and_ff","and_qq","and_uc","android","baidu","chrome","edge","firefox","ie","ie_mob","ios_saf","kaios","op_mini","op_mob","opera","safari","samsung"];function getUnsupportedBrowsersByFeature(s){if(!s)return[];if(!("browser_support"in s))return["> 0%"];const e=[];return ms.forEach((o=>{if("op_mini"===o&&void 0===s.browser_support[o])return void e.push("op_mini all");const t=s.browser_support[o];"string"==typeof t&&/^[0-9|.]+$/.test(t)?e.push(`${o} < ${s.browser_support[o]}`):e.push(`${o} >= 1`)})),e}function getOptionsForBrowsersByFeature(s,e,o,i,a){const r=t(s,{ignoreUnknownVersions:!0});switch(e.id){case"is-pseudo-class":return{onComplexSelector:"warning"};case"nesting-rules":if(needsOptionFor(o.find((s=>"is-pseudo-class"===s.id)),r))return a.log('Disabling :is on "nesting-rules" due to lack of browser support.'),{noIsPseudoSelector:!0};return{};case"any-link-pseudo-class":if(r.find((s=>s.startsWith("ie ")||s.startsWith("edge "))))return a.log('Adding area[href] fallbacks for ":any-link" support in Edge and IE.'),{subFeatures:{areaHrefNeedsFixing:!0}};return{};case"logical-properties-and-values":case"float-clear-logical-values":case"logical-resize":case"logical-viewport-units":return"logical"in i?i.logical:{};default:return{}}}function needsOptionFor(s,e){const o=getUnsupportedBrowsersByFeature(s);return!!e.some((s=>t(o,{ignoreUnknownVersions:!0}).some((e=>e===s))))}function formatPolyfillableFeature(s){const e=getUnsupportedBrowsersByFeature(s);if(s[ss]||s[es]){let o=s.id;return o=s.insertBefore?`before-${o}`:`after-${o}`,{browsers:e,vendors_implementations:s.vendors_implementations,plugin:s[ts],id:o,stage:6}}return{browsers:e,vendors_implementations:s.vendors_implementations,plugin:ls.get(s.id),id:s.id,stage:s.stage}}function formatStagedFeature(s,e,o,t,i,a,r){let p,c;return p=getOptionsForBrowsersByFeature(e,t,s,a,r),!0===o[t.id]?i&&(p=Object.assign({},p,i)):p=i?Object.assign({},p,i,o[t.id]):Object.assign({},p,o[t.id]),p.enableProgressiveCustomProperties=!1,"all-property"===t.id&&"preserve"in p&&(p.replace=p.preserve),"overflow-wrap-property"===t.id&&"preserve"in p&&(p.method=p.preserve?"copy":"replace"),c=t.plugin.postcss&&"function"==typeof t.plugin?t.plugin(p):t.plugin&&t.plugin.default&&"function"==typeof t.plugin.default&&t.plugin.default.postcss?t.plugin.default(p):t.plugin,{browsers:t.browsers,vendors_implementations:t.vendors_implementations,plugin:c,pluginOptions:p,id:t.id}}function intOrZero(s){const e=parseInt(s,10);return Number.isNaN(e)?0:e}function listFeatures(s,e,o,i){const a=Object(e.features),r="enableClientSidePolyfills"in e&&e.enableClientSidePolyfills,p=Object(e.insertBefore),c=Object(e.insertAfter),n=e.browsers,l=clamp(0,intOrZero(e.minimumVendorImplementations),3);l>0&&i.log(`Using features with ${l} or more vendor implementations`);const m=stageFromOptions(e,i);2===m&&o&&!1===o.preserve&&(s=JSON.parse(JSON.stringify(s))).forEach((s=>{("blank-pseudo-class"===s.id||"prefers-color-scheme-query"===s.id)&&(s.stage=1)}));const u=prepareFeaturesList(s,p,c).map((s=>formatPolyfillableFeature(s))).filter((s=>0===l||(!(!s[ss]&&!s[es])||(l<=s.vendors_implementations||(a[s.id]?(i.log(` ${s.id} does not meet the required vendor implementations but has been enabled by options`),!0):(i.log(` ${s.id} with ${s.vendors_implementations} vendor implementations has been disabled`),!1)))))).filter((s=>{const e=s.stage>=m,o=r||!Y.includes(s.id),t=!1===a[s.id],p=a[s.id]?a[s.id]:e&&o;return t?i.log(` ${s.id} has been disabled by options`):e?o||i.log(` ${s.id} has been disabled by "enableClientSidePolyfills: false".`):p?i.log(` ${s.id} does not meet the required stage but has been enabled by options`):i.log(` ${s.id} with stage ${s.stage} has been disabled`),p})).map((t=>formatStagedFeature(s,n,a,t,o,e,i))),d=t(n,{ignoreUnknownVersions:!0});return u.filter((s=>{if(s.id in a)return a[s.id];const e=t(s.browsers,{ignoreUnknownVersions:!0}),o=d.some((s=>e.some((e=>e===s))));return o||i.log(`${s.id} disabled due to browser support`),o}))}class Logger{constructor(){this.logs=[]}log(s){this.logs.push(s)}resetLogger(){this.logs.length=0}dumpLogs(s){s&&this.logs.forEach((e=>s.warn(e))),this.resetLogger()}}var us=[{packageName:"css-blank-pseudo",id:"blank-pseudo-class",importName:"postcssBlankPseudo"},{packageName:"css-has-pseudo",id:"has-pseudo-class",importName:"postcssHasPseudo"},{packageName:"css-prefers-color-scheme",id:"prefers-color-scheme-query",importName:"postcssPrefersColorScheme"},{packageName:"postcss-attribute-case-insensitive",id:"case-insensitive-attributes",importName:"postcssAttributeCaseInsensitive"},{packageName:"postcss-clamp",id:"clamp",importName:"postcssClamp"},{packageName:"@csstools/postcss-color-function",id:"color-function",importName:"postcssColorFunction"},{packageName:"postcss-color-functional-notation",id:"color-functional-notation",importName:"postcssColorFunctionalNotation"},{packageName:"postcss-color-hex-alpha",id:"hexadecimal-alpha-notation",importName:"postcssColorHexAlpha"},{packageName:"postcss-color-rebeccapurple",id:"rebeccapurple-color",importName:"postcssColorRebeccapurple"},{packageName:"postcss-custom-media",id:"custom-media-queries",importName:"postcssCustomMedia"},{packageName:"postcss-custom-properties",id:"custom-properties",importName:"postcssCustomProperties"},{packageName:"postcss-custom-selectors",id:"custom-selectors",importName:"postcssCustomSelectors"},{packageName:"postcss-dir-pseudo-class",id:"dir-pseudo-class",importName:"postcssDirPseudoClass"},{packageName:"postcss-double-position-gradients",id:"double-position-gradients",importName:"postcssDoublePositionGradients"},{packageName:"postcss-focus-visible",id:"focus-visible-pseudo-class",importName:"postcssFocusVisible"},{packageName:"postcss-focus-within",id:"focus-within-pseudo-class",importName:"postcssFocusWithin"},{packageName:"@csstools/postcss-font-format-keywords",id:"font-format-keywords",importName:"postcssFontFormatKeywords"},{packageName:"postcss-font-variant",id:"font-variant-property",importName:"postcssFontVariant"},{packageName:"postcss-gap-properties",id:"gap-properties",importName:"postcssGapProperties"},{packageName:"@csstools/postcss-hwb-function",id:"hwb-function",importName:"postcssHWBFunction"},{packageName:"@csstools/postcss-ic-unit",id:"ic-unit",importName:"postcssICUnit"},{packageName:"postcss-image-set-function",id:"image-set-function",importName:"postcssImageSetFunction"},{packageName:"postcss-initial",id:"all-property",importName:"postcssInitial"},{packageName:"@csstools/postcss-is-pseudo-class",id:"is-pseudo-class",importName:"postcssIsPseudoClass"},{packageName:"@csstools/postcss-scope-pseudo-class",id:"scope-pseudo-class",importName:"postcssScopePseudoClass"},{packageName:"postcss-lab-function",id:"lab-function",importName:"postcssLabFunction"},{packageName:"postcss-logical",id:"logical-properties-and-values",importName:"postcssLogical"},{packageName:"@csstools/postcss-logical-float-and-clear",id:"float-clear-logical-values",importName:"postcssLogicalFloatAndClear"},{packageName:"@csstools/postcss-logical-resize",id:"logical-resize",importName:"postcssLogicalResize"},{packageName:"@csstools/postcss-logical-viewport-units",id:"logical-viewport-units",importName:"postcssLogicalViewportUnits"},{packageName:"postcss-media-minmax",id:"media-query-ranges",importName:"postcssMediaMinmax"},{packageName:"@csstools/postcss-media-queries-aspect-ratio-number-values",id:"media-queries-aspect-ratio-number-values",importName:"postcssMediaQueriesAspectRatioNumberValues"},{packageName:"postcss-nesting",id:"nesting-rules",importName:"postcssNesting"},{packageName:"@csstools/postcss-normalize-display-values",id:"display-two-values",importName:"postcssNormalizeDisplayValues"},{packageName:"@csstools/postcss-oklab-function",id:"oklab-function",importName:"postcssOKLabFunction"},{packageName:"postcss-opacity-percentage",id:"opacity-percentage",importName:"postcssOpacityPercentage"},{packageName:"postcss-overflow-shorthand",id:"overflow-property",importName:"postcssOverflowShorthand"},{packageName:"postcss-page-break",id:"break-properties",importName:"postcssPageBreak"},{packageName:"postcss-place",id:"place-properties",importName:"postcssPlace"},{packageName:"postcss-pseudo-class-any-link",id:"any-link-pseudo-class",importName:"postcssPseudoClassAnyLink"},{packageName:"postcss-replace-overflow-wrap",id:"overflow-wrap-property",importName:"postcssReplaceOverflowWrap"},{packageName:"postcss-selector-not",id:"not-pseudo-class",importName:"postcssSelectorNot"},{packageName:"@csstools/postcss-stepped-value-functions",id:"stepped-value-functions",importName:"postcssSteppedValueFunctions"},{packageName:"postcss-system-ui-font-family",importedPackage:"../patch/postcss-system-ui-font-family.mjs",id:"system-ui-font-family",importName:"postcssFontFamilySystemUI"},{packageName:"@csstools/postcss-unset-value",id:"unset-value",importName:"postcssUnsetValue"},{packageName:"@csstools/postcss-cascade-layers",id:"cascade-layers",importName:"postcssCascadeLayers"},{packageName:"@csstools/postcss-trigonometric-functions",id:"trigonometric-functions",importName:"postcssTrigonometricFunctions"},{packageName:"@csstools/postcss-nested-calc",id:"nested-calc",importName:"postcssNestedCalc"},{packageName:"@csstools/postcss-text-decoration-shorthand",id:"text-decoration-shorthand",importName:"postcssTextDecorationShorthand"}];function getPackageNamesToIds(){const s={};return us.forEach((e=>{s[e.packageName]=e.id})),s}function pluginIdHelp(s,e,o){const t=us.map((s=>s.id)),i=us.map((s=>s.packageName)),a=getPackageNamesToIds();s.forEach((s=>{if(t.includes(s))return;const r=mostSimilar(s,t),p=mostSimilar(s,i);Math.min(r.distance,p.distance)>10?e.warn(o`Unknown feature: "${s}", see the list of features https://github.com/csstools/postcss-plugins/blob/main/plugin-packs/postcss-preset-env/FEATURES.md`):r.distance{const i=new Logger,a=Object(t),r=Object.keys(Object(a.features)),p=a.browsers,c=initializeSharedOptions(a),n=listFeatures(e,a,c,i),l=n.map((s=>s.plugin));!1!==a.autoprefixer&&l.push(s(Object.assign({overrideBrowserslist:p},a.autoprefixer))),l.push(o()),logFeaturesList(n,a,i);const internalPlugin=()=>({postcssPlugin:"postcss-preset-env",OnceExit:function(s,{result:e}){pluginIdHelp(r,s,e),a.debug&&i.dumpLogs(e),i.resetLogger()}});return internalPlugin.postcss=!0,{postcssPlugin:"postcss-preset-env",plugins:[...l,internalPlugin()]}};creator.postcss=!0;export{creator as default}; diff --git a/plugin-packs/postcss-preset-env/dist/options.d.ts b/plugin-packs/postcss-preset-env/dist/options.d.ts index 349b88099..dd1ee72d8 100644 --- a/plugin-packs/postcss-preset-env/dist/options.d.ts +++ b/plugin-packs/postcss-preset-env/dist/options.d.ts @@ -1,5 +1,11 @@ import type autoprefixer from 'autoprefixer'; import { pluginsOptions } from './plugins/plugins-options'; +export declare enum DirectionFlow { + TopToBottom = "top-to-bottom", + BottomToTop = "bottom-to-top", + RightToLeft = "right-to-left", + LeftToRight = "left-to-right" +} export type pluginOptions = { /** * Determine which CSS features to polyfill, @@ -63,4 +69,14 @@ export type pluginOptions = { * default: false */ debug?: boolean; + /** + * The `logical` object allows to configure all plugins related to logical document flow at once. + * It accepts the same options as each plugin: `inlineDirection` and `blockDirection`. + */ + logical?: { + /** Set the inline flow direction. default: left-to-right */ + inlineDirection?: DirectionFlow; + /** Set the block flow direction. default: top-to-bottom */ + blockDirection?: DirectionFlow; + }; }; diff --git a/plugin-packs/postcss-preset-env/dist/plugins/plugins-options.d.ts b/plugin-packs/postcss-preset-env/dist/plugins/plugins-options.d.ts index 7be79c4be..013d7421e 100644 --- a/plugin-packs/postcss-preset-env/dist/plugins/plugins-options.d.ts +++ b/plugin-packs/postcss-preset-env/dist/plugins/plugins-options.d.ts @@ -13,6 +13,7 @@ import type { pluginOptions as postcssCustomSelectors } from 'postcss-custom-sel import type { pluginOptions as postcssDirPseudoClass } from 'postcss-dir-pseudo-class'; import type { pluginOptions as postcssNormalizeDisplayValues } from '@csstools/postcss-normalize-display-values'; import type { pluginOptions as postcssDoublePositionGradients } from 'postcss-double-position-gradients'; +import type { pluginOptions as postcssLogicalFloatAndClear } from '@csstools/postcss-logical-float-and-clear'; import type { pluginOptions as postcssFocusVisible } from 'postcss-focus-visible'; import type { pluginOptions as postcssFocusWithin } from 'postcss-focus-within'; import type { pluginOptions as postcssFontFormatKeywords } from '@csstools/postcss-font-format-keywords'; @@ -25,7 +26,9 @@ import type { pluginOptions as postcssICUnit } from '@csstools/postcss-ic-unit'; import type { pluginOptions as postcssImageSetFunction } from 'postcss-image-set-function'; import type { pluginOptions as postcssIsPseudoClass } from '@csstools/postcss-is-pseudo-class'; import type { pluginOptions as postcssLabFunction } from 'postcss-lab-function'; -import type { pluginOptions as postcssLogical } from '../types/postcss-logical/plugin-options'; +import type { pluginOptions as postcssLogical } from 'postcss-logical'; +import type { pluginOptions as postcssLogicalResize } from '@csstools/postcss-logical-resize'; +import type { pluginOptions as postcssLogicalViewportUnits } from '@csstools/postcss-logical-viewport-units'; import type { pluginOptions as postcssMediaQueriesAspectRatioNumberValues } from '@csstools/postcss-media-queries-aspect-ratio-number-values'; import type { pluginOptions as postcssMediaMinmax } from '../types/postcss-media-minmax/plugin-options'; import type { pluginOptions as postcssNestedCalc } from '@csstools/postcss-nested-calc'; @@ -75,6 +78,8 @@ export type pluginsOptions = { 'display-two-values'?: postcssNormalizeDisplayValues | boolean; /** plugin options for "postcss-double-position-gradients" */ 'double-position-gradients'?: postcssDoublePositionGradients | boolean; + /** plugin options for "@csstools/postcss-logical-float-and-clear" */ + 'float-clear-logical-values'?: postcssLogicalFloatAndClear | boolean; /** plugin options for "postcss-focus-visible" */ 'focus-visible-pseudo-class'?: postcssFocusVisible | boolean; /** plugin options for "postcss-focus-within" */ @@ -101,6 +106,10 @@ export type pluginsOptions = { 'lab-function'?: postcssLabFunction | boolean; /** plugin options for "postcss-logical" */ 'logical-properties-and-values'?: postcssLogical | boolean; + /** plugin options for "@csstools/postcss-logical-resize" */ + 'logical-resize'?: postcssLogicalResize | boolean; + /** plugin options for "@csstools/postcss-logical-viewport-units" */ + 'logical-viewport-units'?: postcssLogicalViewportUnits | boolean; /** plugin options for "@csstools/postcss-media-queries-aspect-ratio-number-values" */ 'media-queries-aspect-ratio-number-values'?: postcssMediaQueriesAspectRatioNumberValues | boolean; /** plugin options for "postcss-media-minmax" */ diff --git a/plugin-packs/postcss-preset-env/dist/types/postcss-logical/plugin-options.d.ts b/plugin-packs/postcss-preset-env/dist/types/postcss-logical/plugin-options.d.ts deleted file mode 100644 index 0f5b4789d..000000000 --- a/plugin-packs/postcss-preset-env/dist/types/postcss-logical/plugin-options.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** postcss-logical plugin options */ -export type pluginOptions = { - /** Preserve the original notation. default: false */ - preserve?: boolean; - /** Assume a direction for the document. default: null */ - dir?: 'ltr' | 'rtl'; -}; diff --git a/plugin-packs/postcss-preset-env/package.json b/plugin-packs/postcss-preset-env/package.json index cf4bf7c5e..ea709a458 100644 --- a/plugin-packs/postcss-preset-env/package.json +++ b/plugin-packs/postcss-preset-env/package.json @@ -34,6 +34,9 @@ "@csstools/postcss-hwb-function": "^1.0.2", "@csstools/postcss-ic-unit": "^1.0.1", "@csstools/postcss-is-pseudo-class": "^2.0.7", + "@csstools/postcss-logical-float-and-clear": "^1.0.0", + "@csstools/postcss-logical-resize": "^1.0.0", + "@csstools/postcss-logical-viewport-units": "^1.0.0", "@csstools/postcss-media-queries-aspect-ratio-number-values": "^1.0.0", "@csstools/postcss-nested-calc": "^1.0.0", "@csstools/postcss-normalize-display-values": "^1.0.1", @@ -55,7 +58,7 @@ "postcss-color-functional-notation": "^4.2.4", "postcss-color-hex-alpha": "^8.0.4", "postcss-color-rebeccapurple": "^7.1.1", - "postcss-custom-media": "^9.0.0", + "postcss-custom-media": "^9.0.1", "postcss-custom-properties": "^13.0.0", "postcss-custom-selectors": "^7.0.0", "postcss-dir-pseudo-class": "^6.0.5", @@ -70,7 +73,7 @@ "postcss-logical": "^5.0.4", "postcss-media-minmax": "^5.0.0", "postcss-nesting": "^10.2.0", - "postcss-opacity-percentage": "^1.1.2", + "postcss-opacity-percentage": "^1.1.3", "postcss-overflow-shorthand": "^3.0.4", "postcss-page-break": "^3.0.4", "postcss-place": "^7.0.5", @@ -83,7 +86,7 @@ "postcss": "^8.4" }, "devDependencies": { - "postcss-simple-vars": "^7.0.0" + "postcss-simple-vars": "^7.0.1" }, "scripts": { "prebuild": "node ./scripts/generate-plugins-data.mjs && eslint --fix ./src/plugins/*.mjs && npm run clean", diff --git a/plugin-packs/postcss-preset-env/scripts/plugins-data.json b/plugin-packs/postcss-preset-env/scripts/plugins-data.json index f3a3454d5..e5057da40 100644 --- a/plugin-packs/postcss-preset-env/scripts/plugins-data.json +++ b/plugin-packs/postcss-preset-env/scripts/plugins-data.json @@ -134,6 +134,21 @@ "id": "logical-properties-and-values", "importName": "postcssLogical" }, + { + "packageName": "@csstools/postcss-logical-float-and-clear", + "id": "float-clear-logical-values", + "importName": "postcssLogicalFloatAndClear" + }, + { + "packageName": "@csstools/postcss-logical-resize", + "id": "logical-resize", + "importName": "postcssLogicalResize" + }, + { + "packageName": "@csstools/postcss-logical-viewport-units", + "id": "logical-viewport-units", + "importName": "postcssLogicalViewportUnits" + }, { "packageName": "postcss-media-minmax", "id": "media-query-ranges", diff --git a/plugin-packs/postcss-preset-env/src/index.ts b/plugin-packs/postcss-preset-env/src/index.ts index 61826c771..86265d685 100644 --- a/plugin-packs/postcss-preset-env/src/index.ts +++ b/plugin-packs/postcss-preset-env/src/index.ts @@ -20,9 +20,7 @@ const creator: PluginCreator = (opts?: pluginOptions) => { const sharedOptions = initializeSharedOptions(options); const features = listFeatures(cssdb, options, sharedOptions, logger); - const plugins = features.map((feature) => { - return feature.plugin; - }); + const plugins = features.map((feature) => feature.plugin); if (options.autoprefixer !== false) { plugins.push( diff --git a/plugin-packs/postcss-preset-env/src/lib/format-feature.mjs b/plugin-packs/postcss-preset-env/src/lib/format-feature.mjs index 671fd0019..750c1e1a7 100644 --- a/plugin-packs/postcss-preset-env/src/lib/format-feature.mjs +++ b/plugin-packs/postcss-preset-env/src/lib/format-feature.mjs @@ -33,41 +33,41 @@ export function formatPolyfillableFeature(feature) { }; } -export function formatStagedFeature(cssdbList, browsers, features, feature, sharedOptions, logger) { - let options; +export function formatStagedFeature(cssdbList, browsers, features, feature, sharedOptions, options, logger) { + let pluginOption; let plugin; - options = getOptionsForBrowsersByFeature(browsers, feature, cssdbList, logger); + pluginOption = getOptionsForBrowsersByFeature(browsers, feature, cssdbList, options, logger); if (features[feature.id] === true) { if (sharedOptions) { - options = Object.assign({}, options, sharedOptions); + pluginOption = Object.assign({}, pluginOption, sharedOptions); } } else { if (sharedOptions) { - options = Object.assign({}, options, sharedOptions, features[feature.id]); + pluginOption = Object.assign({}, pluginOption, sharedOptions, features[feature.id]); } else { - options = Object.assign({}, options, features[feature.id]); + pluginOption = Object.assign({}, pluginOption, features[feature.id]); } } // postcss-preset-env : option overrides - options.enableProgressiveCustomProperties = false; + pluginOption.enableProgressiveCustomProperties = false; // https://github.com/maximkoretskiy/postcss-initial#replace - if (feature.id === 'all-property' && 'preserve' in options) { - options.replace = options.preserve; + if (feature.id === 'all-property' && 'preserve' in pluginOption) { + pluginOption.replace = pluginOption.preserve; } // https://github.com/MattDiMu/postcss-replace-overflow-wrap/blob/ec9914e0b9473a75a5d1fe32ea4311555eb81b71/index.js#L10 - if (feature.id === 'overflow-wrap-property' && 'preserve' in options) { - options.method = options.preserve ? 'copy' : 'replace'; + if (feature.id === 'overflow-wrap-property' && 'preserve' in pluginOption) { + pluginOption.method = pluginOption.preserve ? 'copy' : 'replace'; } if (feature.plugin.postcss && typeof feature.plugin === 'function') { - plugin = feature.plugin(options); + plugin = feature.plugin(pluginOption); } else if (feature.plugin && feature.plugin.default && typeof feature.plugin.default === 'function' && feature.plugin.default.postcss) { - plugin = feature.plugin.default(options); + plugin = feature.plugin.default(pluginOption); } else { plugin = feature.plugin; } @@ -76,7 +76,7 @@ export function formatStagedFeature(cssdbList, browsers, features, feature, shar browsers: feature.browsers, vendors_implementations: feature.vendors_implementations, plugin: plugin, - pluginOptions: options, + pluginOptions: pluginOption, id: feature.id, }; } diff --git a/plugin-packs/postcss-preset-env/src/lib/get-options-for-browsers-by-feature.mjs b/plugin-packs/postcss-preset-env/src/lib/get-options-for-browsers-by-feature.mjs index f1db958cf..0dbe0f2aa 100644 --- a/plugin-packs/postcss-preset-env/src/lib/get-options-for-browsers-by-feature.mjs +++ b/plugin-packs/postcss-preset-env/src/lib/get-options-for-browsers-by-feature.mjs @@ -2,7 +2,7 @@ import browserslist from 'browserslist'; import getUnsupportedBrowsersByFeature from './get-unsupported-browsers-by-feature.mjs'; // add extra options for certain browsers by feature -export default function getOptionsForBrowsersByFeature(browsers, feature, cssdbList, logger) { +export default function getOptionsForBrowsersByFeature(browsers, feature, cssdbList, options, logger) { const supportedBrowsers = browserslist(browsers, { ignoreUnknownVersions: true }); switch (feature.id) { @@ -45,6 +45,17 @@ export default function getOptionsForBrowsersByFeature(browsers, feature, cssdbL } } + return {}; + case 'logical-properties-and-values': + case 'float-clear-logical-values': + case 'logical-resize': + case 'logical-viewport-units': + { + if ('logical' in options) { + return options.logical; + } + } + return {}; default: diff --git a/plugin-packs/postcss-preset-env/src/lib/list-features.mjs b/plugin-packs/postcss-preset-env/src/lib/list-features.mjs index b892ad48d..e5a62b128 100644 --- a/plugin-packs/postcss-preset-env/src/lib/list-features.mjs +++ b/plugin-packs/postcss-preset-env/src/lib/list-features.mjs @@ -93,7 +93,7 @@ export function listFeatures(cssdbList, options, sharedOptions, logger) { return isAllowedFeature; }).map((feature) => { - return formatStagedFeature(cssdbList, browsers, features, feature, sharedOptions, logger); + return formatStagedFeature(cssdbList, browsers, features, feature, sharedOptions, options, logger); }); // browsers supported by the configuration diff --git a/plugin-packs/postcss-preset-env/src/lib/shared-options.mjs b/plugin-packs/postcss-preset-env/src/lib/shared-options.mjs index fa46a98a5..7444c8aa4 100644 --- a/plugin-packs/postcss-preset-env/src/lib/shared-options.mjs +++ b/plugin-packs/postcss-preset-env/src/lib/shared-options.mjs @@ -1,11 +1,7 @@ export function initializeSharedOptions(opts) { if ('preserve' in opts) { const sharedOptions = {}; - - if ('preserve' in opts) { - sharedOptions.preserve = opts.preserve; - } - + sharedOptions.preserve = opts.preserve; return sharedOptions; } diff --git a/plugin-packs/postcss-preset-env/src/options.ts b/plugin-packs/postcss-preset-env/src/options.ts index fad49438a..a9de6f868 100644 --- a/plugin-packs/postcss-preset-env/src/options.ts +++ b/plugin-packs/postcss-preset-env/src/options.ts @@ -1,6 +1,13 @@ import type autoprefixer from 'autoprefixer'; import { pluginsOptions } from './plugins/plugins-options'; +export enum DirectionFlow { + TopToBottom = 'top-to-bottom', + BottomToTop = 'bottom-to-top', + RightToLeft = 'right-to-left', + LeftToRight = 'left-to-right', +} + export type pluginOptions = { /** * Determine which CSS features to polyfill, @@ -73,4 +80,15 @@ export type pluginOptions = { * default: false */ debug?: boolean + + /** + * The `logical` object allows to configure all plugins related to logical document flow at once. + * It accepts the same options as each plugin: `inlineDirection` and `blockDirection`. + */ + logical?: { + /** Set the inline flow direction. default: left-to-right */ + inlineDirection?: DirectionFlow + /** Set the block flow direction. default: top-to-bottom */ + blockDirection?: DirectionFlow + } } diff --git a/plugin-packs/postcss-preset-env/src/plugins/plugins-by-id.mjs b/plugin-packs/postcss-preset-env/src/plugins/plugins-by-id.mjs index 94d133417..34fc27466 100644 --- a/plugin-packs/postcss-preset-env/src/plugins/plugins-by-id.mjs +++ b/plugin-packs/postcss-preset-env/src/plugins/plugins-by-id.mjs @@ -13,6 +13,7 @@ import postcssCustomSelectors from 'postcss-custom-selectors'; import postcssDirPseudoClass from 'postcss-dir-pseudo-class'; import postcssNormalizeDisplayValues from '@csstools/postcss-normalize-display-values'; import postcssDoublePositionGradients from 'postcss-double-position-gradients'; +import postcssLogicalFloatAndClear from '@csstools/postcss-logical-float-and-clear'; import postcssFocusVisible from 'postcss-focus-visible'; import postcssFocusWithin from 'postcss-focus-within'; import postcssFontFormatKeywords from '@csstools/postcss-font-format-keywords'; @@ -26,6 +27,8 @@ import postcssImageSetFunction from 'postcss-image-set-function'; import postcssIsPseudoClass from '@csstools/postcss-is-pseudo-class'; import postcssLabFunction from 'postcss-lab-function'; import postcssLogical from 'postcss-logical'; +import postcssLogicalResize from '@csstools/postcss-logical-resize'; +import postcssLogicalViewportUnits from '@csstools/postcss-logical-viewport-units'; import postcssMediaQueriesAspectRatioNumberValues from '@csstools/postcss-media-queries-aspect-ratio-number-values'; import postcssMediaMinmax from 'postcss-media-minmax'; import postcssNestedCalc from '@csstools/postcss-nested-calc'; @@ -63,6 +66,7 @@ export const pluginsById = new Map( ['dir-pseudo-class', postcssDirPseudoClass], ['display-two-values', postcssNormalizeDisplayValues], ['double-position-gradients', postcssDoublePositionGradients], + ['float-clear-logical-values', postcssLogicalFloatAndClear], ['focus-visible-pseudo-class', postcssFocusVisible], ['focus-within-pseudo-class', postcssFocusWithin], ['font-format-keywords', postcssFontFormatKeywords], @@ -76,6 +80,8 @@ export const pluginsById = new Map( ['is-pseudo-class', postcssIsPseudoClass], ['lab-function', postcssLabFunction], ['logical-properties-and-values', postcssLogical], + ['logical-resize', postcssLogicalResize], + ['logical-viewport-units', postcssLogicalViewportUnits], ['media-queries-aspect-ratio-number-values', postcssMediaQueriesAspectRatioNumberValues], ['media-query-ranges', postcssMediaMinmax], ['nested-calc', postcssNestedCalc], diff --git a/plugin-packs/postcss-preset-env/src/plugins/plugins-data.mjs b/plugin-packs/postcss-preset-env/src/plugins/plugins-data.mjs index a331cd0e8..4dadbaf80 100644 --- a/plugin-packs/postcss-preset-env/src/plugins/plugins-data.mjs +++ b/plugin-packs/postcss-preset-env/src/plugins/plugins-data.mjs @@ -134,6 +134,21 @@ export default [ 'id': 'logical-properties-and-values', 'importName': 'postcssLogical', }, + { + 'packageName': '@csstools/postcss-logical-float-and-clear', + 'id': 'float-clear-logical-values', + 'importName': 'postcssLogicalFloatAndClear', + }, + { + 'packageName': '@csstools/postcss-logical-resize', + 'id': 'logical-resize', + 'importName': 'postcssLogicalResize', + }, + { + 'packageName': '@csstools/postcss-logical-viewport-units', + 'id': 'logical-viewport-units', + 'importName': 'postcssLogicalViewportUnits', + }, { 'packageName': 'postcss-media-minmax', 'id': 'media-query-ranges', diff --git a/plugin-packs/postcss-preset-env/src/plugins/plugins-options.ts b/plugin-packs/postcss-preset-env/src/plugins/plugins-options.ts index 4083e70e7..236d6de65 100644 --- a/plugin-packs/postcss-preset-env/src/plugins/plugins-options.ts +++ b/plugin-packs/postcss-preset-env/src/plugins/plugins-options.ts @@ -13,6 +13,7 @@ import type { pluginOptions as postcssCustomSelectors } from 'postcss-custom-sel import type { pluginOptions as postcssDirPseudoClass } from 'postcss-dir-pseudo-class'; import type { pluginOptions as postcssNormalizeDisplayValues } from '@csstools/postcss-normalize-display-values'; import type { pluginOptions as postcssDoublePositionGradients } from 'postcss-double-position-gradients'; +import type { pluginOptions as postcssLogicalFloatAndClear } from '@csstools/postcss-logical-float-and-clear'; import type { pluginOptions as postcssFocusVisible } from 'postcss-focus-visible'; import type { pluginOptions as postcssFocusWithin } from 'postcss-focus-within'; import type { pluginOptions as postcssFontFormatKeywords } from '@csstools/postcss-font-format-keywords'; @@ -25,7 +26,9 @@ import type { pluginOptions as postcssICUnit } from '@csstools/postcss-ic-unit'; import type { pluginOptions as postcssImageSetFunction } from 'postcss-image-set-function'; import type { pluginOptions as postcssIsPseudoClass } from '@csstools/postcss-is-pseudo-class'; import type { pluginOptions as postcssLabFunction } from 'postcss-lab-function'; -import type { pluginOptions as postcssLogical } from '../types/postcss-logical/plugin-options'; +import type { pluginOptions as postcssLogical } from 'postcss-logical'; +import type { pluginOptions as postcssLogicalResize } from '@csstools/postcss-logical-resize'; +import type { pluginOptions as postcssLogicalViewportUnits } from '@csstools/postcss-logical-viewport-units'; import type { pluginOptions as postcssMediaQueriesAspectRatioNumberValues } from '@csstools/postcss-media-queries-aspect-ratio-number-values'; import type { pluginOptions as postcssMediaMinmax } from '../types/postcss-media-minmax/plugin-options'; import type { pluginOptions as postcssNestedCalc } from '@csstools/postcss-nested-calc'; @@ -76,6 +79,8 @@ export type pluginsOptions = { 'display-two-values'?: postcssNormalizeDisplayValues | boolean /** plugin options for "postcss-double-position-gradients" */ 'double-position-gradients'?: postcssDoublePositionGradients | boolean + /** plugin options for "@csstools/postcss-logical-float-and-clear" */ + 'float-clear-logical-values'?: postcssLogicalFloatAndClear | boolean /** plugin options for "postcss-focus-visible" */ 'focus-visible-pseudo-class'?: postcssFocusVisible | boolean /** plugin options for "postcss-focus-within" */ @@ -102,6 +107,10 @@ export type pluginsOptions = { 'lab-function'?: postcssLabFunction | boolean /** plugin options for "postcss-logical" */ 'logical-properties-and-values'?: postcssLogical | boolean + /** plugin options for "@csstools/postcss-logical-resize" */ + 'logical-resize'?: postcssLogicalResize | boolean + /** plugin options for "@csstools/postcss-logical-viewport-units" */ + 'logical-viewport-units'?: postcssLogicalViewportUnits | boolean /** plugin options for "@csstools/postcss-media-queries-aspect-ratio-number-values" */ 'media-queries-aspect-ratio-number-values'?: postcssMediaQueriesAspectRatioNumberValues | boolean /** plugin options for "postcss-media-minmax" */ diff --git a/plugin-packs/postcss-preset-env/src/test/lib/format-staged-feature.mjs b/plugin-packs/postcss-preset-env/src/test/lib/format-staged-feature.mjs index 8ec0fed1c..75609b446 100644 --- a/plugin-packs/postcss-preset-env/src/test/lib/format-staged-feature.mjs +++ b/plugin-packs/postcss-preset-env/src/test/lib/format-staged-feature.mjs @@ -18,6 +18,7 @@ assert.deepStrictEqual( vendors_implementations: 1, }, undefined, + undefined, testLogger.logger, ), { @@ -52,6 +53,7 @@ assert.deepStrictEqual( vendors_implementations: 1, }, undefined, + undefined, testLogger.logger, ), { @@ -88,6 +90,43 @@ assert.deepStrictEqual( { shared: true, }, + undefined, + testLogger.logger, + ), + { + browsers: [ + 'ie >= 1', + ], + vendors_implementations: 1, + plugin: true, + pluginOptions: { + subFeatures: { + areaHrefNeedsFixing: true, + }, + enableProgressiveCustomProperties: false, + shared: true, + }, + id: 'any-link-pseudo-class', + }, +); + +assert.deepStrictEqual( + formatStagedFeature( + [], + ['ie >= 1'], + {}, + { + id: 'any-link-pseudo-class', + plugin: true, + browsers: [ + 'ie >= 1', + ], + vendors_implementations: 1, + }, + { + shared: true, + }, + undefined, testLogger.logger, ), { @@ -107,6 +146,7 @@ assert.deepStrictEqual( }, ); +// Logical does not get passed to a non-logical plugin assert.deepStrictEqual( formatStagedFeature( [], @@ -123,6 +163,11 @@ assert.deepStrictEqual( { shared: true, }, + { + logical: { + inlineDirection: 'right-to-left', + }, + }, testLogger.logger, ), { @@ -141,3 +186,54 @@ assert.deepStrictEqual( id: 'any-link-pseudo-class', }, ); + + +{ +// Logical gets passed to a logical plugin + const logicalPlugins = [ + 'logical-properties-and-values', + 'float-clear-logical-values', + 'logical-resize', + 'logical-viewport-units', + ]; + + for (const plugin of logicalPlugins) { + assert.deepStrictEqual( + formatStagedFeature( + [], + ['ie >= 1'], + {}, + { + id: plugin, + plugin: true, + browsers: [ + 'ie >= 1', + ], + vendors_implementations: 1, + }, + { + shared: true, + }, + { + logical: { + inlineDirection: 'right-to-left', + }, + }, + testLogger.logger, + ), + { + browsers: [ + 'ie >= 1', + ], + vendors_implementations: 1, + plugin: true, + pluginOptions: { + enableProgressiveCustomProperties: false, + shared: true, + inlineDirection: 'right-to-left', + }, + id: plugin, + }, + ); + } +} diff --git a/plugin-packs/postcss-preset-env/src/types/postcss-logical/index.d.ts b/plugin-packs/postcss-preset-env/src/types/postcss-logical/index.d.ts deleted file mode 100644 index b672797f4..000000000 --- a/plugin-packs/postcss-preset-env/src/types/postcss-logical/index.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -declare module 'postcss-logical' { - /** postcss-logical plugin options */ - export type pluginOptions = { - /** Preserve the original notation. default: false */ - preserve?: boolean, - /** Assume a direction for the document. default: null */ - dir?: 'ltr' | 'rtl' - }; -} diff --git a/plugin-packs/postcss-preset-env/src/types/postcss-logical/plugin-options.ts b/plugin-packs/postcss-preset-env/src/types/postcss-logical/plugin-options.ts deleted file mode 100644 index ae080e6b5..000000000 --- a/plugin-packs/postcss-preset-env/src/types/postcss-logical/plugin-options.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** postcss-logical plugin options */ -export type pluginOptions = { - /** Preserve the original notation. default: false */ - preserve?: boolean, - /** Assume a direction for the document. default: null */ - dir?: 'ltr' | 'rtl' -}; diff --git a/plugin-packs/postcss-preset-env/test/basic.autoprefixer.expect.css b/plugin-packs/postcss-preset-env/test/basic.autoprefixer.expect.css index c64a04d58..573ccc0ad 100644 --- a/plugin-packs/postcss-preset-env/test/basic.autoprefixer.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.autoprefixer.expect.css @@ -30,18 +30,21 @@ } } -[dir="ltr"] .test-logical-properties-and-values { - margin: 1px 4px 3px 2px; +.test-logical-properties-and-values { + margin-left: 1px; + margin-right: 2px; + order: 3; + padding-top: 4px; + padding-bottom: 4px; } -[dir="rtl"] .test-logical-properties-and-values { - margin: 1px 2px 3px 4px; +.test-logical-resize { + resize: horizontal; } -.test-logical-properties-and-values { - order: 3; - padding-top: 5px; - padding-bottom: 5px; +.test-logical-viewport-units { + width: calc(10vw + 5px); + width: calc(10vi + 5px); } .test-nesting-rules { @@ -414,14 +417,10 @@ display: ruby-text flow; } -[dir="ltr"] .logical-float { +.logical-float { float: left; } -[dir="rtl"] .logical-float { - float: right; -} - .color-function { prop-1: rgb(0,132,94); prop-2: 'color(display-p3 0.02472 0.01150 0.00574 / 1)'; @@ -529,10 +528,7 @@ right: 3px; bottom: 3px; left: 2px; - top: 2px; - right: 2px; - bottom: 2px; - left: 2px; + padding-left: 2px; } .trigonometric { @@ -587,24 +583,11 @@ text-decoration-thickness: 3px; } -[dir="ltr"] .stage__container { +.stage__container { left: 1rem; left: var(--size, 1rem); } -[dir="rtl"] .stage__container { - right: 1rem; - right: var(--size, 1rem); -} - -[dir="ltr"] .stage__container { - left: 1rem; -} - -[dir="rtl"] .stage__container { - right: 1rem; -} - :root { content: "plain :scope"; } diff --git a/plugin-packs/postcss-preset-env/test/basic.autoprefixer.false.expect.css b/plugin-packs/postcss-preset-env/test/basic.autoprefixer.false.expect.css index c64a04d58..573ccc0ad 100644 --- a/plugin-packs/postcss-preset-env/test/basic.autoprefixer.false.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.autoprefixer.false.expect.css @@ -30,18 +30,21 @@ } } -[dir="ltr"] .test-logical-properties-and-values { - margin: 1px 4px 3px 2px; +.test-logical-properties-and-values { + margin-left: 1px; + margin-right: 2px; + order: 3; + padding-top: 4px; + padding-bottom: 4px; } -[dir="rtl"] .test-logical-properties-and-values { - margin: 1px 2px 3px 4px; +.test-logical-resize { + resize: horizontal; } -.test-logical-properties-and-values { - order: 3; - padding-top: 5px; - padding-bottom: 5px; +.test-logical-viewport-units { + width: calc(10vw + 5px); + width: calc(10vi + 5px); } .test-nesting-rules { @@ -414,14 +417,10 @@ display: ruby-text flow; } -[dir="ltr"] .logical-float { +.logical-float { float: left; } -[dir="rtl"] .logical-float { - float: right; -} - .color-function { prop-1: rgb(0,132,94); prop-2: 'color(display-p3 0.02472 0.01150 0.00574 / 1)'; @@ -529,10 +528,7 @@ right: 3px; bottom: 3px; left: 2px; - top: 2px; - right: 2px; - bottom: 2px; - left: 2px; + padding-left: 2px; } .trigonometric { @@ -587,24 +583,11 @@ text-decoration-thickness: 3px; } -[dir="ltr"] .stage__container { +.stage__container { left: 1rem; left: var(--size, 1rem); } -[dir="rtl"] .stage__container { - right: 1rem; - right: var(--size, 1rem); -} - -[dir="ltr"] .stage__container { - left: 1rem; -} - -[dir="rtl"] .stage__container { - right: 1rem; -} - :root { content: "plain :scope"; } diff --git a/plugin-packs/postcss-preset-env/test/basic.ch38.expect.css b/plugin-packs/postcss-preset-env/test/basic.ch38.expect.css index 28ea512cf..c92c1c8ea 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ch38.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ch38.expect.css @@ -23,18 +23,21 @@ order: 2; } -[dir="ltr"] .test-logical-properties-and-values { - margin: 1px 4px 3px 2px; +.test-logical-properties-and-values { + margin-left: 1px; + margin-right: 2px; + order: 3; + padding-top: 4px; + padding-bottom: 4px; } -[dir="rtl"] .test-logical-properties-and-values { - margin: 1px 2px 3px 4px; +.test-logical-resize { + resize: horizontal; } -.test-logical-properties-and-values { - order: 3; - padding-top: 5px; - padding-bottom: 5px; +.test-logical-viewport-units { + width: calc(10vw + 5px); + width: calc(10vi + 5px); } .test-nesting-rules { @@ -325,14 +328,10 @@ display: ruby-text flow; } -[dir="ltr"] .logical-float { +.logical-float { float: left; } -[dir="rtl"] .logical-float { - float: right; -} - .color-function { prop-1: rgb(0,132,94); prop-2: 'color(display-p3 0.02472 0.01150 0.00574 / 1)'; @@ -439,10 +438,7 @@ right: 3px; bottom: 3px; left: 2px; - top: 2px; - right: 2px; - bottom: 2px; - left: 2px; + padding-left: 2px; } .trigonometric { @@ -497,24 +493,11 @@ text-decoration-thickness: 3px; } -[dir="ltr"] .stage__container { +.stage__container { left: 1rem; left: var(--size, 1rem); } -[dir="rtl"] .stage__container { - right: 1rem; - right: var(--size, 1rem); -} - -[dir="ltr"] .stage__container { - left: 1rem; -} - -[dir="rtl"] .stage__container { - right: 1rem; -} - :scope { content: "plain :scope"; } diff --git a/plugin-packs/postcss-preset-env/test/basic.ch88-ff78-saf10.expect.css b/plugin-packs/postcss-preset-env/test/basic.ch88-ff78-saf10.expect.css index 78a2aefb7..9b1f83b5c 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ch88-ff78-saf10.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ch88-ff78-saf10.expect.css @@ -30,18 +30,21 @@ } } -[dir="ltr"] .test-logical-properties-and-values { - margin: 1px 4px 3px 2px; +.test-logical-properties-and-values { + margin-left: 1px; + margin-right: 2px; + order: 3; + padding-top: 4px; + padding-bottom: 4px; } -[dir="rtl"] .test-logical-properties-and-values { - margin: 1px 2px 3px 4px; +.test-logical-resize { + resize: horizontal; } -.test-logical-properties-and-values { - order: 3; - padding-top: 5px; - padding-bottom: 5px; +.test-logical-viewport-units { + width: calc(10vw + 5px); + width: calc(10vi + 5px); } .test-nesting-rules { @@ -352,14 +355,10 @@ h6.test-custom-selectors { display: ruby-text flow; } -[dir="ltr"] .logical-float { +.logical-float { float: left; } -[dir="rtl"] .logical-float { - float: right; -} - .color-function { prop-1: rgb(0,132,94); prop-2: 'color(display-p3 0.02472 0.01150 0.00574 / 1)'; @@ -465,10 +464,7 @@ h6.test-custom-selectors { right: 3px; bottom: 3px; left: 2px; - top: 2px; - right: 2px; - bottom: 2px; - left: 2px; + padding-left: 2px; } .trigonometric { @@ -520,14 +516,10 @@ h6.test-custom-selectors { text-decoration-thickness: 3px; } -[dir="ltr"] .stage__container { +.stage__container { left: var(--size, 1rem); } -[dir="rtl"] .stage__container { - right: var(--size, 1rem); -} - :scope { content: "plain :scope"; } diff --git a/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.expect.css b/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.expect.css index 00ccf869b..bca8608ab 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.expect.css @@ -30,18 +30,21 @@ } } -[dir="ltr"] .test-logical-properties-and-values { - margin: 1px 4px 3px 2px; +.test-logical-properties-and-values { + margin-left: 1px; + margin-right: 2px; + order: 3; + padding-top: 4px; + padding-bottom: 4px; } -[dir="rtl"] .test-logical-properties-and-values { - margin: 1px 2px 3px 4px; +.test-logical-resize { + resize: horizontal; } -.test-logical-properties-and-values { - order: 3; - padding-top: 5px; - padding-bottom: 5px; +.test-logical-viewport-units { + width: calc(10vw + 5px); + width: calc(10vi + 5px); } .test-nesting-rules { @@ -352,14 +355,10 @@ h6.test-custom-selectors { display: ruby-text flow; } -[dir="ltr"] .logical-float { +.logical-float { float: left; } -[dir="rtl"] .logical-float { - float: right; -} - .color-function { prop-1: rgb(0,132,94); prop-2: 'color(display-p3 0.02472 0.01150 0.00574 / 1)'; @@ -465,10 +464,7 @@ h6.test-custom-selectors { right: 3px; bottom: 3px; left: 2px; - top: 2px; - right: 2px; - bottom: 2px; - left: 2px; + padding-left: 2px; } .trigonometric { @@ -516,14 +512,10 @@ h6.test-custom-selectors { text-decoration: 3px wavy pink overline; } -[dir="ltr"] .stage__container { +.stage__container { left: var(--size, 1rem); } -[dir="rtl"] .stage__container { - right: var(--size, 1rem); -} - :scope { content: "plain :scope"; } diff --git a/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.no-is-pseudo.expect.css b/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.no-is-pseudo.expect.css index 00ccf869b..bca8608ab 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.no-is-pseudo.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.no-is-pseudo.expect.css @@ -30,18 +30,21 @@ } } -[dir="ltr"] .test-logical-properties-and-values { - margin: 1px 4px 3px 2px; +.test-logical-properties-and-values { + margin-left: 1px; + margin-right: 2px; + order: 3; + padding-top: 4px; + padding-bottom: 4px; } -[dir="rtl"] .test-logical-properties-and-values { - margin: 1px 2px 3px 4px; +.test-logical-resize { + resize: horizontal; } -.test-logical-properties-and-values { - order: 3; - padding-top: 5px; - padding-bottom: 5px; +.test-logical-viewport-units { + width: calc(10vw + 5px); + width: calc(10vi + 5px); } .test-nesting-rules { @@ -352,14 +355,10 @@ h6.test-custom-selectors { display: ruby-text flow; } -[dir="ltr"] .logical-float { +.logical-float { float: left; } -[dir="rtl"] .logical-float { - float: right; -} - .color-function { prop-1: rgb(0,132,94); prop-2: 'color(display-p3 0.02472 0.01150 0.00574 / 1)'; @@ -465,10 +464,7 @@ h6.test-custom-selectors { right: 3px; bottom: 3px; left: 2px; - top: 2px; - right: 2px; - bottom: 2px; - left: 2px; + padding-left: 2px; } .trigonometric { @@ -516,14 +512,10 @@ h6.test-custom-selectors { text-decoration: 3px wavy pink overline; } -[dir="ltr"] .stage__container { +.stage__container { left: var(--size, 1rem); } -[dir="rtl"] .stage__container { - right: var(--size, 1rem); -} - :scope { content: "plain :scope"; } diff --git a/plugin-packs/postcss-preset-env/test/basic.css b/plugin-packs/postcss-preset-env/test/basic.css index 902e8ec88..c25040ca1 100644 --- a/plugin-packs/postcss-preset-env/test/basic.css +++ b/plugin-packs/postcss-preset-env/test/basic.css @@ -16,9 +16,18 @@ } .test-logical-properties-and-values { - margin: logical 1px 2px 3px 4px; + margin-inline-start: 1px; + margin-inline-end: 2px; order: 3; - padding-block: 5px; + padding-block: 4px; +} + +.test-logical-resize { + resize: inline; +} + +.test-logical-viewport-units { + width: calc(10vi + 5px); } .test-nesting-rules { @@ -354,7 +363,7 @@ right: round(nearest, 2.5px, 1px); bottom: round(up, 2.5px, 1px); left: round(down, 2.5px, 1px); - inset: round(to-zero, 2.5px, 1px); + padding-left: round(to-zero, 2.5px, 1px); } .trigonometric { diff --git a/plugin-packs/postcss-preset-env/test/basic.expect.css b/plugin-packs/postcss-preset-env/test/basic.expect.css index e7b7c9046..aee0f6da9 100644 --- a/plugin-packs/postcss-preset-env/test/basic.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.expect.css @@ -31,18 +31,21 @@ } } -[dir="ltr"] .test-logical-properties-and-values { - margin: 1px 4px 3px 2px; +.test-logical-properties-and-values { + margin-left: 1px; + margin-right: 2px; + order: 3; + padding-top: 4px; + padding-bottom: 4px; } -[dir="rtl"] .test-logical-properties-and-values { - margin: 1px 2px 3px 4px; +.test-logical-resize { + resize: horizontal; } -.test-logical-properties-and-values { - order: 3; - padding-top: 5px; - padding-bottom: 5px; +.test-logical-viewport-units { + width: calc(10vw + 5px); + width: calc(10vi + 5px); } .test-nesting-rules { @@ -432,14 +435,10 @@ display: ruby-text flow; } -[dir="ltr"] .logical-float { +.logical-float { float: left; } -[dir="rtl"] .logical-float { - float: right; -} - .color-function { prop-1: rgb(0,132,94); prop-2: 'color(display-p3 0.02472 0.01150 0.00574 / 1)'; @@ -547,10 +546,7 @@ right: 3px; bottom: 3px; left: 2px; - top: 2px; - right: 2px; - bottom: 2px; - left: 2px; + padding-left: 2px; } .trigonometric { @@ -606,24 +602,11 @@ text-decoration-thickness: 3px; } -[dir="ltr"] .stage__container { +.stage__container { left: 1rem; left: var(--size, 1rem); } -[dir="rtl"] .stage__container { - right: 1rem; - right: var(--size, 1rem); -} - -[dir="ltr"] .stage__container { - left: 1rem; -} - -[dir="rtl"] .stage__container { - right: 1rem; -} - :root { content: "plain :scope"; } diff --git a/plugin-packs/postcss-preset-env/test/basic.ff49.expect.css b/plugin-packs/postcss-preset-env/test/basic.ff49.expect.css index fa741304a..dd8bd73a8 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ff49.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ff49.expect.css @@ -29,18 +29,21 @@ } } -.test-logical-properties-and-values:dir(ltr) { - margin: 1px 4px 3px 2px; +.test-logical-properties-and-values { + margin-left: 1px; + margin-right: 2px; + order: 3; + padding-top: 4px; + padding-bottom: 4px; } -.test-logical-properties-and-values:dir(rtl) { - margin: 1px 2px 3px 4px; +.test-logical-resize { + resize: horizontal; } -.test-logical-properties-and-values { - order: 3; - padding-top: 5px; - padding-bottom: 5px; +.test-logical-viewport-units { + width: calc(10vw + 5px); + width: calc(10vi + 5px); } .test-nesting-rules { @@ -329,14 +332,10 @@ display: ruby-text flow; } -.logical-float:dir(ltr) { +.logical-float { float: left; } -.logical-float:dir(rtl) { - float: right; -} - .color-function { prop-1: rgb(0,132,94); prop-2: 'color(display-p3 0.02472 0.01150 0.00574 / 1)'; @@ -442,10 +441,7 @@ right: 3px; bottom: 3px; left: 2px; - top: 2px; - right: 2px; - bottom: 2px; - left: 2px; + padding-left: 2px; } .trigonometric { @@ -499,14 +495,10 @@ text-decoration-thickness: 3px; } -.stage__container:dir(ltr) { +.stage__container { left: var(--size, 1rem); } -.stage__container:dir(rtl) { - right: var(--size, 1rem); -} - :scope { content: "plain :scope"; } diff --git a/plugin-packs/postcss-preset-env/test/basic.ff66.expect.css b/plugin-packs/postcss-preset-env/test/basic.ff66.expect.css index 974affa79..119e817a1 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ff66.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ff66.expect.css @@ -30,9 +30,19 @@ } .test-logical-properties-and-values { - margin: logical 1px 2px 3px 4px; + margin-inline-start: 1px; + margin-inline-end: 2px; order: 3; - padding-block: 5px; + padding-block: 4px; +} + +.test-logical-resize { + resize: inline; +} + +.test-logical-viewport-units { + width: calc(10vw + 5px); + width: calc(10vi + 5px); } .test-nesting-rules { @@ -426,7 +436,7 @@ right: 3px; bottom: 3px; left: 2px; - inset: 2px; + padding-left: 2px; } .trigonometric { diff --git a/plugin-packs/postcss-preset-env/test/basic.hebrew.expect.css b/plugin-packs/postcss-preset-env/test/basic.hebrew.expect.css new file mode 100644 index 000000000..93be626d6 --- /dev/null +++ b/plugin-packs/postcss-preset-env/test/basic.hebrew.expect.css @@ -0,0 +1,649 @@ +:root { + --order: 1; +} + +.test-custom-property-fallbacks { + --firebrick: rgb(179, 35, 35); +} + +@supports (color: color(display-p3 0 0 0)) { +.test-custom-property-fallbacks { + --firebrick: color(display-p3 0.64331 0.19245 0.16771); +} +} + +.test-custom-properties { + order: 1; + order: var(--order); +} + +.test-image-set-function { + background-image: url(img/test.png); + background-image: -webkit-image-set(url(img/test.png) 1x, url(img/test-2x.png) 2x); + background-image: image-set(url(img/test.png) 1x, url(img/test-2x.png) 2x); + order: 2; +} + +@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { + +.test-image-set-function { + background-image: url(img/test-2x.png); +} +} + +.test-logical-properties-and-values { + margin-right: 1px; + margin-left: 2px; + order: 3; + padding-top: 4px; + padding-bottom: 4px; +} + +.test-logical-resize { + resize: horizontal; +} + +.test-logical-viewport-units { + width: calc(10vw + 5px); + width: calc(10vi + 5px); +} + +.test-nesting-rules { + order: 4; +} + +.test-nesting-rules p { + order: 5; + } + +.test-nesting-rules { + + order: 6; +} + +.test-nesting-rules, +#test-is-pseudo { + order: 7; +} + +.test-nesting-rules + p, #test-is-pseudo + p { + order: 8; + } + +.test-nesting-rules, +#test-is-pseudo { + + order: 9; +} + +@media (max-width: 30em) { + .test-custom-media-queries { + order: 10; + } +} + +@media (min-width: 480px) and (max-width: 767px) { + .test-media-query-ranges { + order: 11; + } +} + +@media (prefers-color-scheme: dark) { + body { + background-color: black; + color: white; + } +} + +h1.test-custom-selectors { + order:12; +} + +h2.test-custom-selectors { + order:12; +} + +h3.test-custom-selectors { + order:12; +} + +h4.test-custom-selectors { + order:12; +} + +h5.test-custom-selectors { + order:12; +} + +h6.test-custom-selectors { + order:12; +} + +.test-case-insensitive-attributes[frame=hsides],.test-case-insensitive-attributes[frame=Hsides],.test-case-insensitive-attributes[frame=hSides],.test-case-insensitive-attributes[frame=HSides],.test-case-insensitive-attributes[frame=hsIdes],.test-case-insensitive-attributes[frame=HsIdes],.test-case-insensitive-attributes[frame=hSIdes],.test-case-insensitive-attributes[frame=HSIdes],.test-case-insensitive-attributes[frame=hsiDes],.test-case-insensitive-attributes[frame=HsiDes],.test-case-insensitive-attributes[frame=hSiDes],.test-case-insensitive-attributes[frame=HSiDes],.test-case-insensitive-attributes[frame=hsIDes],.test-case-insensitive-attributes[frame=HsIDes],.test-case-insensitive-attributes[frame=hSIDes],.test-case-insensitive-attributes[frame=HSIDes],.test-case-insensitive-attributes[frame=hsidEs],.test-case-insensitive-attributes[frame=HsidEs],.test-case-insensitive-attributes[frame=hSidEs],.test-case-insensitive-attributes[frame=HSidEs],.test-case-insensitive-attributes[frame=hsIdEs],.test-case-insensitive-attributes[frame=HsIdEs],.test-case-insensitive-attributes[frame=hSIdEs],.test-case-insensitive-attributes[frame=HSIdEs],.test-case-insensitive-attributes[frame=hsiDEs],.test-case-insensitive-attributes[frame=HsiDEs],.test-case-insensitive-attributes[frame=hSiDEs],.test-case-insensitive-attributes[frame=HSiDEs],.test-case-insensitive-attributes[frame=hsIDEs],.test-case-insensitive-attributes[frame=HsIDEs],.test-case-insensitive-attributes[frame=hSIDEs],.test-case-insensitive-attributes[frame=HSIDEs],.test-case-insensitive-attributes[frame=hsideS],.test-case-insensitive-attributes[frame=HsideS],.test-case-insensitive-attributes[frame=hSideS],.test-case-insensitive-attributes[frame=HSideS],.test-case-insensitive-attributes[frame=hsIdeS],.test-case-insensitive-attributes[frame=HsIdeS],.test-case-insensitive-attributes[frame=hSIdeS],.test-case-insensitive-attributes[frame=HSIdeS],.test-case-insensitive-attributes[frame=hsiDeS],.test-case-insensitive-attributes[frame=HsiDeS],.test-case-insensitive-attributes[frame=hSiDeS],.test-case-insensitive-attributes[frame=HSiDeS],.test-case-insensitive-attributes[frame=hsIDeS],.test-case-insensitive-attributes[frame=HsIDeS],.test-case-insensitive-attributes[frame=hSIDeS],.test-case-insensitive-attributes[frame=HSIDeS],.test-case-insensitive-attributes[frame=hsidES],.test-case-insensitive-attributes[frame=HsidES],.test-case-insensitive-attributes[frame=hSidES],.test-case-insensitive-attributes[frame=HSidES],.test-case-insensitive-attributes[frame=hsIdES],.test-case-insensitive-attributes[frame=HsIdES],.test-case-insensitive-attributes[frame=hSIdES],.test-case-insensitive-attributes[frame=HSIdES],.test-case-insensitive-attributes[frame=hsiDES],.test-case-insensitive-attributes[frame=HsiDES],.test-case-insensitive-attributes[frame=hSiDES],.test-case-insensitive-attributes[frame=HSiDES],.test-case-insensitive-attributes[frame=hsIDES],.test-case-insensitive-attributes[frame=HsIDES],.test-case-insensitive-attributes[frame=hSIDES],.test-case-insensitive-attributes[frame=HSIDES] { + order: 13; +} + +.test-rebeccapurple-color { + color: #639; + order: 14; +} + +.test-hexadecimal-alpha-notation { + background-color: rgba(243,243,243,0.95294); + color: rgba(0,0,0,0.2); + order: 15; +} + +.test-color-functional-notation { + color: rgba(178, 34, 34, 0.5); + order: 16; +} + +.test-lab-function { + background-color: rgb(179, 35, 35); + background-color: color(display-p3 0.64331 0.19245 0.16771); + color: rgba(179, 34, 35, 0.5); + color: color(display-p3 0.64368 0.19188 0.16791 / 50%); + order: 17; +} + +.test-system-ui-font-family { + font-family: system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif; + order: 18; +} + +.test-font-variant-property { + font-feature-settings: "smcp"; + font-variant-caps: small-caps; + order: 19; +} + +.test-all-property { + animation: none 0s ease 0s 1 normal none running; + -webkit-backface-visibility: visible; + backface-visibility: visible; + background: transparent none repeat 0 0 / auto auto padding-box border-box scroll; + border: medium none currentColor; + border-collapse: separate; + -o-border-image: none; + border-image: none; + border-radius: 0; + border-spacing: 0; + bottom: auto; + box-shadow: none; + box-sizing: content-box; + caption-side: top; + clear: none; + clip: auto; + color: #000; + -moz-columns: auto; + columns: auto; + -moz-column-count: auto; + column-count: auto; + -moz-column-fill: balance; + column-fill: balance; + -moz-column-gap: normal; + column-gap: normal; + -moz-column-rule: medium none currentColor; + column-rule: medium none currentColor; + -moz-column-span: 1; + column-span: 1; + -moz-column-width: auto; + column-width: auto; + content: normal; + counter-increment: none; + counter-reset: none; + cursor: auto; + direction: ltr; + display: inline; + empty-cells: show; + float: none; + font-family: serif; + font-size: medium; + font-style: normal; + font-variant: normal; + font-weight: normal; + font-stretch: normal; + line-height: normal; + height: auto; + -webkit-hyphens: none; + hyphens: none; + left: auto; + letter-spacing: normal; + list-style: disc outside none; + margin: 0; + max-height: none; + max-width: none; + min-height: 0; + min-width: 0; + opacity: 1; + orphans: 2; + outline: medium none invert; + overflow: visible; + overflow-x: visible; + overflow-y: visible; + padding: 0; + page-break-after: auto; + page-break-before: auto; + page-break-inside: auto; + perspective: none; + perspective-origin: 50% 50%; + position: static; + right: auto; + -moz-tab-size: 8; + -o-tab-size: 8; + tab-size: 8; + table-layout: auto; + text-align: left; + -moz-text-align-last: auto; + text-align-last: auto; + -webkit-text-decoration: none; + text-decoration: none; + text-indent: 0; + text-shadow: none; + text-transform: none; + top: auto; + transform: none; + transform-origin: 50% 50% 0; + transform-style: flat; + transition: none 0s ease 0s; + unicode-bidi: normal; + vertical-align: baseline; + visibility: visible; + white-space: normal; + widows: 2; + width: auto; + word-spacing: normal; + z-index: auto; + all: initial; + order: 20; +} + +.test-matches-pseudo-class:matches(:first-child, .special) { + order: 21; +} + +.test-not-pseudo-class:not(:first-child):not(.special) { + order: 22; +} + +.test-any-link-pseudo-class:link, .test-any-link-pseudo-class:visited, area[href].test-any-link-pseudo-class { + order: 23; +} + +.test-any-link-pseudo-class:-moz-any-link { + order: 23; +} + +.test-any-link-pseudo-class:any-link { + order: 23; +} + +[dir="rtl"] .test-dir-pseudo-class { + order: 24; +} + +.test-overflow-wrap-property { + order: 25; + word-wrap: break-word; +} + +.test-focus-visible-pseudo-class:focus-visible { + order: 26; +} + +.test-double-position-gradients { + background-image: conic-gradient(yellowgreen 40%, gold 0deg,gold 75%, #f06 0deg); + background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); +} + +.test-blank-pseudo-class:blank { + background-color: yellow; +} + +.test-has-pseudo-class:has(.inner-class) { + background-color: yellow; +} + +.a:focus { + order: 27; +} + +.a:hover { + order: 27; +} + +.b:focus { + order: 27; +} + +.b:hover { + order: 27; +} + +.a.c > .b + .d { + order: 28; +} + +.test-hwb-function { + background-color: rgba(0, 195, 255, .5); +} + +.test-opacity-percent { + opacity: 0.42; +} + +.clamp-same-unit { + width: max(10px, min(64px, 80px)); +} + +.complex-clamp { + width: max(calc(100% - 10px), min(min(10px, 100%), max(40px, 4em))); +} + +.clamp-different-units { + width: max(10%, min(2px, 4rem)); +} + +.mixed-clamp { + grid-template-columns: max(22rem, min(40%, 32rem)) minmax(0, 1fr); + margin: max(1rem, min(2%, 3rem)) 4vh; +} + +.calc-clamp { + margin: 0 40px 0 calc(-1 * max(32px, min(16vw, 64px))); +} + +.multiple-calc-clamp { + margin: calc(-1 * max(1px, min(2vw, 3px))) calc(-1 * max(4px, min(5vw, 6px))); +} + +.nested-clamp { + font-size: max(max(1rem, min(2vw, 3rem)), min(4vw, 5rem)); +} + +@font-face { + font-family: 'A'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url(a) format("woff2"); +} + +.block-flow { + display: block; + display: block flow; +} + +.block-flow-root { + display: flow-root; + display: block flow-root; +} + +.inline-flow { + display: inline; + display: inline flow; +} + +.inline-flow-root { + display: inline-block; + display: inline flow-root; +} + +.run-in-flow { + display: run-in; + display: run-in flow; +} + +.list-item-block-flow { + display: list-item; + display: list-item block flow; +} + +.inline-flow-list-item { + display: inline list-item; + display: inline flow list-item; +} + +.block-flex { + display: flex; + display: block flex; +} + +.inline-flex { + display: inline-flex; + display: inline flex; +} + +.block-grid { + display: grid; + display: block grid; +} + +.inline-grid { + display: inline-grid; + display: inline grid; +} + +.inline-ruby { + display: ruby; + display: inline ruby; +} + +.block-table { + display: table; + display: block table; +} + +.inline-table { + display: inline-table; + display: inline table; +} + +.table-cell-flow { + display: table-cell; + display: table-cell flow; +} + +.table-caption-flow { + display: table-caption; + display: table-caption flow; +} + +.ruby-base-flow { + display: ruby-base; + display: ruby-base flow; +} + +.ruby-text-flow { + display: ruby-text; + display: ruby-text flow; +} + +.logical-float { + float: right; +} + +.color-function { + prop-1: rgb(0,132,94); + prop-2: 'color(display-p3 0.02472 0.01150 0.00574 / 1)'; + prop-3: rgba(7,3,1,1); + prop-4: rgba(7,3,1,calc(33 / 22)); + prop-5: rgb(255,255,255); +} + +.oklab { + color-1: rgb(73, 71, 69); + color-1: color(display-p3 0.28515 0.27983 0.27246); + color-2: rgba(121, 34, 67, 1); + color-2: color(display-p3 0.43853 0.16014 0.26019 / 1); + color-3: rgba(121, 34, 67, .5); + color-3: color(display-p3 0.43853 0.16014 0.26019 / .5); + color-4: rgba(121, 34, 67, 1); + color-4: color(display-p3 0.43853 0.16014 0.26019 / 100%); + color-5: rgba(121, 34, 67, 0.5); + color-5: color(display-p3 0.43853 0.16014 0.26019 / 50%); + color-6: rgb(177, 102, 126); + color-6: color(display-p3 0.65225 0.41303 0.49110); + color-7: oklab(60% 0.1 0 foo); + color-8: rgb(125, 35, 41); + color-8: color(display-p3 0.45163 0.16556 0.17021); + color-9: rgb(198, 93, 7); + color-9: color(display-p3 0.72414 0.38678 0.14879); + color-10: rgb(157, 147, 24); + color-10: color(display-p3 0.60930 0.57658 0.20615); + color-11: rgb(104, 166, 57); + color-11: color(display-p3 0.46287 0.64491 0.28775); + color-12: rgb(98, 172, 239); + color-12: color(display-p3 0.45207 0.66555 0.91656); +} + +.oklch { + color-1: rgb(126, 37, 15); + color-1: color(display-p3 0.45368 0.16978 0.09411); + color-2: rgba(126, 37, 15, 1); + color-2: color(display-p3 0.45368 0.16978 0.09411 / 1); + color-3: rgba(126, 37, 15, .5); + color-3: color(display-p3 0.45368 0.16978 0.09411 / .5); + color-4: rgba(126, 37, 15, 1); + color-4: color(display-p3 0.45368 0.16978 0.09411 / 100%); + color-5: rgba(126, 37, 15, 0.5); + color-5: color(display-p3 0.45368 0.16978 0.09411 / 50%); + color-6: rgb(197, 84, 124); + color-6: color(display-p3 0.71738 0.35446 0.48551); + + color-7: rgb(0, 152, 131); + + color-7: color(display-p3 0.19244 0.58461 0.51559); + color-8: rgb(0, 152, 131); + color-8: color(display-p3 0.19244 0.58461 0.51559); + color-9: rgb(0, 152, 131); + color-9: color(display-p3 0.19244 0.58461 0.51559); + color-10: rgb(0, 152, 131); + color-10: color(display-p3 0.19244 0.58461 0.51559); + color-11: rgb(0, 152, 131); + color-11: color(display-p3 0.19244 0.58461 0.51559); + + color-12: rgb(188, 101, 59); + + color-12: color(display-p3 0.69260 0.41373 0.26821); + color-13: rgb(188, 101, 59); + color-13: color(display-p3 0.69260 0.41373 0.26821); + color-14: rgb(188, 101, 59); + color-14: color(display-p3 0.69260 0.41373 0.26821); + color-15: rgb(188, 101, 59); + color-15: color(display-p3 0.69260 0.41373 0.26821); + color-16: rgb(188, 101, 59); + color-16: color(display-p3 0.69260 0.41373 0.26821); + color-17: oklch(60% 0.1250 0.785398unknown); +} + +.ic-unit { + --value-2ic: initial; + text-indent: 2em; + content: var(--value-2ic); + left: 2em; + left: var(--non-existing, 2em); + width: calc(8em + 20px); + height: 10px; + margin: 0.5em 1em .2em; + padding: 2 ic; +} + +.unset { + clip: auto; + clip: initial; +} + +.mod { + padding: 8px 3px 1px calc(3px + 50%); + transform: rotate(-50deg); + width: 2px; +} + +.rem { + padding: 8px 3px 1px calc(3px + 50%); + transform: rotate(-50deg); +} + +.round { + top: 3px; + right: 3px; + bottom: 3px; + left: 2px; + padding-left: 2px; +} + +.trigonometric { + left: 0.70711; + left: 0.70711; + left: 1; + left: 30deg; + left: 60deg; + left: 84.29deg; + left: -45deg; + left: 90deg; + left: 135deg; + left: 0.90533; +} + +.trigonometric-ignore-not-a-function { + left: sin; + left: cos; + left: tan; + left: asin; + left: acos; + left: atan; + left: atan2; +} + +.trigonometric-ignore-no-arguments { + left: sin(); + left: cos(); + left: tan(); + left: asin(); + left: acos(); + left: atan(); + left: atan2(); +} + +[data-view-size=m] .view { + background: red; +} + +.nested-calc { + order: calc(1 * (8 / 3 + (5 * 10))); + order: calc(1 * calc(8 / 3 + calc(5 * 10))); +} + +.text-decoration-shorthand { + text-decoration: overline; + -webkit-text-decoration: overline wavy pink; + text-decoration: overline wavy pink; + text-decoration-thickness: 3px; +} + +.stage__container { + right: 1rem; + right: var(--size, 1rem); +} + +:root { + content: "plain :scope"; +} + +@scope (.foo) { + :scope { + content: ":scope in @scope"; + } +} + +:root { + @scope (.foo) { + content: ":scope in @scope, but with nesting"; + } +} + +@media (min-aspect-ratio: 177/100) { + /* media query aspect ratio : */ +} diff --git a/plugin-packs/postcss-preset-env/test/basic.ie10.expect.css b/plugin-packs/postcss-preset-env/test/basic.ie10.expect.css index c5aa18ffa..8641cd536 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ie10.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ie10.expect.css @@ -33,19 +33,22 @@ } } -[dir="ltr"] .test-logical-properties-and-values { - margin: 1px 4px 3px 2px; +.test-logical-properties-and-values { + margin-left: 1px; + margin-right: 2px; + -ms-flex-order: 3; + order: 3; + padding-top: 4px; + padding-bottom: 4px; } -[dir="rtl"] .test-logical-properties-and-values { - margin: 1px 2px 3px 4px; +.test-logical-resize { + resize: horizontal; } -.test-logical-properties-and-values { - -ms-flex-order: 3; - order: 3; - padding-top: 5px; - padding-bottom: 5px; +.test-logical-viewport-units { + width: calc(10vw + 5px); + width: calc(10vi + 5px); } .test-nesting-rules { @@ -451,14 +454,10 @@ display: ruby-text flow; } -[dir="ltr"] .logical-float { +.logical-float { float: left; } -[dir="rtl"] .logical-float { - float: right; -} - .color-function { prop-1: rgb(0,132,94); prop-2: 'color(display-p3 0.02472 0.01150 0.00574 / 1)'; @@ -566,10 +565,7 @@ right: 3px; bottom: 3px; left: 2px; - top: 2px; - right: 2px; - bottom: 2px; - left: 2px; + padding-left: 2px; } .trigonometric { @@ -626,24 +622,11 @@ text-decoration-thickness: 3px; } -[dir="ltr"] .stage__container { +.stage__container { left: 1rem; left: var(--size, 1rem); } -[dir="rtl"] .stage__container { - right: 1rem; - right: var(--size, 1rem); -} - -[dir="ltr"] .stage__container { - left: 1rem; -} - -[dir="rtl"] .stage__container { - right: 1rem; -} - :root { content: "plain :scope"; } diff --git a/plugin-packs/postcss-preset-env/test/basic.nesting.false.expect.css b/plugin-packs/postcss-preset-env/test/basic.nesting.false.expect.css index a26a19018..cc7e379ea 100644 --- a/plugin-packs/postcss-preset-env/test/basic.nesting.false.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.nesting.false.expect.css @@ -31,18 +31,21 @@ } } -[dir="ltr"] .test-logical-properties-and-values { - margin: 1px 4px 3px 2px; +.test-logical-properties-and-values { + margin-left: 1px; + margin-right: 2px; + order: 3; + padding-top: 4px; + padding-bottom: 4px; } -[dir="rtl"] .test-logical-properties-and-values { - margin: 1px 2px 3px 4px; +.test-logical-resize { + resize: horizontal; } -.test-logical-properties-and-values { - order: 3; - padding-top: 5px; - padding-bottom: 5px; +.test-logical-viewport-units { + width: calc(10vw + 5px); + width: calc(10vi + 5px); } .test-nesting-rules { @@ -450,14 +453,10 @@ h6.test-custom-selectors { display: ruby-text flow; } -[dir="ltr"] .logical-float { +.logical-float { float: left; } -[dir="rtl"] .logical-float { - float: right; -} - .color-function { prop-1: rgb(0,132,94); prop-2: 'color(display-p3 0.02472 0.01150 0.00574 / 1)'; @@ -565,10 +564,7 @@ h6.test-custom-selectors { right: 3px; bottom: 3px; left: 2px; - top: 2px; - right: 2px; - bottom: 2px; - left: 2px; + padding-left: 2px; } .trigonometric { @@ -622,24 +618,11 @@ h6.test-custom-selectors { text-decoration-thickness: 3px; } -[dir="ltr"] .stage__container { +.stage__container { left: 1rem; left: var(--size, 1rem); } -[dir="rtl"] .stage__container { - right: 1rem; - right: var(--size, 1rem); -} - -[dir="ltr"] .stage__container { - left: 1rem; -} - -[dir="rtl"] .stage__container { - right: 1rem; -} - :root { content: "plain :scope"; } diff --git a/plugin-packs/postcss-preset-env/test/basic.nesting.true.expect.css b/plugin-packs/postcss-preset-env/test/basic.nesting.true.expect.css index 5d8447538..70771a672 100644 --- a/plugin-packs/postcss-preset-env/test/basic.nesting.true.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.nesting.true.expect.css @@ -17,9 +17,20 @@ } .test-logical-properties-and-values { - margin: logical 1px 2px 3px 4px; + -webkit-margin-start: 1px; + margin-inline-start: 1px; + -webkit-margin-end: 2px; + margin-inline-end: 2px; order: 3; - padding-block: 5px; + padding-block: 4px; +} + +.test-logical-resize { + resize: inline; +} + +.test-logical-viewport-units { + width: calc(10vi + 5px); } .test-nesting-rules { @@ -366,7 +377,7 @@ right: round(nearest, 2.5px, 1px); bottom: round(up, 2.5px, 1px); left: round(down, 2.5px, 1px); - inset: round(to-zero, 2.5px, 1px); + padding-left: round(to-zero, 2.5px, 1px); } .trigonometric { diff --git a/plugin-packs/postcss-preset-env/test/basic.op_mini.expect.css b/plugin-packs/postcss-preset-env/test/basic.op_mini.expect.css index 04f779aa2..84b676c56 100644 --- a/plugin-packs/postcss-preset-env/test/basic.op_mini.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.op_mini.expect.css @@ -30,18 +30,21 @@ } } -[dir="ltr"] .test-logical-properties-and-values { - margin: 1px 4px 3px 2px; +.test-logical-properties-and-values { + margin-left: 1px; + margin-right: 2px; + order: 3; + padding-top: 4px; + padding-bottom: 4px; } -[dir="rtl"] .test-logical-properties-and-values { - margin: 1px 2px 3px 4px; +.test-logical-resize { + resize: horizontal; } -.test-logical-properties-and-values { - order: 3; - padding-top: 5px; - padding-bottom: 5px; +.test-logical-viewport-units { + width: calc(10vw + 5px); + width: calc(10vi + 5px); } .test-nesting-rules { @@ -440,14 +443,10 @@ h6.test-custom-selectors { display: ruby-text flow; } -[dir="ltr"] .logical-float { +.logical-float { float: left; } -[dir="rtl"] .logical-float { - float: right; -} - .color-function { prop-1: rgb(0,132,94); prop-2: 'color(display-p3 0.02472 0.01150 0.00574 / 1)'; @@ -555,10 +554,7 @@ h6.test-custom-selectors { right: 3px; bottom: 3px; left: 2px; - top: 2px; - right: 2px; - bottom: 2px; - left: 2px; + padding-left: 2px; } .trigonometric { @@ -609,24 +605,11 @@ h6.test-custom-selectors { text-decoration-thickness: 3px; } -[dir="ltr"] .stage__container { +.stage__container { left: 1rem; left: var(--size, 1rem); } -[dir="rtl"] .stage__container { - right: 1rem; - right: var(--size, 1rem); -} - -[dir="ltr"] .stage__container { - left: 1rem; -} - -[dir="rtl"] .stage__container { - right: 1rem; -} - :root { content: "plain :scope"; } diff --git a/plugin-packs/postcss-preset-env/test/basic.preserve.true.expect.css b/plugin-packs/postcss-preset-env/test/basic.preserve.true.expect.css index 95d1c6c81..019e66568 100644 --- a/plugin-packs/postcss-preset-env/test/basic.preserve.true.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.preserve.true.expect.css @@ -49,32 +49,29 @@ } } -[dir="ltr"] .test-logical-properties-and-values { - margin: 1px 4px 3px 2px; -} - -.test-logical-properties-and-values:dir(ltr) { - margin: 1px 4px 3px 2px; -} - -[dir="rtl"] .test-logical-properties-and-values { - margin: 1px 2px 3px 4px; -} - -.test-logical-properties-and-values:dir(rtl) { - margin: 1px 2px 3px 4px; -} - .test-logical-properties-and-values { - margin: logical 1px 2px 3px 4px; + margin-left: 1px; + margin-right: 2px; -webkit-box-ordinal-group: 4; -webkit-order: 3; -moz-box-ordinal-group: 4; -ms-flex-order: 3; order: 3; - padding-top: 5px; - padding-bottom: 5px; - padding-block: 5px; + padding-top: 4px; + padding-bottom: 4px; +} + +.test-logical-resize { + resize: horizontal; +} + +.test-logical-viewport-units { + width: -webkit-calc(10vw + 5px); + width: -moz-calc(10vw + 5px); + width: calc(10vw + 5px); + width: -webkit-calc(10vi + 5px); + width: -moz-calc(10vi + 5px); + width: calc(10vi + 5px); } .test-nesting-rules { @@ -799,24 +796,8 @@ h6.test-custom-selectors { display: ruby-text flow; } -[dir="ltr"] .logical-float { - float: left; -} - -.logical-float:dir(ltr) { - float: left; -} - -[dir="rtl"] .logical-float { - float: right; -} - -.logical-float:dir(rtl) { - float: right; -} - .logical-float { - float: inline-start; + float: left; } .color-function { @@ -1005,20 +986,8 @@ h6.test-custom-selectors { bottom: round(up, 2.5px, 1px); left: 2px; left: round(down, 2.5px, 1px); - top: 2px; - right: 2px; - bottom: 2px; - left: 2px; - inset: 2px; - top: 2px; - top: round(to-zero, 2.5px, 1px); - right: 2px; - right: round(to-zero, 2.5px, 1px); - bottom: 2px; - bottom: round(to-zero, 2.5px, 1px); - left: 2px; - left: round(to-zero, 2.5px, 1px); - inset: round(to-zero, 2.5px, 1px); + padding-left: 2px; + padding-left: round(to-zero, 2.5px, 1px); } .trigonometric { @@ -1099,57 +1068,11 @@ h6.test-custom-selectors { text-decoration: 3px wavy pink overline; } -[dir="ltr"] .stage__container { - left: 1rem; - left: var(--size, 1rem); -} - -[dir="ltr"] .stage__container { - left: 1rem; - left: var(--size, 1rem); -} - -.stage__container:dir(ltr) { +.stage__container { left: 1rem; left: var(--size, 1rem); } -[dir="rtl"] .stage__container { - right: 1rem; - right: var(--size, 1rem); -} - -[dir="rtl"] .stage__container { - right: 1rem; - right: var(--size, 1rem); -} - -.stage__container:dir(rtl) { - right: 1rem; - right: var(--size, 1rem); -} - -[dir="ltr"] .stage__container { - left: 1rem; -} - -.stage__container:dir(ltr) { - left: 1rem; -} - -[dir="rtl"] .stage__container { - right: 1rem; -} - -.stage__container:dir(rtl) { - right: 1rem; -} - -.stage__container { - inset-inline-start: 1rem; - inset-inline-start: var(--size, 1rem); -} - :root { content: "plain :scope"; } diff --git a/plugin-packs/postcss-preset-env/test/basic.safari15.expect.css b/plugin-packs/postcss-preset-env/test/basic.safari15.expect.css index f51e856ba..e79f3ca96 100644 --- a/plugin-packs/postcss-preset-env/test/basic.safari15.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.safari15.expect.css @@ -24,9 +24,19 @@ } .test-logical-properties-and-values { - margin: logical 1px 2px 3px 4px; + margin-inline-start: 1px; + margin-inline-end: 2px; order: 3; - padding-block: 5px; + padding-block: 4px; +} + +.test-logical-resize { + resize: horizontal; +} + +.test-logical-viewport-units { + width: calc(10vw + 5px); + width: calc(10vi + 5px); } .test-nesting-rules { @@ -279,7 +289,7 @@ } .logical-float { - float: inline-start; + float: left; } .color-function { @@ -387,7 +397,7 @@ right: 3px; bottom: 3px; left: 2px; - inset: 2px; + padding-left: 2px; } .trigonometric { diff --git a/plugin-packs/postcss-preset-env/test/basic.stage0-ff49.expect.css b/plugin-packs/postcss-preset-env/test/basic.stage0-ff49.expect.css index afef2ef1f..b9856b563 100644 --- a/plugin-packs/postcss-preset-env/test/basic.stage0-ff49.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.stage0-ff49.expect.css @@ -29,18 +29,21 @@ } } -.test-logical-properties-and-values:dir(ltr) { - margin: 1px 4px 3px 2px; +.test-logical-properties-and-values { + margin-left: 1px; + margin-right: 2px; + order: 3; + padding-top: 4px; + padding-bottom: 4px; } -.test-logical-properties-and-values:dir(rtl) { - margin: 1px 2px 3px 4px; +.test-logical-resize { + resize: horizontal; } -.test-logical-properties-and-values { - order: 3; - padding-top: 5px; - padding-bottom: 5px; +.test-logical-viewport-units { + width: calc(10vw + 5px); + width: calc(10vi + 5px); } .test-nesting-rules { @@ -354,14 +357,10 @@ h6.test-custom-selectors { display: ruby-text flow; } -.logical-float:dir(ltr) { +.logical-float { float: left; } -.logical-float:dir(rtl) { - float: right; -} - .color-function { prop-1: rgb(0,132,94); prop-2: 'color(display-p3 0.02472 0.01150 0.00574 / 1)'; @@ -467,10 +466,7 @@ h6.test-custom-selectors { right: 3px; bottom: 3px; left: 2px; - top: 2px; - right: 2px; - bottom: 2px; - left: 2px; + padding-left: 2px; } .trigonometric { @@ -520,14 +516,10 @@ h6.test-custom-selectors { text-decoration-thickness: 3px; } -.stage__container:dir(ltr) { +.stage__container { left: var(--size, 1rem); } -.stage__container:dir(rtl) { - right: var(--size, 1rem); -} - :scope { content: "plain :scope"; } diff --git a/plugin-packs/postcss-preset-env/test/basic.stage0-ff66.expect.css b/plugin-packs/postcss-preset-env/test/basic.stage0-ff66.expect.css index 59c09b83c..3386d5aba 100644 --- a/plugin-packs/postcss-preset-env/test/basic.stage0-ff66.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.stage0-ff66.expect.css @@ -30,9 +30,19 @@ } .test-logical-properties-and-values { - margin: logical 1px 2px 3px 4px; + margin-inline-start: 1px; + margin-inline-end: 2px; order: 3; - padding-block: 5px; + padding-block: 4px; +} + +.test-logical-resize { + resize: inline; +} + +.test-logical-viewport-units { + width: calc(10vw + 5px); + width: calc(10vi + 5px); } .test-nesting-rules { @@ -451,7 +461,7 @@ h6.test-custom-selectors { right: 3px; bottom: 3px; left: 2px; - inset: 2px; + padding-left: 2px; } .trigonometric { diff --git a/plugin-packs/postcss-preset-env/test/basic.stage0.expect.css b/plugin-packs/postcss-preset-env/test/basic.stage0.expect.css index 281a4d919..132a17700 100644 --- a/plugin-packs/postcss-preset-env/test/basic.stage0.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.stage0.expect.css @@ -31,18 +31,21 @@ } } -[dir="ltr"] .test-logical-properties-and-values { - margin: 1px 4px 3px 2px; +.test-logical-properties-and-values { + margin-left: 1px; + margin-right: 2px; + order: 3; + padding-top: 4px; + padding-bottom: 4px; } -[dir="rtl"] .test-logical-properties-and-values { - margin: 1px 2px 3px 4px; +.test-logical-resize { + resize: horizontal; } -.test-logical-properties-and-values { - order: 3; - padding-top: 5px; - padding-bottom: 5px; +.test-logical-viewport-units { + width: calc(10vw + 5px); + width: calc(10vi + 5px); } .test-nesting-rules { @@ -457,14 +460,10 @@ h6.test-custom-selectors { display: ruby-text flow; } -[dir="ltr"] .logical-float { +.logical-float { float: left; } -[dir="rtl"] .logical-float { - float: right; -} - .color-function { prop-1: rgb(0,132,94); prop-2: 'color(display-p3 0.02472 0.01150 0.00574 / 1)'; @@ -572,10 +571,7 @@ h6.test-custom-selectors { right: 3px; bottom: 3px; left: 2px; - top: 2px; - right: 2px; - bottom: 2px; - left: 2px; + padding-left: 2px; } .trigonometric { @@ -627,24 +623,11 @@ h6.test-custom-selectors { text-decoration-thickness: 3px; } -[dir="ltr"] .stage__container { +.stage__container { left: 1rem; left: var(--size, 1rem); } -[dir="rtl"] .stage__container { - right: 1rem; - right: var(--size, 1rem); -} - -[dir="ltr"] .stage__container { - left: 1rem; -} - -[dir="rtl"] .stage__container { - right: 1rem; -} - :root { content: "plain :scope"; } diff --git a/plugin-packs/postcss-preset-env/test/basic.vendors-1.expect.css b/plugin-packs/postcss-preset-env/test/basic.vendors-1.expect.css index 628df6647..4a8f4d564 100644 --- a/plugin-packs/postcss-preset-env/test/basic.vendors-1.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.vendors-1.expect.css @@ -31,18 +31,21 @@ } } -[dir="ltr"] .test-logical-properties-and-values { - margin: 1px 4px 3px 2px; +.test-logical-properties-and-values { + margin-left: 1px; + margin-right: 2px; + order: 3; + padding-top: 4px; + padding-bottom: 4px; } -[dir="rtl"] .test-logical-properties-and-values { - margin: 1px 2px 3px 4px; +.test-logical-resize { + resize: horizontal; } -.test-logical-properties-and-values { - order: 3; - padding-top: 5px; - padding-bottom: 5px; +.test-logical-viewport-units { + width: calc(10vw + 5px); + width: calc(10vi + 5px); } .test-nesting-rules { @@ -436,14 +439,10 @@ display: ruby-text flow; } -[dir="ltr"] .logical-float { +.logical-float { float: left; } -[dir="rtl"] .logical-float { - float: right; -} - .color-function { prop-1: rgb(0,132,94); prop-2: 'color(display-p3 0.02472 0.01150 0.00574 / 1)'; @@ -551,10 +550,7 @@ right: 3px; bottom: 3px; left: 2px; - top: 2px; - right: 2px; - bottom: 2px; - left: 2px; + padding-left: 2px; } .trigonometric { @@ -610,24 +606,11 @@ text-decoration-thickness: 3px; } -[dir="ltr"] .stage__container { +.stage__container { left: 1rem; left: var(--size, 1rem); } -[dir="rtl"] .stage__container { - right: 1rem; - right: var(--size, 1rem); -} - -[dir="ltr"] .stage__container { - left: 1rem; -} - -[dir="rtl"] .stage__container { - right: 1rem; -} - :root { content: "plain :scope"; } diff --git a/plugin-packs/postcss-preset-env/test/basic.vendors-2.expect.css b/plugin-packs/postcss-preset-env/test/basic.vendors-2.expect.css index 083625e20..69427e3c9 100644 --- a/plugin-packs/postcss-preset-env/test/basic.vendors-2.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.vendors-2.expect.css @@ -25,18 +25,21 @@ } } -.test-logical-properties-and-values:dir(ltr) { - margin: 1px 4px 3px 2px; +.test-logical-properties-and-values { + margin-left: 1px; + margin-right: 2px; + order: 3; + padding-top: 4px; + padding-bottom: 4px; } -.test-logical-properties-and-values:dir(rtl) { - margin: 1px 2px 3px 4px; +.test-logical-resize { + resize: horizontal; } -.test-logical-properties-and-values { - order: 3; - padding-top: 5px; - padding-bottom: 5px; +.test-logical-viewport-units { + width: calc(10vw + 5px); + width: calc(10vi + 5px); } .test-nesting-rules { @@ -428,12 +431,8 @@ display: ruby-text flow; } -.logical-float:dir(ltr) { - float: left; -} - -.logical-float:dir(rtl) { - float: right; +.logical-float { + float: inline-start; } .color-function { @@ -514,10 +513,7 @@ right: round(nearest, 2.5px, 1px); bottom: round(up, 2.5px, 1px); left: round(down, 2.5px, 1px); - top: round(to-zero, 2.5px, 1px); - right: round(to-zero, 2.5px, 1px); - bottom: round(to-zero, 2.5px, 1px); - left: round(to-zero, 2.5px, 1px); + padding-left: round(to-zero, 2.5px, 1px); } .trigonometric { @@ -573,24 +569,11 @@ text-decoration-thickness: 3px; } -.stage__container:dir(ltr) { +.stage__container { left: 1rem; left: var(--size, 1rem); } -.stage__container:dir(rtl) { - right: 1rem; - right: var(--size, 1rem); -} - -.stage__container:dir(ltr) { - left: 1rem; -} - -.stage__container:dir(rtl) { - right: 1rem; -} - :root { content: "plain :scope"; } diff --git a/plugin-packs/postcss-preset-env/test/basic.vendors-3.expect.css b/plugin-packs/postcss-preset-env/test/basic.vendors-3.expect.css index 0b66c16fb..9f04ed902 100644 --- a/plugin-packs/postcss-preset-env/test/basic.vendors-3.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.vendors-3.expect.css @@ -17,18 +17,21 @@ order: 2; } -.test-logical-properties-and-values:dir(ltr) { - margin: 1px 4px 3px 2px; +.test-logical-properties-and-values { + margin-left: 1px; + margin-right: 2px; + order: 3; + padding-top: 4px; + padding-bottom: 4px; } -.test-logical-properties-and-values:dir(rtl) { - margin: 1px 2px 3px 4px; +.test-logical-resize { + resize: inline; } -.test-logical-properties-and-values { - order: 3; - padding-top: 5px; - padding-bottom: 5px; +.test-logical-viewport-units { + width: calc(10vw + 5px); + width: calc(10vi + 5px); } .test-nesting-rules { @@ -400,12 +403,8 @@ display: ruby-text flow; } -.logical-float:dir(ltr) { - float: left; -} - -.logical-float:dir(rtl) { - float: right; +.logical-float { + float: inline-start; } .color-function { @@ -486,10 +485,7 @@ right: round(nearest, 2.5px, 1px); bottom: round(up, 2.5px, 1px); left: round(down, 2.5px, 1px); - top: round(to-zero, 2.5px, 1px); - right: round(to-zero, 2.5px, 1px); - bottom: round(to-zero, 2.5px, 1px); - left: round(to-zero, 2.5px, 1px); + padding-left: round(to-zero, 2.5px, 1px); } .trigonometric { @@ -543,24 +539,11 @@ text-decoration: 3px wavy pink overline; } -.stage__container:dir(ltr) { +.stage__container { left: 1rem; left: var(--size, 1rem); } -.stage__container:dir(rtl) { - right: 1rem; - right: var(--size, 1rem); -} - -.stage__container:dir(ltr) { - left: 1rem; -} - -.stage__container:dir(rtl) { - right: 1rem; -} - :root { content: "plain :scope"; } diff --git a/plugin-packs/postcss-preset-env/test/layers-basic.expect.css b/plugin-packs/postcss-preset-env/test/layers-basic.expect.css index 2029f8f6f..f337d27aa 100644 --- a/plugin-packs/postcss-preset-env/test/layers-basic.expect.css +++ b/plugin-packs/postcss-preset-env/test/layers-basic.expect.css @@ -19,7 +19,7 @@ --firebrick: rgb(179, 35, 35); } -@supports (color: color(display-p3 0 0 0)){ +@supports (color: color(display-p3 0 0 0)) { .test-custom-property-fallbacks:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { --firebrick: color(display-p3 0.64331 0.19245 0.16771); } @@ -51,23 +51,16 @@ order: 2; } -@media (-webkit-min-device-pixel-ratio: 2), (min--moz-device-pixel-ratio: 2), (-o-min-device-pixel-ratio: 2/1), (min-resolution: 192dpi){ +@media (-webkit-min-device-pixel-ratio: 2), (min--moz-device-pixel-ratio: 2), (-o-min-device-pixel-ratio: 2/1), (min-resolution: 192dpi) { .test-image-set-function:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { background-image: url(img/test-2x.png); } } -[dir="ltr"]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) .test-logical-properties-and-values{ - margin: 1px 4px 3px 2px; -} - -[dir="rtl"]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) .test-logical-properties-and-values{ - margin: 1px 2px 3px 4px; -} - .test-logical-properties-and-values:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { is-layer: C; + margin: logical 1px 2px 3px 4px; -webkit-box-ordinal-group: 4; -webkit-order: 3; -moz-box-ordinal-group: 4; @@ -821,5 +814,4 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n top: 2px; right: 2px; bottom: 2px; - left: 2px; } diff --git a/plugin-packs/postcss-preset-env/test/layers-basic.preserve.true.expect.css b/plugin-packs/postcss-preset-env/test/layers-basic.preserve.true.expect.css index b1ece9af9..34c4de72d 100644 --- a/plugin-packs/postcss-preset-env/test/layers-basic.preserve.true.expect.css +++ b/plugin-packs/postcss-preset-env/test/layers-basic.preserve.true.expect.css @@ -67,22 +67,6 @@ } } -[dir="ltr"]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) .test-logical-properties-and-values{ - margin: 1px 4px 3px 2px; -} - -.test-logical-properties-and-values:dir(ltr):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#){ - margin: 1px 4px 3px 2px; -} - -[dir="rtl"]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) .test-logical-properties-and-values{ - margin: 1px 2px 3px 4px; -} - -.test-logical-properties-and-values:dir(rtl):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#){ - margin: 1px 2px 3px 4px; -} - .test-logical-properties-and-values:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { is-layer: C; margin: logical 1px 2px 3px 4px; @@ -93,7 +77,6 @@ order: 3; padding-top: 5px; padding-bottom: 5px; - padding-block: 5px; } .test-nesting-rules:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { @@ -1006,8 +989,6 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n top: 2px; right: 2px; bottom: 2px; - left: 2px; - inset: 2px; top: 2px; top: round(to-zero, 2.5px, 1px); right: 2px; @@ -1016,5 +997,4 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n bottom: round(to-zero, 2.5px, 1px); left: 2px; left: round(to-zero, 2.5px, 1px); - inset: round(to-zero, 2.5px, 1px); } diff --git a/plugins/css-has-pseudo/test/plugin-order-logical.after.expect.css b/plugins/css-has-pseudo/test/plugin-order-logical.after.expect.css index 66aacd2af..b276da57e 100644 --- a/plugins/css-has-pseudo/test/plugin-order-logical.after.expect.css +++ b/plugins/css-has-pseudo/test/plugin-order-logical.after.expect.css @@ -1,6 +1,3 @@ -.js-has-pseudo [csstools-has-2j-2s-2x-36-1p-y-30-38-36-y-2l-w-2p-1m-2w-2p-37-14-1a-2q-15]:not(.does-not-exist):not(does-not-exist) { - margin-left: 2px -} -.js-has-pseudo [csstools-has-2j-2s-2x-36-1p-y-36-38-30-y-2l-w-2p-1m-2w-2p-37-14-1a-2q-15]:not(.does-not-exist):not(does-not-exist) { - margin-right: 2px +.js-has-pseudo [csstools-has-2p-1m-2w-2p-37-14-1a-2q-15]:not(does-not-exist) { + margin-left: 2px; } diff --git a/plugins/css-has-pseudo/test/plugin-order-logical.after.preserve.expect.css b/plugins/css-has-pseudo/test/plugin-order-logical.after.preserve.expect.css index 045fae412..026ede546 100644 --- a/plugins/css-has-pseudo/test/plugin-order-logical.after.preserve.expect.css +++ b/plugins/css-has-pseudo/test/plugin-order-logical.after.preserve.expect.css @@ -1,57 +1,9 @@ -.js-has-pseudo [csstools-has-2j-2s-2x-36-1p-y-30-38-36-y-2l-w-2p-1m-2w-2p-37-14-1a-2q-15]:not(.does-not-exist):not(does-not-exist) { - margin-left: 2px; -} -[dir="ltr"] a:has(.b) { - margin-left: 2px; -} -.js-has-pseudo [csstools-has-2p-1m-2w-2p-37-14-1a-2q-15-1m-2s-2x-36-14-30-38-36-15]:not(.does-not-exist):not(does-not-exist) { - margin-left: 2px; -} -a:has(.b):dir(ltr) { - margin-left: 2px; -} -.js-has-pseudo [csstools-has-2j-2s-2x-36-1p-y-36-38-30-y-2l-w-2p-1m-2w-2p-37-14-1a-2q-15]:not(.does-not-exist):not(does-not-exist) { - margin-right: 2px; -} -[dir="rtl"] a:has(.b) { - margin-right: 2px; -} -.js-has-pseudo [csstools-has-2p-1m-2w-2p-37-14-1a-2q-15-1m-2s-2x-36-14-36-38-30-15]:not(.does-not-exist):not(does-not-exist) { - margin-right: 2px; -} -a:has(.b):dir(rtl) { - margin-right: 2px; -} -[dir="ltr"] .js-has-pseudo [csstools-has-2p-1m-2w-2p-37-14-1a-2q-15]:not(does-not-exist) { - margin-left: 2px; -} -.js-has-pseudo [csstools-has-2p-1m-2w-2p-37-14-1a-2q-15]:not(does-not-exist):dir(ltr) { - margin-left: 2px; -} -[dir="rtl"] .js-has-pseudo [csstools-has-2p-1m-2w-2p-37-14-1a-2q-15]:not(does-not-exist) { - margin-right: 2px; -} -.js-has-pseudo [csstools-has-2p-1m-2w-2p-37-14-1a-2q-15]:not(does-not-exist):dir(rtl) { - margin-right: 2px; -} .js-has-pseudo [csstools-has-2p-1m-2w-2p-37-14-1a-2q-15]:not(does-not-exist) { - margin-inline-start: 2px; -} -[dir="ltr"] .js-has-pseudo [csstools-has-2p-1m-2w-2p-37-14-1a-2q-15]:not(does-not-exist) { margin-left: 2px; } -.js-has-pseudo [csstools-has-2p-1m-2w-2p-37-14-1a-2q-15]:not(does-not-exist):dir(ltr) { - margin-left: 2px; -} -[dir="rtl"] .js-has-pseudo [csstools-has-2p-1m-2w-2p-37-14-1a-2q-15]:not(does-not-exist) { - margin-right: 2px; -} -.js-has-pseudo [csstools-has-2p-1m-2w-2p-37-14-1a-2q-15]:not(does-not-exist):dir(rtl) { - margin-right: 2px; -} .js-has-pseudo [csstools-has-2p-1m-2w-2p-37-14-1a-2q-15]:not(does-not-exist) { - margin-inline-start: 2px; + margin-left: 2px; } a:has(.b) { - margin-inline-start: 2px; + margin-left: 2px; } diff --git a/plugins/css-has-pseudo/test/plugin-order-logical.before.expect.css b/plugins/css-has-pseudo/test/plugin-order-logical.before.expect.css index 66aacd2af..b276da57e 100644 --- a/plugins/css-has-pseudo/test/plugin-order-logical.before.expect.css +++ b/plugins/css-has-pseudo/test/plugin-order-logical.before.expect.css @@ -1,6 +1,3 @@ -.js-has-pseudo [csstools-has-2j-2s-2x-36-1p-y-30-38-36-y-2l-w-2p-1m-2w-2p-37-14-1a-2q-15]:not(.does-not-exist):not(does-not-exist) { - margin-left: 2px -} -.js-has-pseudo [csstools-has-2j-2s-2x-36-1p-y-36-38-30-y-2l-w-2p-1m-2w-2p-37-14-1a-2q-15]:not(.does-not-exist):not(does-not-exist) { - margin-right: 2px +.js-has-pseudo [csstools-has-2p-1m-2w-2p-37-14-1a-2q-15]:not(does-not-exist) { + margin-left: 2px; } diff --git a/plugins/css-has-pseudo/test/plugin-order-logical.before.preserve.expect.css b/plugins/css-has-pseudo/test/plugin-order-logical.before.preserve.expect.css index 045fae412..026ede546 100644 --- a/plugins/css-has-pseudo/test/plugin-order-logical.before.preserve.expect.css +++ b/plugins/css-has-pseudo/test/plugin-order-logical.before.preserve.expect.css @@ -1,57 +1,9 @@ -.js-has-pseudo [csstools-has-2j-2s-2x-36-1p-y-30-38-36-y-2l-w-2p-1m-2w-2p-37-14-1a-2q-15]:not(.does-not-exist):not(does-not-exist) { - margin-left: 2px; -} -[dir="ltr"] a:has(.b) { - margin-left: 2px; -} -.js-has-pseudo [csstools-has-2p-1m-2w-2p-37-14-1a-2q-15-1m-2s-2x-36-14-30-38-36-15]:not(.does-not-exist):not(does-not-exist) { - margin-left: 2px; -} -a:has(.b):dir(ltr) { - margin-left: 2px; -} -.js-has-pseudo [csstools-has-2j-2s-2x-36-1p-y-36-38-30-y-2l-w-2p-1m-2w-2p-37-14-1a-2q-15]:not(.does-not-exist):not(does-not-exist) { - margin-right: 2px; -} -[dir="rtl"] a:has(.b) { - margin-right: 2px; -} -.js-has-pseudo [csstools-has-2p-1m-2w-2p-37-14-1a-2q-15-1m-2s-2x-36-14-36-38-30-15]:not(.does-not-exist):not(does-not-exist) { - margin-right: 2px; -} -a:has(.b):dir(rtl) { - margin-right: 2px; -} -[dir="ltr"] .js-has-pseudo [csstools-has-2p-1m-2w-2p-37-14-1a-2q-15]:not(does-not-exist) { - margin-left: 2px; -} -.js-has-pseudo [csstools-has-2p-1m-2w-2p-37-14-1a-2q-15]:not(does-not-exist):dir(ltr) { - margin-left: 2px; -} -[dir="rtl"] .js-has-pseudo [csstools-has-2p-1m-2w-2p-37-14-1a-2q-15]:not(does-not-exist) { - margin-right: 2px; -} -.js-has-pseudo [csstools-has-2p-1m-2w-2p-37-14-1a-2q-15]:not(does-not-exist):dir(rtl) { - margin-right: 2px; -} .js-has-pseudo [csstools-has-2p-1m-2w-2p-37-14-1a-2q-15]:not(does-not-exist) { - margin-inline-start: 2px; -} -[dir="ltr"] .js-has-pseudo [csstools-has-2p-1m-2w-2p-37-14-1a-2q-15]:not(does-not-exist) { margin-left: 2px; } -.js-has-pseudo [csstools-has-2p-1m-2w-2p-37-14-1a-2q-15]:not(does-not-exist):dir(ltr) { - margin-left: 2px; -} -[dir="rtl"] .js-has-pseudo [csstools-has-2p-1m-2w-2p-37-14-1a-2q-15]:not(does-not-exist) { - margin-right: 2px; -} -.js-has-pseudo [csstools-has-2p-1m-2w-2p-37-14-1a-2q-15]:not(does-not-exist):dir(rtl) { - margin-right: 2px; -} .js-has-pseudo [csstools-has-2p-1m-2w-2p-37-14-1a-2q-15]:not(does-not-exist) { - margin-inline-start: 2px; + margin-left: 2px; } a:has(.b) { - margin-inline-start: 2px; + margin-left: 2px; } diff --git a/plugins/postcss-logical-float-and-clear/.gitignore b/plugins/postcss-logical-float-and-clear/.gitignore new file mode 100644 index 000000000..e5b28db4a --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/.gitignore @@ -0,0 +1,6 @@ +node_modules +package-lock.json +yarn.lock +*.result.css +*.result.css.map +*.result.html diff --git a/plugins/postcss-logical-float-and-clear/.nvmrc b/plugins/postcss-logical-float-and-clear/.nvmrc new file mode 100644 index 000000000..39e593ebe --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/.nvmrc @@ -0,0 +1 @@ +v18.8.0 diff --git a/plugins/postcss-logical-float-and-clear/.tape.mjs b/plugins/postcss-logical-float-and-clear/.tape.mjs new file mode 100644 index 000000000..68721bc51 --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/.tape.mjs @@ -0,0 +1,29 @@ +import postcssTape from '../../packages/postcss-tape/dist/index.mjs'; +import plugin from '@csstools/postcss-logical-float-and-clear'; + +postcssTape(plugin)({ + basic: { + message: "supports basic usage", + }, + 'basic:hebrew': { + message: "supports { inlineDirection: 'right-to-left' }", + options: { + inlineDirection: 'right-to-left' + } + }, + 'basic:vertical': { + message: "supports { inlineDirection: 'top-to-bottom' }", + options: { + inlineDirection: 'top-to-bottom' + } + }, + 'examples/example': { + message: 'minimal example', + }, + 'examples/example:hebrew': { + message: 'minimal example', + options: { + inlineDirection: 'right-to-left' + } + }, +}); diff --git a/plugins/postcss-logical-float-and-clear/CHANGELOG.md b/plugins/postcss-logical-float-and-clear/CHANGELOG.md new file mode 100644 index 000000000..475c986f9 --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changes to PostCSS Logical Float And Clear + +### 1.0.0 (January 19, 2023) + +- Initial version diff --git a/plugins/postcss-logical-float-and-clear/INSTALL.md b/plugins/postcss-logical-float-and-clear/INSTALL.md new file mode 100644 index 000000000..c408c6744 --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/INSTALL.md @@ -0,0 +1,235 @@ +# Installing PostCSS Logical Float And Clear + +[PostCSS Logical Float And Clear] runs in all Node environments, with special instructions for: + +- [Node](#node) +- [PostCSS CLI](#postcss-cli) +- [PostCSS Load Config](#postcss-load-config) +- [Webpack](#webpack) +- [Next.js](#nextjs) +- [Gulp](#gulp) +- [Grunt](#grunt) + + + +## Node + +Add [PostCSS Logical Float And Clear] to your project: + +```bash +npm install postcss @csstools/postcss-logical-float-and-clear --save-dev +``` + +Use it as a [PostCSS] plugin: + +```js +// commonjs +const postcss = require('postcss'); +const postcssLogicalFloatAndClear = require('@csstools/postcss-logical-float-and-clear'); + +postcss([ + postcssLogicalFloatAndClear(/* pluginOptions */) +]).process(YOUR_CSS /*, processOptions */); +``` + +```js +// esm +import postcss from 'postcss'; +import postcssLogicalFloatAndClear from '@csstools/postcss-logical-float-and-clear'; + +postcss([ + postcssLogicalFloatAndClear(/* pluginOptions */) +]).process(YOUR_CSS /*, processOptions */); +``` + +## PostCSS CLI + +Add [PostCSS CLI] to your project: + +```bash +npm install postcss-cli @csstools/postcss-logical-float-and-clear --save-dev +``` + +Use [PostCSS Logical Float And Clear] in your `postcss.config.js` configuration file: + +```js +const postcssLogicalFloatAndClear = require('@csstools/postcss-logical-float-and-clear'); + +module.exports = { + plugins: [ + postcssLogicalFloatAndClear(/* pluginOptions */) + ] +} +``` + +## PostCSS Load Config + +If your framework/CLI supports [`postcss-load-config`](https://github.com/postcss/postcss-load-config). + +```bash +npm install @csstools/postcss-logical-float-and-clear --save-dev +``` + +`package.json`: + +```json +{ + "postcss": { + "plugins": { + "@csstools/postcss-logical-float-and-clear": {} + } + } +} +``` + +`.postcssrc.json`: + +```json +{ + "plugins": { + "@csstools/postcss-logical-float-and-clear": {} + } +} +``` + +_See the [README of `postcss-load-config`](https://github.com/postcss/postcss-load-config#usage) for more usage options._ + +## Webpack + +_Webpack version 5_ + +Add [PostCSS Loader] to your project: + +```bash +npm install postcss-loader @csstools/postcss-logical-float-and-clear --save-dev +``` + +Use [PostCSS Logical Float And Clear] in your Webpack configuration: + +```js +module.exports = { + module: { + rules: [ + { + test: /\.css$/i, + use: [ + "style-loader", + { + loader: "css-loader", + options: { importLoaders: 1 }, + }, + { + loader: "postcss-loader", + options: { + postcssOptions: { + plugins: [ + // Other plugins, + [ + "@csstools/postcss-logical-float-and-clear", + { + // Options + }, + ], + ], + }, + }, + }, + ], + }, + ], + }, +}; +``` + +## Next.js + +Read the instructions on how to [customize the PostCSS configuration in Next.js](https://nextjs.org/docs/advanced-features/customizing-postcss-config) + +```bash +npm install @csstools/postcss-logical-float-and-clear --save-dev +``` + +Use [PostCSS Logical Float And Clear] in your `postcss.config.json` file: + +```json +{ + "plugins": [ + "@csstools/postcss-logical-float-and-clear" + ] +} +``` + +```json5 +{ + "plugins": [ + [ + "@csstools/postcss-logical-float-and-clear", + { + // Optionally add plugin options + } + ] + ] +} +``` + +## Gulp + +Add [Gulp PostCSS] to your project: + +```bash +npm install gulp-postcss @csstools/postcss-logical-float-and-clear --save-dev +``` + +Use [PostCSS Logical Float And Clear] in your Gulpfile: + +```js +const postcss = require('gulp-postcss'); +const postcssLogicalFloatAndClear = require('@csstools/postcss-logical-float-and-clear'); + +gulp.task('css', function () { + var plugins = [ + postcssLogicalFloatAndClear(/* pluginOptions */) + ]; + + return gulp.src('./src/*.css') + .pipe(postcss(plugins)) + .pipe(gulp.dest('.')); +}); +``` + +## Grunt + +Add [Grunt PostCSS] to your project: + +```bash +npm install grunt-postcss @csstools/postcss-logical-float-and-clear --save-dev +``` + +Use [PostCSS Logical Float And Clear] in your Gruntfile: + +```js +const postcssLogicalFloatAndClear = require('@csstools/postcss-logical-float-and-clear'); + +grunt.loadNpmTasks('grunt-postcss'); + +grunt.initConfig({ + postcss: { + options: { + processors: [ + postcssLogicalFloatAndClear(/* pluginOptions */) + ] + }, + dist: { + src: '*.css' + } + } +}); +``` + +[Gulp PostCSS]: https://github.com/postcss/gulp-postcss +[Grunt PostCSS]: https://github.com/nDmitry/grunt-postcss +[PostCSS]: https://github.com/postcss/postcss +[PostCSS CLI]: https://github.com/postcss/postcss-cli +[PostCSS Loader]: https://github.com/postcss/postcss-loader +[PostCSS Logical Float And Clear]: https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-logical-float-and-clear +[Next.js]: https://nextjs.org diff --git a/plugins/postcss-logical-float-and-clear/LICENSE.md b/plugins/postcss-logical-float-and-clear/LICENSE.md new file mode 100644 index 000000000..0bc1fa706 --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/LICENSE.md @@ -0,0 +1,108 @@ +# CC0 1.0 Universal + +## Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an “owner”) of an original work of +authorship and/or a database (each, a “Work”). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific works +(“Commons”) that the public can reliably and without fear of later claims of +infringement build upon, modify, incorporate in other works, reuse and +redistribute as freely as possible in any form whatsoever and for any purposes, +including without limitation commercial purposes. These owners may contribute +to the Commons to promote the ideal of a free culture and the further +production of creative, cultural and scientific works, or to gain reputation or +greater distribution for their Work in part through the use and efforts of +others. + +For these and/or other purposes and motivations, and without any expectation of +additional consideration or compensation, the person associating CC0 with a +Work (the “Affirmer”), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and +publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be + protected by copyright and related or neighboring rights (“Copyright and + Related Rights”). Copyright and Related Rights include, but are not limited + to, the following: + 1. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + 2. moral rights retained by the original author(s) and/or performer(s); + 3. publicity and privacy rights pertaining to a person’s image or likeness + depicted in a Work; + 4. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(i), below; + 5. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + 6. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + 7. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations + thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, + applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and + unconditionally waives, abandons, and surrenders all of Affirmer’s Copyright + and Related Rights and associated claims and causes of action, whether now + known or unknown (including existing as well as future claims and causes of + action), in the Work (i) in all territories worldwide, (ii) for the maximum + duration provided by applicable law or treaty (including future time + extensions), (iii) in any current or future medium and for any number of + copies, and (iv) for any purpose whatsoever, including without limitation + commercial, advertising or promotional purposes (the “Waiver”). Affirmer + makes the Waiver for the benefit of each member of the public at large and + to the detriment of Affirmer’s heirs and successors, fully intending that + such Waiver shall not be subject to revocation, rescission, cancellation, + termination, or any other legal or equitable action to disrupt the quiet + enjoyment of the Work by the public as contemplated by Affirmer’s express + Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be + judged legally invalid or ineffective under applicable law, then the Waiver + shall be preserved to the maximum extent permitted taking into account + Affirmer’s express Statement of Purpose. In addition, to the extent the + Waiver is so judged Affirmer hereby grants to each affected person a + royalty-free, non transferable, non sublicensable, non exclusive, + irrevocable and unconditional license to exercise Affirmer’s Copyright and + Related Rights in the Work (i) in all territories worldwide, (ii) for the + maximum duration provided by applicable law or treaty (including future time + extensions), (iii) in any current or future medium and for any number of + copies, and (iv) for any purpose whatsoever, including without limitation + commercial, advertising or promotional purposes (the “License”). The License + shall be deemed effective as of the date CC0 was applied by Affirmer to the + Work. Should any part of the License for any reason be judged legally + invalid or ineffective under applicable law, such partial invalidity or + ineffectiveness shall not invalidate the remainder of the License, and in + such case Affirmer hereby affirms that he or she will not (i) exercise any + of his or her remaining Copyright and Related Rights in the Work or (ii) + assert any associated claims and causes of action with respect to the Work, + in either case contrary to Affirmer’s express Statement of Purpose. + +4. Limitations and Disclaimers. + 1. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + 2. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or + otherwise, including without limitation warranties of title, + merchantability, fitness for a particular purpose, non infringement, or + the absence of latent or other defects, accuracy, or the present or + absence of errors, whether or not discoverable, all to the greatest + extent permissible under applicable law. + 3. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person’s Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the Work. + 4. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see +http://creativecommons.org/publicdomain/zero/1.0/. diff --git a/plugins/postcss-logical-float-and-clear/README.md b/plugins/postcss-logical-float-and-clear/README.md new file mode 100644 index 000000000..268c30855 --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/README.md @@ -0,0 +1,95 @@ +# PostCSS Logical Float And Clear [PostCSS Logo][PostCSS] + +[npm version][npm-url] [CSS Standard Status][css-url] [Build Status][cli-url] [Discord][discord] + +[PostCSS Logical Float And Clear] lets you use logical, rather than physical, direction and dimension mappings in CSS, following the [CSS Logical Properties and Values] specification. + +```pcss +.element { + clear: inline-start; + float: inline-end; +} + +/* becomes */ + +.element { + clear: left; + float: right; +} +``` + +## Usage + +Add [PostCSS Logical Float And Clear] to your project: + +```bash +npm install postcss @csstools/postcss-logical-float-and-clear --save-dev +``` + +Use it as a [PostCSS] plugin: + +```js +const postcss = require('postcss'); +const postcssLogicalFloatAndClear = require('@csstools/postcss-logical-float-and-clear'); + +postcss([ + postcssLogicalFloatAndClear(/* pluginOptions */) +]).process(YOUR_CSS /*, processOptions */); +``` + +[PostCSS Logical Float And Clear] runs in all Node environments, with special +instructions for: + +- [Node](INSTALL.md#node) +- [PostCSS CLI](INSTALL.md#postcss-cli) +- [PostCSS Load Config](INSTALL.md#postcss-load-config) +- [Webpack](INSTALL.md#webpack) +- [Next.js](INSTALL.md#nextjs) +- [Gulp](INSTALL.md#gulp) +- [Grunt](INSTALL.md#grunt) + +## Options + +### inlineDirection + +The `inlineDirection` option allows you to specify the direction of the inline axe. The default value is `left-to-right` respectively which would match any latin language. + +You might want to tweak these value if you are using a different writing system, such as Arabic, Hebrew or Chinese for example. + +```js +postcssLogicalFloatAndClear({ + inlineDirection: 'right-to-left' +}) +``` + +```pcss +.element { + clear: inline-start; + float: inline-end; +} + +/* becomes */ + +.element { + clear: right; + float: left; +} +``` + +Each direction must be one of the following: + +- `top-to-bottom` +- `bottom-to-top` +- `left-to-right` +- `right-to-left` + +Please do note that transformations won't run if `inlineDirection` becomes vertical. + +[cli-url]: https://github.com/csstools/postcss-plugins/actions/workflows/test.yml?query=workflow/test +[css-url]: https://cssdb.org/#float-clear-logical-values +[discord]: https://discord.gg/bUadyRwkJS +[npm-url]: https://www.npmjs.com/package/@csstools/postcss-logical-float-and-clear + +[PostCSS]: https://github.com/postcss/postcss +[PostCSS Logical Float And Clear]: https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-logical-float-and-clear +[CSS Logical Properties and Values]: https://www.w3.org/TR/css-logical-1/#float-clear diff --git a/plugins/postcss-logical-float-and-clear/dist/index.cjs b/plugins/postcss-logical-float-and-clear/dist/index.cjs new file mode 100644 index 000000000..c073727d7 --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/dist/index.cjs @@ -0,0 +1 @@ +"use strict";const t="inline-start",o="inline-end";var e,i;function directionFlowToAxes(t){switch(t){case e.TopToBottom:return[i.Top,i.Bottom];case e.BottomToTop:return[i.Bottom,i.Top];case e.RightToLeft:return[i.Right,i.Left];case e.LeftToRight:return[i.Left,i.Right]}}function cloneDeclaration(t,o,e){t.parent&&t.parent.some((t=>"decl"==t.type&&t.prop===e&&t.value===o))||t.cloneBefore({value:o,prop:e})}!function(t){t.TopToBottom="top-to-bottom",t.BottomToTop="bottom-to-top",t.RightToLeft="right-to-left",t.LeftToRight="left-to-right"}(e||(e={})),function(t){t.Top="top",t.Right="right",t.Bottom="bottom",t.Left="left"}(i||(i={}));const creator=i=>{const n=Object.assign({inlineDirection:e.LeftToRight},i),c=Object.values(e);if(!c.includes(n.inlineDirection))throw new Error(`[postcss-logical-float-and-clear] "inlineDirection" must be one of ${c.join(", ")}`);if(![e.LeftToRight,e.RightToLeft].includes(n.inlineDirection))return{postcssPlugin:"postcss-logical-float-and-clear",Once(){}};const[r,l]=directionFlowToAxes(n.inlineDirection),makeTransform=e=>{const i=e.value.toLowerCase();if(![t,o].includes(i))return;cloneDeclaration(e,i===t?r:l,e.prop),e.remove()};return{postcssPlugin:"postcss-logical-float-and-clear",Declaration:{float:makeTransform,clear:makeTransform}}};creator.postcss=!0,module.exports=creator; diff --git a/plugins/postcss-logical-float-and-clear/dist/index.d.ts b/plugins/postcss-logical-float-and-clear/dist/index.d.ts new file mode 100644 index 000000000..8faa333f6 --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/dist/index.d.ts @@ -0,0 +1,9 @@ +import type { PluginCreator } from 'postcss'; +import { DirectionFlow } from './lib/types'; +/** postcss-logical-float-and-clear plugin options */ +export type pluginOptions = { + /** Sets the direction for inline. default: left-to-right */ + inlineDirection?: DirectionFlow; +}; +declare const creator: PluginCreator; +export default creator; diff --git a/plugins/postcss-logical-float-and-clear/dist/index.mjs b/plugins/postcss-logical-float-and-clear/dist/index.mjs new file mode 100644 index 000000000..f05b65782 --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/dist/index.mjs @@ -0,0 +1 @@ +const t="inline-start",o="inline-end";var e,n;function directionFlowToAxes(t){switch(t){case e.TopToBottom:return[n.Top,n.Bottom];case e.BottomToTop:return[n.Bottom,n.Top];case e.RightToLeft:return[n.Right,n.Left];case e.LeftToRight:return[n.Left,n.Right]}}function cloneDeclaration(t,o,e){t.parent&&t.parent.some((t=>"decl"==t.type&&t.prop===e&&t.value===o))||t.cloneBefore({value:o,prop:e})}!function(t){t.TopToBottom="top-to-bottom",t.BottomToTop="bottom-to-top",t.RightToLeft="right-to-left",t.LeftToRight="left-to-right"}(e||(e={})),function(t){t.Top="top",t.Right="right",t.Bottom="bottom",t.Left="left"}(n||(n={}));const creator=n=>{const i=Object.assign({inlineDirection:e.LeftToRight},n),c=Object.values(e);if(!c.includes(i.inlineDirection))throw new Error(`[postcss-logical-float-and-clear] "inlineDirection" must be one of ${c.join(", ")}`);if(![e.LeftToRight,e.RightToLeft].includes(i.inlineDirection))return{postcssPlugin:"postcss-logical-float-and-clear",Once(){}};const[r,l]=directionFlowToAxes(i.inlineDirection),makeTransform=e=>{const n=e.value.toLowerCase();if(![t,o].includes(n))return;cloneDeclaration(e,n===t?r:l,e.prop),e.remove()};return{postcssPlugin:"postcss-logical-float-and-clear",Declaration:{float:makeTransform,clear:makeTransform}}};creator.postcss=!0;export{creator as default}; diff --git a/plugins/postcss-logical-float-and-clear/dist/lib/clone-declaration.d.ts b/plugins/postcss-logical-float-and-clear/dist/lib/clone-declaration.d.ts new file mode 100644 index 000000000..1503bf6f1 --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/dist/lib/clone-declaration.d.ts @@ -0,0 +1,2 @@ +import type { Declaration } from 'postcss'; +export declare function cloneDeclaration(declaration: Declaration, value: string, prop: string): void; diff --git a/plugins/postcss-logical-float-and-clear/dist/lib/types.d.ts b/plugins/postcss-logical-float-and-clear/dist/lib/types.d.ts new file mode 100644 index 000000000..2b3c47f9b --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/dist/lib/types.d.ts @@ -0,0 +1,18 @@ +export declare const DirectionValues: { + BlockStart: string; + BlockEnd: string; + InlineStart: string; + InlineEnd: string; +}; +export declare enum DirectionFlow { + TopToBottom = "top-to-bottom", + BottomToTop = "bottom-to-top", + RightToLeft = "right-to-left", + LeftToRight = "left-to-right" +} +export declare enum Axes { + Top = "top", + Right = "right", + Bottom = "bottom", + Left = "left" +} diff --git a/plugins/postcss-logical-float-and-clear/dist/utils/direction-flow-to-axes.d.ts b/plugins/postcss-logical-float-and-clear/dist/utils/direction-flow-to-axes.d.ts new file mode 100644 index 000000000..2652d71d8 --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/dist/utils/direction-flow-to-axes.d.ts @@ -0,0 +1,2 @@ +import { DirectionFlow, Axes } from '../lib/types'; +export declare function directionFlowToAxes(directionFlow: DirectionFlow): [Axes, Axes]; diff --git a/plugins/postcss-logical-float-and-clear/docs/README.md b/plugins/postcss-logical-float-and-clear/docs/README.md new file mode 100644 index 000000000..b14f97731 --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/docs/README.md @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + +
+ +[] lets you use logical, rather than physical, direction and dimension mappings in CSS, following the [CSS Logical Properties and Values] specification. + +```pcss + + +/* becomes */ + + +``` + + + + + +## Options + +### inlineDirection + +The `inlineDirection` option allows you to specify the direction of the inline axe. The default value is `left-to-right` respectively which would match any latin language. + +You might want to tweak these value if you are using a different writing system, such as Arabic, Hebrew or Chinese for example. + +```js +({ + inlineDirection: 'right-to-left' +}) +``` + +```pcss + + +/* becomes */ + + +``` + +Each direction must be one of the following: + +- `top-to-bottom` +- `bottom-to-top` +- `left-to-right` +- `right-to-left` + +Please do note that transformations won't run if `inlineDirection` becomes vertical. + + +[CSS Logical Properties and Values]: diff --git a/plugins/postcss-logical-float-and-clear/package.json b/plugins/postcss-logical-float-and-clear/package.json new file mode 100644 index 000000000..71b61d38b --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/package.json @@ -0,0 +1,82 @@ +{ + "name": "@csstools/postcss-logical-float-and-clear", + "description": "Use flow-relative (inline-start and inline-end) values for float and clear", + "version": "1.0.0", + "contributors": [ + { + "name": "Antonio Laguna", + "email": "antonio@laguna.es", + "url": "https://antonio.laguna.es" + }, + { + "name": "Romain Menke", + "email": "romainmenke@gmail.com" + } + ], + "license": "CC0-1.0", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "main": "dist/index.cjs", + "module": "dist/index.mjs", + "types": "dist/index.d.ts", + "exports": { + ".": { + "import": "./dist/index.mjs", + "require": "./dist/index.cjs", + "default": "./dist/index.mjs" + } + }, + "files": [ + "CHANGELOG.md", + "LICENSE.md", + "README.md", + "dist" + ], + "peerDependencies": { + "postcss": "^8.4" + }, + "scripts": { + "prebuild": "npm run clean", + "build": "rollup -c ../../rollup/default.mjs", + "clean": "node -e \"fs.rmSync('./dist', { recursive: true, force: true }); fs.mkdirSync('./dist');\"", + "docs": "node ../../.github/bin/generate-docs/install.mjs && node ../../.github/bin/generate-docs/readme.mjs", + "lint": "npm run lint:eslint && npm run lint:package-json", + "lint:eslint": "eslint ./src --ext .js --ext .ts --ext .mjs --no-error-on-unmatched-pattern", + "lint:package-json": "node ../../.github/bin/format-package-json.mjs", + "prepublishOnly": "npm run clean && npm run build && npm run test", + "test": "node .tape.mjs && npm run test:exports", + "test:exports": "node ./test/_import.mjs && node ./test/_require.cjs", + "test:rewrite-expects": "REWRITE_EXPECTS=true node .tape.mjs" + }, + "homepage": "https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-logical-float-and-clear#readme", + "repository": { + "type": "git", + "url": "https://github.com/csstools/postcss-plugins.git", + "directory": "plugins/postcss-logical-float-and-clear" + }, + "bugs": "https://github.com/csstools/postcss-plugins/issues", + "keywords": [ + "block", + "clear", + "css", + "float", + "inline", + "logical", + "postcss", + "postcss-plugin" + ], + "csstools": { + "cssdbId": "float-clear-logical-values", + "exportName": "postcssLogicalFloatAndClear", + "humanReadableName": "PostCSS Logical Float And Clear", + "specUrl": "https://www.w3.org/TR/css-logical-1/#float-clear" + }, + "volta": { + "extends": "../../package.json" + } +} diff --git a/plugins/postcss-logical-float-and-clear/src/index.ts b/plugins/postcss-logical-float-and-clear/src/index.ts new file mode 100644 index 000000000..29caabf91 --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/src/index.ts @@ -0,0 +1,63 @@ +import type { PluginCreator, Declaration } from 'postcss'; +import { DirectionFlow, DirectionValues } from './lib/types'; +import { directionFlowToAxes } from './utils/direction-flow-to-axes'; +import { cloneDeclaration } from './lib/clone-declaration'; + +/** postcss-logical-float-and-clear plugin options */ +export type pluginOptions = { + /** Sets the direction for inline. default: left-to-right */ + inlineDirection?: DirectionFlow, +}; + +const creator: PluginCreator = (opts?: pluginOptions) => { + const options = Object.assign( + // Default options + { + inlineDirection: DirectionFlow.LeftToRight, + }, + // Provided options + opts, + ); + + const directionValues = Object.values(DirectionFlow); + if (!directionValues.includes(options.inlineDirection)) { + throw new Error(`[postcss-logical-float-and-clear] "inlineDirection" must be one of ${directionValues.join(', ')}`); + } + + const isHorizontal = [DirectionFlow.LeftToRight, DirectionFlow.RightToLeft].includes(options.inlineDirection); + + if (!isHorizontal) { + return { + postcssPlugin: 'postcss-logical-float-and-clear', + Once() { + // noop + }, + }; + } + + const [inlineStart, inlineEnd] = directionFlowToAxes(options.inlineDirection); + const makeTransform = (decl: Declaration) => { + const value = decl.value.toLowerCase(); + const possibleValues = [DirectionValues.InlineStart, DirectionValues.InlineEnd]; + + if (!possibleValues.includes(value)) { + return; + } + + const newValue = value === DirectionValues.InlineStart ? inlineStart : inlineEnd; + cloneDeclaration(decl, newValue, decl.prop); + decl.remove(); + }; + + return { + postcssPlugin: 'postcss-logical-float-and-clear', + Declaration: { + 'float': makeTransform, + 'clear': makeTransform, + }, + }; +}; + +creator.postcss = true; + +export default creator; diff --git a/plugins/postcss-logical-float-and-clear/src/lib/clone-declaration.ts b/plugins/postcss-logical-float-and-clear/src/lib/clone-declaration.ts new file mode 100644 index 000000000..e78433f98 --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/src/lib/clone-declaration.ts @@ -0,0 +1,15 @@ +import type { Declaration } from 'postcss'; + +export function cloneDeclaration( + declaration: Declaration, + value: string, + prop: string, +): void { + if (declaration.parent && declaration.parent.some((childNode) => { + return childNode.type == 'decl' && childNode.prop === prop && childNode.value === value; + })) { + return; + } + + declaration.cloneBefore({ value, prop }); +} diff --git a/plugins/postcss-logical-float-and-clear/src/lib/types.ts b/plugins/postcss-logical-float-and-clear/src/lib/types.ts new file mode 100644 index 000000000..06807b9c0 --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/src/lib/types.ts @@ -0,0 +1,19 @@ +export const DirectionValues = { + BlockStart: 'block-start', + BlockEnd: 'block-end', + InlineStart: 'inline-start', + InlineEnd: 'inline-end', +}; +export enum DirectionFlow { + TopToBottom = 'top-to-bottom', + BottomToTop = 'bottom-to-top', + RightToLeft = 'right-to-left', + LeftToRight = 'left-to-right', +} + +export enum Axes { + Top = 'top', + Right = 'right', + Bottom = 'bottom', + Left = 'left', +} diff --git a/plugins/postcss-logical-float-and-clear/src/utils/direction-flow-to-axes.ts b/plugins/postcss-logical-float-and-clear/src/utils/direction-flow-to-axes.ts new file mode 100644 index 000000000..627a44479 --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/src/utils/direction-flow-to-axes.ts @@ -0,0 +1,17 @@ +import { DirectionFlow, Axes } from '../lib/types'; + +export function directionFlowToAxes(directionFlow: DirectionFlow): [Axes, Axes] { + switch (directionFlow) { + case DirectionFlow.TopToBottom: + return [Axes.Top, Axes.Bottom]; + + case DirectionFlow.BottomToTop: + return [Axes.Bottom, Axes.Top]; + + case DirectionFlow.RightToLeft: + return [Axes.Right, Axes.Left]; + + case DirectionFlow.LeftToRight: + return [Axes.Left, Axes.Right]; + } +} diff --git a/plugins/postcss-logical-float-and-clear/test/_import.mjs b/plugins/postcss-logical-float-and-clear/test/_import.mjs new file mode 100644 index 000000000..d7a7b04ab --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/test/_import.mjs @@ -0,0 +1,6 @@ +import assert from 'assert'; +import plugin from '@csstools/postcss-logical-float-and-clear'; +plugin(); + +assert.ok(plugin.postcss, 'should have "postcss flag"'); +assert.equal(typeof plugin, 'function', 'should return a function'); diff --git a/plugins/postcss-logical-float-and-clear/test/_require.cjs b/plugins/postcss-logical-float-and-clear/test/_require.cjs new file mode 100644 index 000000000..9db181ef0 --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/test/_require.cjs @@ -0,0 +1,6 @@ +const assert = require('assert'); +const plugin = require('@csstools/postcss-logical-float-and-clear'); +plugin(); + +assert.ok(plugin.postcss, 'should have "postcss flag"'); +assert.equal(typeof plugin, 'function', 'should return a function'); diff --git a/plugins/postcss-logical-float-and-clear/test/basic.css b/plugins/postcss-logical-float-and-clear/test/basic.css new file mode 100644 index 000000000..0652e759b --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/test/basic.css @@ -0,0 +1,19 @@ +.foo { + clear: inline-start; + float: inline-end; +} + +.foo { + clear: iNlInE-eNd; + float: iNlInE-sTaRt; +} + +.foo { + clear: var(--inline-start); + float: var(--inline-end); +} + +.foo { + clear: page; + float: contour; +} diff --git a/plugins/postcss-logical-float-and-clear/test/basic.expect.css b/plugins/postcss-logical-float-and-clear/test/basic.expect.css new file mode 100644 index 000000000..a60b3c3ed --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/test/basic.expect.css @@ -0,0 +1,19 @@ +.foo { + clear: left; + float: right; +} + +.foo { + clear: right; + float: left; +} + +.foo { + clear: var(--inline-start); + float: var(--inline-end); +} + +.foo { + clear: page; + float: contour; +} diff --git a/plugins/postcss-logical-float-and-clear/test/basic.hebrew.expect.css b/plugins/postcss-logical-float-and-clear/test/basic.hebrew.expect.css new file mode 100644 index 000000000..b03e5b7fd --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/test/basic.hebrew.expect.css @@ -0,0 +1,19 @@ +.foo { + clear: right; + float: left; +} + +.foo { + clear: left; + float: right; +} + +.foo { + clear: var(--inline-start); + float: var(--inline-end); +} + +.foo { + clear: page; + float: contour; +} diff --git a/plugins/postcss-logical-float-and-clear/test/basic.vertical.expect.css b/plugins/postcss-logical-float-and-clear/test/basic.vertical.expect.css new file mode 100644 index 000000000..0652e759b --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/test/basic.vertical.expect.css @@ -0,0 +1,19 @@ +.foo { + clear: inline-start; + float: inline-end; +} + +.foo { + clear: iNlInE-eNd; + float: iNlInE-sTaRt; +} + +.foo { + clear: var(--inline-start); + float: var(--inline-end); +} + +.foo { + clear: page; + float: contour; +} diff --git a/plugins/postcss-logical-float-and-clear/test/examples/example.css b/plugins/postcss-logical-float-and-clear/test/examples/example.css new file mode 100644 index 000000000..86360cb3f --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/test/examples/example.css @@ -0,0 +1,4 @@ +.element { + clear: inline-start; + float: inline-end; +} diff --git a/plugins/postcss-logical-float-and-clear/test/examples/example.expect.css b/plugins/postcss-logical-float-and-clear/test/examples/example.expect.css new file mode 100644 index 000000000..8cf546267 --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/test/examples/example.expect.css @@ -0,0 +1,4 @@ +.element { + clear: left; + float: right; +} diff --git a/plugins/postcss-logical-float-and-clear/test/examples/example.hebrew.expect.css b/plugins/postcss-logical-float-and-clear/test/examples/example.hebrew.expect.css new file mode 100644 index 000000000..d117dfb1f --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/test/examples/example.hebrew.expect.css @@ -0,0 +1,4 @@ +.element { + clear: right; + float: left; +} diff --git a/plugins/postcss-logical-float-and-clear/tsconfig.json b/plugins/postcss-logical-float-and-clear/tsconfig.json new file mode 100644 index 000000000..e0d06239c --- /dev/null +++ b/plugins/postcss-logical-float-and-clear/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "declarationDir": "." + }, + "include": ["./src/**/*"], + "exclude": ["dist"], +} diff --git a/plugins/postcss-logical-resize/.gitignore b/plugins/postcss-logical-resize/.gitignore new file mode 100644 index 000000000..e5b28db4a --- /dev/null +++ b/plugins/postcss-logical-resize/.gitignore @@ -0,0 +1,6 @@ +node_modules +package-lock.json +yarn.lock +*.result.css +*.result.css.map +*.result.html diff --git a/plugins/postcss-logical-resize/.nvmrc b/plugins/postcss-logical-resize/.nvmrc new file mode 100644 index 000000000..39e593ebe --- /dev/null +++ b/plugins/postcss-logical-resize/.nvmrc @@ -0,0 +1 @@ +v18.8.0 diff --git a/plugins/postcss-logical-resize/.tape.mjs b/plugins/postcss-logical-resize/.tape.mjs new file mode 100644 index 000000000..49235294a --- /dev/null +++ b/plugins/postcss-logical-resize/.tape.mjs @@ -0,0 +1,44 @@ +import postcssTape from '../../packages/postcss-tape/dist/index.mjs'; +import plugin from '@csstools/postcss-logical-resize'; + +postcssTape(plugin)({ + 'basic': { + message: 'basic test with default setting', + }, + 'basic:rtl': { + message: 'basic test with rtl', + options: { + inlineDirection: 'right-to-left' + }, + }, + 'basic:bt': { + message: 'basic test with bt', + options: { + blockDirection: 'bottom-to-top' + }, + }, + 'basic:rtl-and-bt': { + message: 'basic test with rtl and bt', + options: { + blockDirection: 'bottom-to-top', + inlineDirection: 'right-to-left' + }, + }, + 'basic:chinese': { + message: 'basic test with rtl and bt', + options: { + blockDirection: 'right-to-left', + inlineDirection: 'top-to-bottom' + }, + }, + 'examples/example': { + message: 'minimal example', + }, + 'examples/example:chinese': { + message: 'minimal example', + options: { + blockDirection: 'right-to-left', + inlineDirection: 'top-to-bottom' + } + }, +}); diff --git a/plugins/postcss-logical-resize/CHANGELOG.md b/plugins/postcss-logical-resize/CHANGELOG.md new file mode 100644 index 000000000..eb2ba4759 --- /dev/null +++ b/plugins/postcss-logical-resize/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changes to PostCSS Logical Resize + +### 1.0.0 (January 21, 20223) + +- Initial version diff --git a/plugins/postcss-logical-resize/INSTALL.md b/plugins/postcss-logical-resize/INSTALL.md new file mode 100644 index 000000000..a6b00797e --- /dev/null +++ b/plugins/postcss-logical-resize/INSTALL.md @@ -0,0 +1,235 @@ +# Installing PostCSS Logical Resize + +[PostCSS Logical Resize] runs in all Node environments, with special instructions for: + +- [Node](#node) +- [PostCSS CLI](#postcss-cli) +- [PostCSS Load Config](#postcss-load-config) +- [Webpack](#webpack) +- [Next.js](#nextjs) +- [Gulp](#gulp) +- [Grunt](#grunt) + + + +## Node + +Add [PostCSS Logical Resize] to your project: + +```bash +npm install postcss @csstools/postcss-logical-resize --save-dev +``` + +Use it as a [PostCSS] plugin: + +```js +// commonjs +const postcss = require('postcss'); +const postcssLogicalResize = require('@csstools/postcss-logical-resize'); + +postcss([ + postcssLogicalResize(/* pluginOptions */) +]).process(YOUR_CSS /*, processOptions */); +``` + +```js +// esm +import postcss from 'postcss'; +import postcssLogicalResize from '@csstools/postcss-logical-resize'; + +postcss([ + postcssLogicalResize(/* pluginOptions */) +]).process(YOUR_CSS /*, processOptions */); +``` + +## PostCSS CLI + +Add [PostCSS CLI] to your project: + +```bash +npm install postcss-cli @csstools/postcss-logical-resize --save-dev +``` + +Use [PostCSS Logical Resize] in your `postcss.config.js` configuration file: + +```js +const postcssLogicalResize = require('@csstools/postcss-logical-resize'); + +module.exports = { + plugins: [ + postcssLogicalResize(/* pluginOptions */) + ] +} +``` + +## PostCSS Load Config + +If your framework/CLI supports [`postcss-load-config`](https://github.com/postcss/postcss-load-config). + +```bash +npm install @csstools/postcss-logical-resize --save-dev +``` + +`package.json`: + +```json +{ + "postcss": { + "plugins": { + "@csstools/postcss-logical-resize": {} + } + } +} +``` + +`.postcssrc.json`: + +```json +{ + "plugins": { + "@csstools/postcss-logical-resize": {} + } +} +``` + +_See the [README of `postcss-load-config`](https://github.com/postcss/postcss-load-config#usage) for more usage options._ + +## Webpack + +_Webpack version 5_ + +Add [PostCSS Loader] to your project: + +```bash +npm install postcss-loader @csstools/postcss-logical-resize --save-dev +``` + +Use [PostCSS Logical Resize] in your Webpack configuration: + +```js +module.exports = { + module: { + rules: [ + { + test: /\.css$/i, + use: [ + "style-loader", + { + loader: "css-loader", + options: { importLoaders: 1 }, + }, + { + loader: "postcss-loader", + options: { + postcssOptions: { + plugins: [ + // Other plugins, + [ + "@csstools/postcss-logical-resize", + { + // Options + }, + ], + ], + }, + }, + }, + ], + }, + ], + }, +}; +``` + +## Next.js + +Read the instructions on how to [customize the PostCSS configuration in Next.js](https://nextjs.org/docs/advanced-features/customizing-postcss-config) + +```bash +npm install @csstools/postcss-logical-resize --save-dev +``` + +Use [PostCSS Logical Resize] in your `postcss.config.json` file: + +```json +{ + "plugins": [ + "@csstools/postcss-logical-resize" + ] +} +``` + +```json5 +{ + "plugins": [ + [ + "@csstools/postcss-logical-resize", + { + // Optionally add plugin options + } + ] + ] +} +``` + +## Gulp + +Add [Gulp PostCSS] to your project: + +```bash +npm install gulp-postcss @csstools/postcss-logical-resize --save-dev +``` + +Use [PostCSS Logical Resize] in your Gulpfile: + +```js +const postcss = require('gulp-postcss'); +const postcssLogicalResize = require('@csstools/postcss-logical-resize'); + +gulp.task('css', function () { + var plugins = [ + postcssLogicalResize(/* pluginOptions */) + ]; + + return gulp.src('./src/*.css') + .pipe(postcss(plugins)) + .pipe(gulp.dest('.')); +}); +``` + +## Grunt + +Add [Grunt PostCSS] to your project: + +```bash +npm install grunt-postcss @csstools/postcss-logical-resize --save-dev +``` + +Use [PostCSS Logical Resize] in your Gruntfile: + +```js +const postcssLogicalResize = require('@csstools/postcss-logical-resize'); + +grunt.loadNpmTasks('grunt-postcss'); + +grunt.initConfig({ + postcss: { + options: { + processors: [ + postcssLogicalResize(/* pluginOptions */) + ] + }, + dist: { + src: '*.css' + } + } +}); +``` + +[Gulp PostCSS]: https://github.com/postcss/gulp-postcss +[Grunt PostCSS]: https://github.com/nDmitry/grunt-postcss +[PostCSS]: https://github.com/postcss/postcss +[PostCSS CLI]: https://github.com/postcss/postcss-cli +[PostCSS Loader]: https://github.com/postcss/postcss-loader +[PostCSS Logical Resize]: https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-logical-resize +[Next.js]: https://nextjs.org diff --git a/plugins/postcss-logical-resize/LICENSE.md b/plugins/postcss-logical-resize/LICENSE.md new file mode 100644 index 000000000..0bc1fa706 --- /dev/null +++ b/plugins/postcss-logical-resize/LICENSE.md @@ -0,0 +1,108 @@ +# CC0 1.0 Universal + +## Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an “owner”) of an original work of +authorship and/or a database (each, a “Work”). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific works +(“Commons”) that the public can reliably and without fear of later claims of +infringement build upon, modify, incorporate in other works, reuse and +redistribute as freely as possible in any form whatsoever and for any purposes, +including without limitation commercial purposes. These owners may contribute +to the Commons to promote the ideal of a free culture and the further +production of creative, cultural and scientific works, or to gain reputation or +greater distribution for their Work in part through the use and efforts of +others. + +For these and/or other purposes and motivations, and without any expectation of +additional consideration or compensation, the person associating CC0 with a +Work (the “Affirmer”), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and +publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be + protected by copyright and related or neighboring rights (“Copyright and + Related Rights”). Copyright and Related Rights include, but are not limited + to, the following: + 1. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + 2. moral rights retained by the original author(s) and/or performer(s); + 3. publicity and privacy rights pertaining to a person’s image or likeness + depicted in a Work; + 4. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(i), below; + 5. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + 6. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + 7. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations + thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, + applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and + unconditionally waives, abandons, and surrenders all of Affirmer’s Copyright + and Related Rights and associated claims and causes of action, whether now + known or unknown (including existing as well as future claims and causes of + action), in the Work (i) in all territories worldwide, (ii) for the maximum + duration provided by applicable law or treaty (including future time + extensions), (iii) in any current or future medium and for any number of + copies, and (iv) for any purpose whatsoever, including without limitation + commercial, advertising or promotional purposes (the “Waiver”). Affirmer + makes the Waiver for the benefit of each member of the public at large and + to the detriment of Affirmer’s heirs and successors, fully intending that + such Waiver shall not be subject to revocation, rescission, cancellation, + termination, or any other legal or equitable action to disrupt the quiet + enjoyment of the Work by the public as contemplated by Affirmer’s express + Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be + judged legally invalid or ineffective under applicable law, then the Waiver + shall be preserved to the maximum extent permitted taking into account + Affirmer’s express Statement of Purpose. In addition, to the extent the + Waiver is so judged Affirmer hereby grants to each affected person a + royalty-free, non transferable, non sublicensable, non exclusive, + irrevocable and unconditional license to exercise Affirmer’s Copyright and + Related Rights in the Work (i) in all territories worldwide, (ii) for the + maximum duration provided by applicable law or treaty (including future time + extensions), (iii) in any current or future medium and for any number of + copies, and (iv) for any purpose whatsoever, including without limitation + commercial, advertising or promotional purposes (the “License”). The License + shall be deemed effective as of the date CC0 was applied by Affirmer to the + Work. Should any part of the License for any reason be judged legally + invalid or ineffective under applicable law, such partial invalidity or + ineffectiveness shall not invalidate the remainder of the License, and in + such case Affirmer hereby affirms that he or she will not (i) exercise any + of his or her remaining Copyright and Related Rights in the Work or (ii) + assert any associated claims and causes of action with respect to the Work, + in either case contrary to Affirmer’s express Statement of Purpose. + +4. Limitations and Disclaimers. + 1. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + 2. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or + otherwise, including without limitation warranties of title, + merchantability, fitness for a particular purpose, non infringement, or + the absence of latent or other defects, accuracy, or the present or + absence of errors, whether or not discoverable, all to the greatest + extent permissible under applicable law. + 3. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person’s Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the Work. + 4. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see +http://creativecommons.org/publicdomain/zero/1.0/. diff --git a/plugins/postcss-logical-resize/README.md b/plugins/postcss-logical-resize/README.md new file mode 100644 index 000000000..3e0d3a242 --- /dev/null +++ b/plugins/postcss-logical-resize/README.md @@ -0,0 +1,108 @@ +# PostCSS Logical Resize [PostCSS Logo][PostCSS] + +[npm version][npm-url] [CSS Standard Status][css-url] [Build Status][cli-url] [Discord][discord] + +[PostCSS Logical Resize] lets you use logical, rather than physical, values for `resize`, following the [CSS Logical Properties and Values] specification. + +```pcss +.resize-block { + resize: block; +} + +.resize-inline { + resize: inline; +} + +/* becomes */ + +.resize-block { + resize: vertical; +} + +.resize-inline { + resize: horizontal; +} +``` + +## Usage + +Add [PostCSS Logical Resize] to your project: + +```bash +npm install postcss @csstools/postcss-logical-resize --save-dev +``` + +Use it as a [PostCSS] plugin: + +```js +const postcss = require('postcss'); +const postcssLogicalResize = require('@csstools/postcss-logical-resize'); + +postcss([ + postcssLogicalResize(/* pluginOptions */) +]).process(YOUR_CSS /*, processOptions */); +``` + +[PostCSS Logical Resize] runs in all Node environments, with special +instructions for: + +- [Node](INSTALL.md#node) +- [PostCSS CLI](INSTALL.md#postcss-cli) +- [PostCSS Load Config](INSTALL.md#postcss-load-config) +- [Webpack](INSTALL.md#webpack) +- [Next.js](INSTALL.md#nextjs) +- [Gulp](INSTALL.md#gulp) +- [Grunt](INSTALL.md#grunt) + +## Options + +### blockDirection & inlineDirection + +The `blockDirection` and `inlineDirection` options allow you to specify the direction of the block and inline axes. The default values are `top-to-bottom` and `left-to-right` respectively which would match any latin language. + +You might want to tweak these values if you are using a different writing system, such as Arabic, Hebrew or Chinese for example. + +```js +postcssLogicalResize({ + blockDirection: 'right-to-left', + inlineDirection: 'top-to-bottom' +}) +``` + +```pcss +.resize-block { + resize: block; +} + +.resize-inline { + resize: inline; +} + +/* becomes */ + +.resize-block { + resize: horizontal; +} + +.resize-inline { + resize: vertical; +} +``` + +Each direction must be one of the following: + +- `top-to-bottom` +- `bottom-to-top` +- `left-to-right` +- `right-to-left` + +You can't mix two vertical directions or two horizontal directions so for example `top-to-bottom` and `right-to-left` are valid, but `top-to-bottom` and `bottom-to-top` are not. + +[cli-url]: https://github.com/csstools/postcss-plugins/actions/workflows/test.yml?query=workflow/test +[css-url]: https://cssdb.org/#logical-resize +[discord]: https://discord.gg/bUadyRwkJS +[npm-url]: https://www.npmjs.com/package/@csstools/postcss-logical-resize + +[PostCSS]: https://github.com/postcss/postcss +[PostCSS Logical Resize]: https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-logical-resize +[CSS Logical Properties and Values]: https://www.w3.org/TR/css-logical-1/ diff --git a/plugins/postcss-logical-resize/dist/index.cjs b/plugins/postcss-logical-resize/dist/index.cjs new file mode 100644 index 000000000..6c1aaad14 --- /dev/null +++ b/plugins/postcss-logical-resize/dist/index.cjs @@ -0,0 +1 @@ +"use strict";var o,t,e,i,n=require("postcss-value-parser");function cloneDeclaration(o,t,e){o.parent&&o.parent.some((o=>"decl"==o.type&&o.prop===e&&o.value===t))||o.cloneBefore({value:t,prop:e})}function transformResize(o){return t=>{const{prop:e,value:i}=t,r=n(i),c=o.inlineIsHorizontal?"horizontal":"vertical",s=o.inlineIsHorizontal?"vertical":"horizontal";r.nodes.forEach((o=>{if("word"===o.type){const t=o.value.toLowerCase();if("inline"===t)return void(o.value=c);"block"===t&&(o.value=s)}}));const l=r.toString();return l!==i&&(cloneDeclaration(t,l,e),!0)}}function directionFlowToAxes(o){switch(o){case e.TopToBottom:return[i.Top,i.Bottom];case e.BottomToTop:return[i.Bottom,i.Top];case e.RightToLeft:return[i.Right,i.Left];case e.LeftToRight:return[i.Left,i.Right]}}!function(o){o.Block="block",o.Inline="inline"}(o||(o={})),function(o){o.Start="start",o.End="end"}(t||(t={})),function(o){o.TopToBottom="top-to-bottom",o.BottomToTop="bottom-to-top",o.RightToLeft="right-to-left",o.LeftToRight="left-to-right"}(e||(e={})),function(o){o.Top="top",o.Right="right",o.Bottom="bottom",o.Left="left"}(i||(i={}));const creator=o=>{const t=Object.assign({blockDirection:e.TopToBottom,inlineDirection:e.LeftToRight},o),n=Object.values(e);if(!n.includes(t.blockDirection))throw new Error(`[postcss-logical-resize] "blockDirection" must be one of ${n.join(", ")}`);if(!n.includes(t.inlineDirection))throw new Error(`[postcss-logical-resize] "inlineDirection" must be one of ${n.join(", ")}`);const[r,c]=directionFlowToAxes(t.blockDirection),[s,l]=directionFlowToAxes(t.inlineDirection);if(!Object.values(i).every((o=>[r,c,s,l].includes(o))))throw new Error('[postcss-logical-resize] "blockDirection" and "inlineDirection" must be on separate axes');const a={block:[r,c],inline:[s,l],inlineIsHorizontal:[e.LeftToRight,e.RightToLeft].includes(t.inlineDirection)};return{postcssPlugin:"postcss-logical-resize",Declaration:{resize:(u=transformResize(a),(o,{result:t})=>{if(!u)return;let e=!1;try{e=u(o)}catch(e){return void o.warn(t,e.message)}e&&o.remove()})}};var u};creator.postcss=!0,module.exports=creator; diff --git a/plugins/postcss-logical-resize/dist/index.d.ts b/plugins/postcss-logical-resize/dist/index.d.ts new file mode 100644 index 000000000..0cac31d03 --- /dev/null +++ b/plugins/postcss-logical-resize/dist/index.d.ts @@ -0,0 +1,11 @@ +import type { PluginCreator } from 'postcss'; +import { DirectionFlow } from './lib/types'; +/** postcss-logical-resize plugin options */ +export type pluginOptions = { + /** Sets the direction for block. default: top-to-bottom */ + blockDirection?: DirectionFlow; + /** Sets the direction for inline. default: left-to-right */ + inlineDirection?: DirectionFlow; +}; +declare const creator: PluginCreator; +export default creator; diff --git a/plugins/postcss-logical-resize/dist/index.mjs b/plugins/postcss-logical-resize/dist/index.mjs new file mode 100644 index 000000000..5cffc5e7b --- /dev/null +++ b/plugins/postcss-logical-resize/dist/index.mjs @@ -0,0 +1 @@ +import o from"postcss-value-parser";var t,e,i,n;function cloneDeclaration(o,t,e){o.parent&&o.parent.some((o=>"decl"==o.type&&o.prop===e&&o.value===t))||o.cloneBefore({value:t,prop:e})}function transformResize(t){return e=>{const{prop:i,value:n}=e,r=o(n),c=t.inlineIsHorizontal?"horizontal":"vertical",s=t.inlineIsHorizontal?"vertical":"horizontal";r.nodes.forEach((o=>{if("word"===o.type){const t=o.value.toLowerCase();if("inline"===t)return void(o.value=c);"block"===t&&(o.value=s)}}));const l=r.toString();return l!==n&&(cloneDeclaration(e,l,i),!0)}}function directionFlowToAxes(o){switch(o){case i.TopToBottom:return[n.Top,n.Bottom];case i.BottomToTop:return[n.Bottom,n.Top];case i.RightToLeft:return[n.Right,n.Left];case i.LeftToRight:return[n.Left,n.Right]}}!function(o){o.Block="block",o.Inline="inline"}(t||(t={})),function(o){o.Start="start",o.End="end"}(e||(e={})),function(o){o.TopToBottom="top-to-bottom",o.BottomToTop="bottom-to-top",o.RightToLeft="right-to-left",o.LeftToRight="left-to-right"}(i||(i={})),function(o){o.Top="top",o.Right="right",o.Bottom="bottom",o.Left="left"}(n||(n={}));const creator=o=>{const t=Object.assign({blockDirection:i.TopToBottom,inlineDirection:i.LeftToRight},o),e=Object.values(i);if(!e.includes(t.blockDirection))throw new Error(`[postcss-logical-resize] "blockDirection" must be one of ${e.join(", ")}`);if(!e.includes(t.inlineDirection))throw new Error(`[postcss-logical-resize] "inlineDirection" must be one of ${e.join(", ")}`);const[r,c]=directionFlowToAxes(t.blockDirection),[s,l]=directionFlowToAxes(t.inlineDirection);if(!Object.values(n).every((o=>[r,c,s,l].includes(o))))throw new Error('[postcss-logical-resize] "blockDirection" and "inlineDirection" must be on separate axes');const a={block:[r,c],inline:[s,l],inlineIsHorizontal:[i.LeftToRight,i.RightToLeft].includes(t.inlineDirection)};return{postcssPlugin:"postcss-logical-resize",Declaration:{resize:(u=transformResize(a),(o,{result:t})=>{if(!u)return;let e=!1;try{e=u(o)}catch(e){return void o.warn(t,e.message)}e&&o.remove()})}};var u};creator.postcss=!0;export{creator as default}; diff --git a/plugins/postcss-logical-resize/dist/lib/clone-declaration.d.ts b/plugins/postcss-logical-resize/dist/lib/clone-declaration.d.ts new file mode 100644 index 000000000..1503bf6f1 --- /dev/null +++ b/plugins/postcss-logical-resize/dist/lib/clone-declaration.d.ts @@ -0,0 +1,2 @@ +import type { Declaration } from 'postcss'; +export declare function cloneDeclaration(declaration: Declaration, value: string, prop: string): void; diff --git a/plugins/postcss-logical-resize/dist/lib/transform-resize.d.ts b/plugins/postcss-logical-resize/dist/lib/transform-resize.d.ts new file mode 100644 index 000000000..12100551c --- /dev/null +++ b/plugins/postcss-logical-resize/dist/lib/transform-resize.d.ts @@ -0,0 +1,3 @@ +import type { Declaration } from 'postcss'; +import { DirectionConfig } from './types'; +export declare function transformResize(directionConfig: DirectionConfig): (declaration: Declaration) => boolean; diff --git a/plugins/postcss-logical-resize/dist/lib/types.d.ts b/plugins/postcss-logical-resize/dist/lib/types.d.ts new file mode 100644 index 000000000..7f27fd46e --- /dev/null +++ b/plugins/postcss-logical-resize/dist/lib/types.d.ts @@ -0,0 +1,31 @@ +export declare enum Direction { + Block = "block", + Inline = "inline" +} +export declare enum DirectionValue { + Start = "start", + End = "end" +} +export declare const DirectionValues: { + BlockStart: string; + BlockEnd: string; + InlineStart: string; + InlineEnd: string; +}; +export declare enum DirectionFlow { + TopToBottom = "top-to-bottom", + BottomToTop = "bottom-to-top", + RightToLeft = "right-to-left", + LeftToRight = "left-to-right" +} +export declare enum Axes { + Top = "top", + Right = "right", + Bottom = "bottom", + Left = "left" +} +export type DirectionConfig = { + [Direction.Block]: [Axes, Axes]; + [Direction.Inline]: [Axes, Axes]; + inlineIsHorizontal: boolean; +}; diff --git a/plugins/postcss-logical-resize/dist/utils/direction-flow-to-axes.d.ts b/plugins/postcss-logical-resize/dist/utils/direction-flow-to-axes.d.ts new file mode 100644 index 000000000..2652d71d8 --- /dev/null +++ b/plugins/postcss-logical-resize/dist/utils/direction-flow-to-axes.d.ts @@ -0,0 +1,2 @@ +import { DirectionFlow, Axes } from '../lib/types'; +export declare function directionFlowToAxes(directionFlow: DirectionFlow): [Axes, Axes]; diff --git a/plugins/postcss-logical-resize/docs/README.md b/plugins/postcss-logical-resize/docs/README.md new file mode 100644 index 000000000..cb707a19d --- /dev/null +++ b/plugins/postcss-logical-resize/docs/README.md @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + +
+ +[] lets you use logical, rather than physical, values for `resize`, following the [CSS Logical Properties and Values] specification. + +```pcss + + +/* becomes */ + + +``` + + + + + +## Options + +### blockDirection & inlineDirection + +The `blockDirection` and `inlineDirection` options allow you to specify the direction of the block and inline axes. The default values are `top-to-bottom` and `left-to-right` respectively which would match any latin language. + +You might want to tweak these values if you are using a different writing system, such as Arabic, Hebrew or Chinese for example. + +```js +({ + blockDirection: 'right-to-left', + inlineDirection: 'top-to-bottom' +}) +``` + +```pcss + + +/* becomes */ + + +``` + +Each direction must be one of the following: + +- `top-to-bottom` +- `bottom-to-top` +- `left-to-right` +- `right-to-left` + +You can't mix two vertical directions or two horizontal directions so for example `top-to-bottom` and `right-to-left` are valid, but `top-to-bottom` and `bottom-to-top` are not. + + +[CSS Logical Properties and Values]: diff --git a/plugins/postcss-logical-resize/package.json b/plugins/postcss-logical-resize/package.json new file mode 100644 index 000000000..aa4b46051 --- /dev/null +++ b/plugins/postcss-logical-resize/package.json @@ -0,0 +1,84 @@ +{ + "name": "@csstools/postcss-logical-resize", + "description": "Use logical values in the resize property", + "version": "1.0.0", + "contributors": [ + { + "name": "Antonio Laguna", + "email": "antonio@laguna.es", + "url": "https://antonio.laguna.es" + }, + { + "name": "Romain Menke", + "email": "romainmenke@gmail.com" + } + ], + "license": "CC0-1.0", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "main": "dist/index.cjs", + "module": "dist/index.mjs", + "types": "dist/index.d.ts", + "exports": { + ".": { + "import": "./dist/index.mjs", + "require": "./dist/index.cjs", + "default": "./dist/index.mjs" + } + }, + "files": [ + "CHANGELOG.md", + "LICENSE.md", + "README.md", + "dist" + ], + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "peerDependencies": { + "postcss": "^8.4" + }, + "scripts": { + "prebuild": "npm run clean", + "build": "rollup -c ../../rollup/default.mjs", + "clean": "node -e \"fs.rmSync('./dist', { recursive: true, force: true }); fs.mkdirSync('./dist');\"", + "docs": "node ../../.github/bin/generate-docs/install.mjs && node ../../.github/bin/generate-docs/readme.mjs", + "lint": "npm run lint:eslint && npm run lint:package-json", + "lint:eslint": "eslint ./src --ext .js --ext .ts --ext .mjs --no-error-on-unmatched-pattern", + "lint:package-json": "node ../../.github/bin/format-package-json.mjs", + "prepublishOnly": "npm run clean && npm run build && npm run test", + "test": "node .tape.mjs && npm run test:exports", + "test:exports": "node ./test/_import.mjs && node ./test/_require.cjs", + "test:rewrite-expects": "REWRITE_EXPECTS=true node .tape.mjs" + }, + "homepage": "https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-logical-resize#readme", + "repository": { + "type": "git", + "url": "https://github.com/csstools/postcss-plugins.git", + "directory": "plugins/postcss-logical-resize" + }, + "bugs": "https://github.com/csstools/postcss-plugins/issues", + "keywords": [ + "block", + "css", + "inline", + "logical", + "postcss", + "postcss-plugin", + "resize" + ], + "csstools": { + "cssdbId": "logical-resize", + "exportName": "postcssLogicalResize", + "humanReadableName": "PostCSS Logical Resize", + "specUrl": "https://www.w3.org/TR/css-logical-1/" + }, + "volta": { + "extends": "../../package.json" + } +} diff --git a/plugins/postcss-logical-resize/src/index.ts b/plugins/postcss-logical-resize/src/index.ts new file mode 100644 index 000000000..2dc3a551b --- /dev/null +++ b/plugins/postcss-logical-resize/src/index.ts @@ -0,0 +1,86 @@ +import type { Declaration, PluginCreator, Result } from 'postcss'; +import { Axes, DirectionConfig, DirectionFlow } from './lib/types'; +import { transformResize } from './lib/transform-resize'; +import { directionFlowToAxes } from './utils/direction-flow-to-axes'; + +/** postcss-logical-resize plugin options */ +export type pluginOptions = { + /** Sets the direction for block. default: top-to-bottom */ + blockDirection?: DirectionFlow, + /** Sets the direction for inline. default: left-to-right */ + inlineDirection?: DirectionFlow, +}; + +const creator: PluginCreator = (opts?: pluginOptions) => { + const options = Object.assign( + // Default options + { + blockDirection: DirectionFlow.TopToBottom, + inlineDirection: DirectionFlow.LeftToRight, + }, + // Provided options + opts, + ); + const directionValues = Object.values(DirectionFlow); + + if (!directionValues.includes(options.blockDirection)) { + throw new Error(`[postcss-logical-resize] "blockDirection" must be one of ${directionValues.join(', ')}`); + } + + if (!directionValues.includes(options.inlineDirection)) { + throw new Error(`[postcss-logical-resize] "inlineDirection" must be one of ${directionValues.join(', ')}`); + } + + const [blockStart, blockEnd] = directionFlowToAxes(options.blockDirection); + const [inlineStart, inlineEnd] = directionFlowToAxes(options.inlineDirection); + const allAxesCovered = Object.values(Axes) + .every((axis) => [blockStart, blockEnd, inlineStart, inlineEnd].includes(axis)); + + if (!allAxesCovered) { + throw new Error('[postcss-logical-resize] "blockDirection" and "inlineDirection" must be on separate axes'); + } + + const directionConfig: DirectionConfig = { + block: [blockStart, blockEnd], + inline: [inlineStart, inlineEnd], + inlineIsHorizontal: [DirectionFlow.LeftToRight, DirectionFlow.RightToLeft].includes(options.inlineDirection), + }; + + const makeTransform = (transform: (decl: Declaration) => boolean | null) => { + return ( + decl: Declaration, + { result }: { result: Result }, + ) => { + if (!transform) { + return; + } + + let transformed = false; + + try { + transformed = transform(decl); + } catch (error) { + decl.warn(result, error.message); + return; + } + + if (!transformed) { + return; + } + + decl.remove(); + }; + }; + + return { + postcssPlugin: 'postcss-logical-resize', + Declaration: { + // 2.4 Resize + 'resize': makeTransform(transformResize(directionConfig)), + }, + }; +}; + +creator.postcss = true; + +export default creator; diff --git a/plugins/postcss-logical-resize/src/lib/clone-declaration.ts b/plugins/postcss-logical-resize/src/lib/clone-declaration.ts new file mode 100644 index 000000000..b738ea4a9 --- /dev/null +++ b/plugins/postcss-logical-resize/src/lib/clone-declaration.ts @@ -0,0 +1,15 @@ +import type { Declaration } from 'postcss'; + +export function cloneDeclaration( + declaration: Declaration, + value: string, + prop: string, +): void { + if (declaration.parent && declaration.parent.some((x) => { + return x.type == 'decl' && x.prop === prop && x.value === value; + })) { + return; + } + + declaration.cloneBefore({ value, prop }); +} diff --git a/plugins/postcss-logical-resize/src/lib/transform-resize.ts b/plugins/postcss-logical-resize/src/lib/transform-resize.ts new file mode 100644 index 000000000..1f2c99b03 --- /dev/null +++ b/plugins/postcss-logical-resize/src/lib/transform-resize.ts @@ -0,0 +1,38 @@ +import type { Declaration } from 'postcss'; +import valueParser from 'postcss-value-parser'; +import { DirectionConfig } from './types'; +import { cloneDeclaration } from './clone-declaration'; + +export function transformResize( + directionConfig: DirectionConfig, +): (declaration: Declaration) => boolean { + return (declaration: Declaration) => { + const { prop, value } = declaration; + const valueAST = valueParser(value); + const inlineValue = directionConfig.inlineIsHorizontal ? 'horizontal' : 'vertical'; + const blockValue = directionConfig.inlineIsHorizontal ? 'vertical' : 'horizontal'; + + valueAST.nodes.forEach((node) => { + if (node.type === 'word') { + const valueCandidate = node.value.toLowerCase(); + + if (valueCandidate === 'inline') { + node.value = inlineValue; + return; + } + + if (valueCandidate === 'block') { + node.value = blockValue; + } + } + }); + + const modifiedValued = valueAST.toString(); + if (modifiedValued !== value) { + cloneDeclaration(declaration, modifiedValued, prop); + return true; + } + + return false; + }; +} diff --git a/plugins/postcss-logical-resize/src/lib/types.ts b/plugins/postcss-logical-resize/src/lib/types.ts new file mode 100644 index 000000000..23dadd9d6 --- /dev/null +++ b/plugins/postcss-logical-resize/src/lib/types.ts @@ -0,0 +1,36 @@ +export enum Direction { + Block = 'block', + Inline = 'inline', +} + +export enum DirectionValue { + Start = 'start', + End = 'end', +} + +export const DirectionValues = { + BlockStart: 'block-start', + BlockEnd: 'block-end', + InlineStart: 'inline-start', + InlineEnd: 'inline-end', +}; + +export enum DirectionFlow { + TopToBottom = 'top-to-bottom', + BottomToTop = 'bottom-to-top', + RightToLeft = 'right-to-left', + LeftToRight = 'left-to-right', +} + +export enum Axes { + Top = 'top', + Right = 'right', + Bottom = 'bottom', + Left = 'left', +} + +export type DirectionConfig = { + [Direction.Block]: [Axes, Axes]; + [Direction.Inline]: [Axes, Axes]; + inlineIsHorizontal: boolean; +}; diff --git a/plugins/postcss-logical-resize/src/utils/direction-flow-to-axes.ts b/plugins/postcss-logical-resize/src/utils/direction-flow-to-axes.ts new file mode 100644 index 000000000..627a44479 --- /dev/null +++ b/plugins/postcss-logical-resize/src/utils/direction-flow-to-axes.ts @@ -0,0 +1,17 @@ +import { DirectionFlow, Axes } from '../lib/types'; + +export function directionFlowToAxes(directionFlow: DirectionFlow): [Axes, Axes] { + switch (directionFlow) { + case DirectionFlow.TopToBottom: + return [Axes.Top, Axes.Bottom]; + + case DirectionFlow.BottomToTop: + return [Axes.Bottom, Axes.Top]; + + case DirectionFlow.RightToLeft: + return [Axes.Right, Axes.Left]; + + case DirectionFlow.LeftToRight: + return [Axes.Left, Axes.Right]; + } +} diff --git a/plugins/postcss-logical-resize/test/_import.mjs b/plugins/postcss-logical-resize/test/_import.mjs new file mode 100644 index 000000000..cd29efc0e --- /dev/null +++ b/plugins/postcss-logical-resize/test/_import.mjs @@ -0,0 +1,6 @@ +import assert from 'assert'; +import plugin from '@csstools/postcss-logical-resize'; +plugin(); + +assert.ok(plugin.postcss, 'should have "postcss flag"'); +assert.equal(typeof plugin, 'function', 'should return a function'); diff --git a/plugins/postcss-logical-resize/test/_require.cjs b/plugins/postcss-logical-resize/test/_require.cjs new file mode 100644 index 000000000..62e615f85 --- /dev/null +++ b/plugins/postcss-logical-resize/test/_require.cjs @@ -0,0 +1,6 @@ +const assert = require('assert'); +const plugin = require('@csstools/postcss-logical-resize'); +plugin(); + +assert.ok(plugin.postcss, 'should have "postcss flag"'); +assert.equal(typeof plugin, 'function', 'should return a function'); diff --git a/plugins/postcss-logical/test/resize.expect.css b/plugins/postcss-logical-resize/test/basic.bt.expect.css similarity index 53% rename from plugins/postcss-logical/test/resize.expect.css rename to plugins/postcss-logical-resize/test/basic.bt.expect.css index d9cf49b72..923184399 100644 --- a/plugins/postcss-logical/test/resize.expect.css +++ b/plugins/postcss-logical-resize/test/basic.bt.expect.css @@ -1,4 +1,7 @@ -test-resize { +.resize-block { resize: vertical; +} + +.resize-inline { resize: horizontal; } diff --git a/plugins/postcss-logical-resize/test/basic.chinese.expect.css b/plugins/postcss-logical-resize/test/basic.chinese.expect.css new file mode 100644 index 000000000..b0ea8839b --- /dev/null +++ b/plugins/postcss-logical-resize/test/basic.chinese.expect.css @@ -0,0 +1,7 @@ +.resize-block { + resize: horizontal; +} + +.resize-inline { + resize: vertical; +} diff --git a/plugins/postcss-logical-resize/test/basic.css b/plugins/postcss-logical-resize/test/basic.css new file mode 100644 index 000000000..23695ee66 --- /dev/null +++ b/plugins/postcss-logical-resize/test/basic.css @@ -0,0 +1,7 @@ +.resize-block { + resize: block; +} + +.resize-inline { + resize: inline; +} diff --git a/plugins/postcss-logical-resize/test/basic.expect.css b/plugins/postcss-logical-resize/test/basic.expect.css new file mode 100644 index 000000000..923184399 --- /dev/null +++ b/plugins/postcss-logical-resize/test/basic.expect.css @@ -0,0 +1,7 @@ +.resize-block { + resize: vertical; +} + +.resize-inline { + resize: horizontal; +} diff --git a/plugins/postcss-logical-resize/test/basic.rtl-and-bt.expect.css b/plugins/postcss-logical-resize/test/basic.rtl-and-bt.expect.css new file mode 100644 index 000000000..923184399 --- /dev/null +++ b/plugins/postcss-logical-resize/test/basic.rtl-and-bt.expect.css @@ -0,0 +1,7 @@ +.resize-block { + resize: vertical; +} + +.resize-inline { + resize: horizontal; +} diff --git a/plugins/postcss-logical-resize/test/basic.rtl.expect.css b/plugins/postcss-logical-resize/test/basic.rtl.expect.css new file mode 100644 index 000000000..923184399 --- /dev/null +++ b/plugins/postcss-logical-resize/test/basic.rtl.expect.css @@ -0,0 +1,7 @@ +.resize-block { + resize: vertical; +} + +.resize-inline { + resize: horizontal; +} diff --git a/plugins/postcss-logical-resize/test/examples/example.chinese.expect.css b/plugins/postcss-logical-resize/test/examples/example.chinese.expect.css new file mode 100644 index 000000000..b0ea8839b --- /dev/null +++ b/plugins/postcss-logical-resize/test/examples/example.chinese.expect.css @@ -0,0 +1,7 @@ +.resize-block { + resize: horizontal; +} + +.resize-inline { + resize: vertical; +} diff --git a/plugins/postcss-logical-resize/test/examples/example.css b/plugins/postcss-logical-resize/test/examples/example.css new file mode 100644 index 000000000..23695ee66 --- /dev/null +++ b/plugins/postcss-logical-resize/test/examples/example.css @@ -0,0 +1,7 @@ +.resize-block { + resize: block; +} + +.resize-inline { + resize: inline; +} diff --git a/plugins/postcss-logical-resize/test/examples/example.expect.css b/plugins/postcss-logical-resize/test/examples/example.expect.css new file mode 100644 index 000000000..923184399 --- /dev/null +++ b/plugins/postcss-logical-resize/test/examples/example.expect.css @@ -0,0 +1,7 @@ +.resize-block { + resize: vertical; +} + +.resize-inline { + resize: horizontal; +} diff --git a/plugins/postcss-logical-resize/tsconfig.json b/plugins/postcss-logical-resize/tsconfig.json new file mode 100644 index 000000000..e0d06239c --- /dev/null +++ b/plugins/postcss-logical-resize/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "declarationDir": "." + }, + "include": ["./src/**/*"], + "exclude": ["dist"], +} diff --git a/plugins/postcss-logical-viewport-units/package.json b/plugins/postcss-logical-viewport-units/package.json index b3bcb8c90..83bb81fe8 100644 --- a/plugins/postcss-logical-viewport-units/package.json +++ b/plugins/postcss-logical-viewport-units/package.json @@ -64,7 +64,14 @@ }, "bugs": "https://github.com/csstools/postcss-plugins/issues", "keywords": [ - "postcss-plugin" + "block", + "css", + "inline", + "logical", + "padding", + "postcss", + "postcss-plugin", + "viewport units" ], "csstools": { "cssdbId": "logical-viewport-units", diff --git a/plugins/postcss-logical/.gitignore b/plugins/postcss-logical/.gitignore index 801908343..e5b28db4a 100644 --- a/plugins/postcss-logical/.gitignore +++ b/plugins/postcss-logical/.gitignore @@ -1,13 +1,6 @@ node_modules package-lock.json yarn.lock -*.log* *.result.css *.result.css.map *.result.html -!.editorconfig -!.gitignore -!.rollup.js -!.tape.js -!.travis.yml -!.github diff --git a/plugins/postcss-logical/.tape.mjs b/plugins/postcss-logical/.tape.mjs index 321ec02e8..a7628f499 100644 --- a/plugins/postcss-logical/.tape.mjs +++ b/plugins/postcss-logical/.tape.mjs @@ -2,113 +2,127 @@ import postcssTape from '../../packages/postcss-tape/dist/index.mjs'; import plugin from 'postcss-logical'; postcssTape(plugin)({ - 'border': { - message: 'supports logical "border" property values' + 'abstract': { + message: 'abstract test with default setting', }, - 'border:ltr': { - message: 'supports logical "border" property values with { dir: "ltr" }', + 'abstract:rtl': { + message: 'abstract test with rtl', options: { - dir: 'ltr' - } + inlineDirection: 'right-to-left' + }, }, - 'border:preserve': { - message: 'supports logical "border" property values with { preserve: true }', + 'abstract:bt': { + message: 'abstract test with bt', options: { - preserve: true - } + blockDirection: 'bottom-to-top' + }, }, - 'clear': { - message: 'supports logical "clear" property values' + 'abstract:rtl-and-bt': { + message: 'abstract test with rtl and bt', + options: { + blockDirection: 'bottom-to-top', + inlineDirection: 'right-to-left' + }, }, - 'clear:ltr': { - message: 'supports logical "clear" property values with { dir: "ltr" }', + 'abstract:chinese': { + message: 'abstract test with rtl and bt', options: { - dir: 'ltr' - } + blockDirection: 'right-to-left', + inlineDirection: 'top-to-bottom' + }, }, - 'float': { - message: 'supports logical "float" property values' + 'caption-side': { + message: 'supports logical "caption-side" properties', }, - 'float:ltr': { - message: 'supports logical "float" property values with { dir: "ltr" }', + 'caption-side:chinese': { + message: 'supports logical "caption-side" properties { blockDirection: "right-to-left", inlineDirection: "top-to-bottom" }', options: { - dir: 'ltr' - } + blockDirection: 'right-to-left', + inlineDirection: 'top-to-bottom' + }, }, - 'inset': { - message: 'supports logical "inset" properties' + 'text-align': { + message: 'supports logical "text-align" property', }, - 'inset:ltr': { - message: 'supports logical "inset" properties with { dir: "ltr" }', + 'text-align:chinese': { + message: 'supports logical "text-align" property { blockDirection: "right-to-left", inlineDirection: "top-to-bottom" }', options: { - dir: 'ltr' - } + blockDirection: 'right-to-left', + inlineDirection: 'top-to-bottom' + }, }, - 'margin': { - message: 'supports logical "margin" properties' - }, - 'margin:ltr': { - message: 'supports logical "margin" properties with { dir: "ltr" }', + 'text-align:hebrew': { + message: 'supports logical "text-align" property { inlineDirection: "right-to-left" }', options: { - dir: 'ltr' + inlineDirection: 'right-to-left', } }, - 'padding': { - message: 'supports logical "padding" properties' + 'logical-size': { + message: 'supports logical "block-size" & "inline-size" properties', }, - 'padding:ltr': { - message: 'supports logical "padding" properties with { dir: "ltr" }', + 'logical-size:chinese': { + message: 'supports logical "block-size" & "inline-size" properties { blockDirection: "right-to-left", inlineDirection: "top-to-bottom" }', options: { - dir: 'ltr' - } + blockDirection: 'right-to-left', + inlineDirection: 'top-to-bottom' + }, }, - 'resize': { - message: 'supports logical "resize" properties' + margin: { + message: 'supports logical "margin" properties', + warnings: 1, }, - 'size': { - message: 'supports logical "size" properties' - }, - 'size:preserve': { - message: 'supports logical "size" properties with { preserve: true }', + 'margin:chinese': { + message: 'supports logical "margin" properties { blockDirection: "right-to-left", inlineDirection: "top-to-bottom" }', + warnings: 1, options: { - preserve: true - } + blockDirection: 'right-to-left', + inlineDirection: 'top-to-bottom' + }, }, - 'text-align': { - message: 'supports logical "text-align" properties' + offsets: { + message: 'supports logical "offsets" properties', + warnings: 3, }, - 'text-align:ltr': { - message: 'supports logical "text-align" properties with { dir: "ltr" }', + 'offsets:chinese': { + message: 'supports logical "offsets" properties { blockDirection: "right-to-left", inlineDirection: "top-to-bottom" }', + warnings: 3, options: { - dir: 'ltr' - } + blockDirection: 'right-to-left', + inlineDirection: 'top-to-bottom' + }, }, - 'transition': { - message: 'supports logical "transition" properties' + padding: { + message: 'supports logical "padding" properties', + warnings: 1, }, - 'transition:ltr': { - message: 'supports logical "transition" properties with { dir: "ltr" }', + 'padding:chinese': { + message: 'supports logical "padding" properties { blockDirection: "right-to-left", inlineDirection: "top-to-bottom" }', + warnings: 1, options: { - dir: 'ltr' - } + blockDirection: 'right-to-left', + inlineDirection: 'top-to-bottom' + }, }, - 'transition:preserve:ltr': { - message: 'supports logical "transition" properties with { dir: "ltr", preserve: true }', - options: { - dir: 'ltr', - preserve: true - } + border: { + message: 'supports logical "border" properties', + warnings: 6, }, - 'generated-declaration-cases': { - message: 'correctly handles generated cases', + 'border:chinese': { + message: 'supports logical "border" properties { blockDirection: "right-to-left", inlineDirection: "top-to-bottom" }', + warnings: 6, options: { - preserve: false - } + blockDirection: 'right-to-left', + inlineDirection: 'top-to-bottom' + }, + }, + 'examples/example': { + message: 'minimal example', }, - 'generated-declaration-cases:preserve': { - message: 'correctly handles generated cases', + 'examples/example:chinese': { + message: 'minimal example', options: { - preserve: true + blockDirection: 'right-to-left', + inlineDirection: 'top-to-bottom' } }, }); diff --git a/plugins/postcss-logical/CHANGELOG.md b/plugins/postcss-logical/CHANGELOG.md index 61fb26d3e..6c10d130a 100644 --- a/plugins/postcss-logical/CHANGELOG.md +++ b/plugins/postcss-logical/CHANGELOG.md @@ -3,6 +3,12 @@ ### Unreleased (major) - Updated: Support for Node v14+ (major). +- Added: TypeScript support. +- Added: Support for `block-size`, `inline-size` and `caption-side`. +- Removed: Support for the `logical` keyword within `margin`, `padding`, `border-width`, `border-style`, `border-color` properties. (major) +- Removed support for `preserve` option. Changes are no longer preserved (major). +- Removed support for transforming `float`, `clear` and `resize` properties. (major) +- Updated: The plugin now requires block and inline direction to be configured (uses `top-to-bottom` and `left-to-right` respectively) and no longer introduces `:dir` (major). ### 5.0.4 (February 5, 2022) @@ -33,7 +39,7 @@ making it impossible for end users to have a working setup. ### 4.0.2 (June 10, 2019) - Fixed: Restored transforms for `max-block-size`, `max-inline-size`, - `min-block-size`, and `min-inline-size`. + `min-block-size`, and `min-inline-size`. ### 4.0.1 (June 10, 2019) @@ -42,13 +48,13 @@ making it impossible for end users to have a working setup. ### 4.0.0 (June 5, 2019) - Added: Logical border-radius properties, which include - `border-end-end-radius`, `border-end-start-radius`, `border-start-end-radius`, - and `border-start-start-radius`. + `border-end-end-radius`, `border-end-start-radius`, `border-start-end-radius`, + and `border-start-start-radius`. - Removed: All unknown logical properties, which include `border-end`, - `border-end-color`, `border-end-style`, `border-end-width`, `border-start`, - `border-start-color`, `border-start-style`, `border-start-width`, `inset-end`, - `inset-start`, `margin-end`, `margin-start`, `padding-end`, `padding-start` - and `border` with `logical`. + `border-end-color`, `border-end-style`, `border-end-width`, `border-start`, + `border-start-color`, `border-start-style`, `border-start-width`, `inset-end`, + `inset-start`, `margin-end`, `margin-start`, `padding-end`, `padding-start` + and `border` with `logical`. - Updated: `transition` and `transition-property` to support the changes. - Updated: `postcss` to 7.0.16 (patch) - Updated: Node 8+ compatibility (major) @@ -56,9 +62,9 @@ making it impossible for end users to have a working setup. ### 3.0.0 (September 20, 2018) - Added: Support for logical properties within `transition` and - `transition-property`. + `transition-property`. - Changed: Physical rule fallbacks are written as full selectors rather than - as nesting selectors. + as nesting selectors. ### 2.0.0 (September 17, 2018) diff --git a/plugins/postcss-logical/README.md b/plugins/postcss-logical/README.md index 27b22e50f..3967e5036 100644 --- a/plugins/postcss-logical/README.md +++ b/plugins/postcss-logical/README.md @@ -1,211 +1,122 @@ -# PostCSS Logical Properties and Values [PostCSS Logo][postcss] +# PostCSS Logical Properties and Values [PostCSS Logo][PostCSS] -[![NPM Version][npm-img]][npm-url] -[![CSS Standard Status][css-img]][css-url] -[![Build Status][cli-img]][cli-url] -[Discord][discord] +[npm version][npm-url] [CSS Standard Status][css-url] [Build Status][cli-url] [Discord][discord] -[PostCSS Logical Properties and Values] lets you use logical, rather than -physical, direction and dimension mappings in CSS, following the -[CSS Logical Properties and Values] specification. - -[!['Can I use' table](https://caniuse.bitsofco.de/image/css-logical-props.png)](https://caniuse.com/#feat=css-logical-props) +[PostCSS Logical Properties and Values] lets you use logical, rather than physical, direction and dimension mappings in CSS, following the [CSS Logical Properties and Values] specification. ```pcss -.banner { - color: #222222; - inset: logical 0 5px 10px; - padding-inline: 20px 40px; - resize: block; - transition: color 200ms; +.element { + block-size: 100px; + inline-size: 200px; + padding-block: 10px 20px; + margin-inline: auto; + border-block-width: 2px; + border-block-style: solid; } /* becomes */ -.banner:dir(ltr) { - padding-left: 20px; - padding-right: 40px; -} -.banner:dir(rtl) { - padding-right: 20px; - padding-left: 40px; -} -.banner { - color: #222222; - top: 0; - left: 5px; - bottom: 10px; - right: 5px; - resize: vertical; - transition: color 200ms; -} - -/* or, when used with { dir: 'ltr' } */ - -.banner { - color: #222222; - top: 0; - left: 5px; - bottom: 10px; - right: 5px; - padding-left: 20px; - padding-right: 40px; - resize: vertical; - transition: color 200ms; -} - -/* or, when used with { preserve: true } */ - -.banner:dir(ltr) { - padding-left: 20px; - padding-right: 40px; -} -.banner:dir(rtl) { - padding-right: 20px; - padding-left: 40px; -} -.banner { - color: #222222; - top: 0; - left: 5px; - bottom: 10px; - right: 5px; - inset: logical 0 5px 10px; - padding-inline: 20px 40px; - resize: vertical; - resize: block; - transition: color 200ms; +.element { + height: 100px; + width: 200px; + padding-top: 10px; + padding-bottom: 20px; + margin-left: auto; + margin-right: auto; + border-top-width: 2px; + border-bottom-width: 2px; + border-top-style: solid; + border-bottom-style: solid; } ``` -These shorthand properties set values for physical properties by default. -Specifying the `logical` keyboard at the beginning of the property value will -transform the flow-relative values afterward into both physical LTR and RTL -properties: - -#### Logical Borders - -- `border`, `border-block`, `border-block-start`, `border-block-end`, - `border-inline`, `border-inline-start`, `border-inline-end`, `border-start`, - `border-end`, `border-color`, `border-block-color`, - `border-block-start-color`, `border-block-end-color`, `border-inline-color`, - `border-inline-start-color`, `border-inline-end-color`, `border-start-color`, - `border-end-color`, `border-style`, `border-block-style`, - `border-block-start-style`, `border-block-end-style`, `border-inline-style`, - `border-inline-start-style`, `border-inline-end-style`, `border-start-style`, - `border-end-style`, `border-width`, `border-block-width`, - `border-block-start-width`, `border-block-end-width`, `border-inline-width`, - `border-inline-start-width`, `border-inline-end-width`, `border-start-width`, - `border-end-width`, `border-start-start-radius`, `border-start-end-radius`, - `border-end-start-radius`, `border-end-end-radius` - -#### Logical Offsets - -- `inset`, `inset-block`, `inset-block-start`, `inset-block-end`, - `inset-inline`, `inset-inline-start`, `inset-inline-end`, `inset-start`, - `inset-end` - -#### Logical Margins - -- `margin`, `margin-block`, `margin-block-start`, `margin-block-end`, - `margin-inline`, `margin-inline-start`, `margin-inline-end`, `margin-start`, - `margin-end` - -#### Logical Paddings - -- `padding`, `padding-block`, `padding-block-start`, `padding-block-end`, - `padding-inline`, `padding-inline-start`, `padding-inline-end`, - `padding-start`, `padding-end` - -#### Logical Sizes - -- `block-size`, `max-block-size`, `min-block-size`, `inline-size`, `max-inline-size`, `min-inline-size` - -#### Flow-Relative Values - -- `clear: inline-start`, `clear: inline-end`, `float: inline-start`, - `float: inline-end`, `text-align: start`, `text-align: end` - ---- - -By default, [PostCSS Logical Properties and Values] creates fallback selectors -which require at least one `[dir]` attribute in your HTML. If you don’t have -any `[dir]` attributes, consider using the following JavaScript: - -```js -// force at least one dir attribute (this can run at any time) -document.documentElement.dir = document.documentElement.dir || 'ltr'; -``` - -Otherwise, consider using the `dir` option to transform all logical properties -and values to a specific direction. - -```js -require('postcss-logical')({ - dir: 'ltr' -}); -``` - ## Usage Add [PostCSS Logical Properties and Values] to your project: ```bash -npm install postcss-logical --save-dev +npm install postcss postcss-logical --save-dev ``` -Use [PostCSS Logical Properties and Values] as a [PostCSS] plugin: +Use it as a [PostCSS] plugin: ```js const postcss = require('postcss'); const postcssLogical = require('postcss-logical'); postcss([ - postcssLogical(/* pluginOptions */) + postcssLogical(/* pluginOptions */) ]).process(YOUR_CSS /*, processOptions */); ``` -[PostCSS Logical Properties and Values] runs in all Node environments, with -special instructions for: +[PostCSS Logical Properties and Values] runs in all Node environments, with special +instructions for: -| [Node](INSTALL.md#node) | [PostCSS CLI](INSTALL.md#postcss-cli) | [Webpack](INSTALL.md#webpack) | [Gulp](INSTALL.md#gulp) | [Grunt](INSTALL.md#grunt) | -| --- | --- | --- | --- | --- | +- [Node](INSTALL.md#node) +- [PostCSS CLI](INSTALL.md#postcss-cli) +- [PostCSS Load Config](INSTALL.md#postcss-load-config) +- [Webpack](INSTALL.md#webpack) +- [Next.js](INSTALL.md#nextjs) +- [Gulp](INSTALL.md#gulp) +- [Grunt](INSTALL.md#grunt) ## Options -### dir +### blockDirection & inlineDirection + +The `blockDirection` and `inlineDirection` options allow you to specify the direction of the block and inline axes. The default values are `top-to-bottom` and `left-to-right` respectively which would match any latin language. + +You might want to tweak these values if you are using a different writing system, such as Arabic, Hebrew or Chinese for example. -The `dir` option determines how directional fallbacks should be added to CSS. -By default, fallbacks replace the logical declaration with nested `:dir` -pseudo-classes. If `dir` is defined as `ltr` or `rtl` then only the left or -right directional fallbacks will replace the logical declarations. If -`preserve` is defined as `true`, then the `dir` option will be ignored. +```js +postcssLogical({ + blockDirection: 'right-to-left', + inlineDirection: 'top-to-bottom' +}) +``` -### preserve +```pcss +.element { + block-size: 100px; + inline-size: 200px; + padding-block: 10px 20px; + margin-inline: auto; + border-block-width: 2px; + border-block-style: solid; +} -The `preserve` option determines whether directional fallbacks should be added -before logical declarations without replacing them. By default, directional -fallbacks replace logical declaration. If `preserve` is defined as `true`, then -the `dir` option will be ignored. +/* becomes */ -## :dir() pseudo class +.element { + width: 100px; + height: 200px; + padding-right: 10px; + padding-left: 20px; + margin-top: auto; + margin-bottom: auto; + border-right-width: 2px; + border-left-width: 2px; + border-right-style: solid; + border-left-style: solid; +} +``` -This plugin transforms using the `:dir(ltr)` pseudo class. -Use [postcss-dir-pseudo-class](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-dir-pseudo-class#readme) to further transform to `[dir="ltr"]`. +Each direction must be one of the following: -Currently `:dir(ltr)` doesn't have great browser support but this will improve over time. +- `top-to-bottom` +- `bottom-to-top` +- `left-to-right` +- `right-to-left` + +You can't mix two vertical directions or two horizontal directions so for example `top-to-bottom` and `right-to-left` are valid, but `top-to-bottom` and `bottom-to-top` are not. + +Please do note that `text-align` won't be transformed if `inlineDirection` becomes vertical. -[css-img]: https://cssdb.org/images/badges/logical-properties-and-values.svg -[css-url]: https://cssdb.org/#logical-properties-and-values -[cli-img]: https://github.com/csstools/postcss-plugins/workflows/test/badge.svg [cli-url]: https://github.com/csstools/postcss-plugins/actions/workflows/test.yml?query=workflow/test +[css-url]: https://cssdb.org/#logical-properties-and-values [discord]: https://discord.gg/bUadyRwkJS -[npm-img]: https://img.shields.io/npm/v/postcss-logical.svg [npm-url]: https://www.npmjs.com/package/postcss-logical -[CSS Logical Properties and Values]: https://drafts.csswg.org/css-logical/ -[Gulp PostCSS]: https://github.com/postcss/gulp-postcss -[Grunt PostCSS]: https://github.com/nDmitry/grunt-postcss [PostCSS]: https://github.com/postcss/postcss -[PostCSS Loader]: https://github.com/postcss/postcss-loader [PostCSS Logical Properties and Values]: https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-logical +[CSS Logical Properties and Values]: https://www.w3.org/TR/css-logical-1/ diff --git a/plugins/postcss-logical/dist/index.cjs b/plugins/postcss-logical/dist/index.cjs index cf7578392..e674b781c 100644 --- a/plugins/postcss-logical/dist/index.cjs +++ b/plugins/postcss-logical/dist/index.cjs @@ -1 +1 @@ -"use strict";var r=require("postcss"),cloneRule=(e,t)=>{const o="rule"===Object(e.parent).type?e.parent.cloneBefore({raws:{}}).removeAll():r.rule({selector:"&"});return o.selectors=o.selectors.map((r=>`${r}:dir(${t})`)),o};const e=/^border-(block|block-start|block-end|inline|inline-start|inline-end)(-(width|style|color))?$/i;var transformBorder_border_block=(r,t,o,l)=>{r.cloneBefore({prop:`border-top${r.prop.replace(e,"$2")}`,value:t[0]}),r.cloneBefore({prop:`border-bottom${r.prop.replace(e,"$2")}`,value:t[1]||t[0]}),clean$8(r,l)},transformBorder_border_block_start=(r,t,o,l)=>{r.cloneBefore({prop:`border-top${r.prop.replace(e,"$2")}`}),clean$8(r,l)},transformBorder_border_block_end=(r,t,o,l)=>{r.cloneBefore({prop:`border-bottom${r.prop.replace(e,"$2")}`}),clean$8(r,l)},transformBorder_border_inline=(r,t,o,l)=>{const ltrDecls=()=>[r.cloneBefore({prop:`border-left${r.prop.replace(e,"$2")}`,value:t[0]}),r.cloneBefore({prop:`border-right${r.prop.replace(e,"$2")}`,value:t[1]||t[0]})],rtlDecls=()=>[r.clone({prop:`border-right${r.prop.replace(e,"$2")}`,value:t[0]}),r.clone({prop:`border-left${r.prop.replace(e,"$2")}`,value:t[1]||t[0]})];return 1===t.length||2===t.length&&t[0]===t[1]||"ltr"===o?(ltrDecls(),void clean$8(r,l)):"rtl"===o?(rtlDecls(),void clean$8(r,l)):(cloneRule(r,"ltr").append(ltrDecls()),cloneRule(r,"rtl").append(rtlDecls()),void clean$8(r,l))},transformBorder_border_inline_start=(r,t,o,l)=>{const ltrDecl=()=>r.cloneBefore({prop:`border-left${r.prop.replace(e,"$2")}`}),rtlDecl=()=>r.cloneBefore({prop:`border-right${r.prop.replace(e,"$2")}`});return"ltr"===o?(ltrDecl(),void clean$8(r,l)):"rtl"===o?(rtlDecl(),void clean$8(r,l)):(cloneRule(r,"ltr").append(ltrDecl()),cloneRule(r,"rtl").append(rtlDecl()),void clean$8(r,l))},transformBorder_border_inline_end=(r,t,o,l)=>{const ltrDecl=()=>r.cloneBefore({prop:`border-right${r.prop.replace(e,"$2")}`}),rtlDecl=()=>r.cloneBefore({prop:`border-left${r.prop.replace(e,"$2")}`});return"ltr"===o?(ltrDecl(),void clean$8(r,l)):"rtl"===o?(rtlDecl(),void clean$8(r,l)):(cloneRule(r,"ltr").append(ltrDecl()),cloneRule(r,"rtl").append(rtlDecl()),void clean$8(r,l))};function clean$8(r,e){e||r.remove()}const t=/^(border-)(end-end|end-start|start-end|start-start)(-radius)$/i,o={"end-end":"bottom-right","end-start":"bottom-left","start-end":"top-right","start-start":"top-left"},l={"end-end":"bottom-left","end-start":"bottom-right","start-end":"top-left","start-start":"top-right"};var transformBorderRadius=(r,e,t,o)=>"ltr"===t?(lDecl$3(r),void clean$7(r,o)):"rtl"===t?(rDecl$3(r),void clean$7(r,o)):(cloneRule(r,"ltr").append(lDecl$3(r)),cloneRule(r,"rtl").append(rDecl$3(r)),void clean$7(r,o));function lDecl$3(r){return r.cloneBefore({prop:r.prop.replace(t,((r,e,t,l)=>`${e}${o[t]}${l}`))})}function rDecl$3(r){return r.cloneBefore({prop:r.prop.replace(t,((r,e,t,o)=>`${e}${l[t]}${o}`))})}function clean$7(r,e){e||r.remove()}var reduceValues=r=>{const e=r.slice();return 4===e.length&&e[3]===e[1]&&e.pop(),3===e.length&&e[2]===e[0]&&e.pop(),2===e.length&&e[1]===e[0]&&e.pop(),e},transformDirectionalShorthands=(r,e,t,o)=>{if("logical"!==e[0])return null;const[,l,n,i,d]=e,a=reduceValues([l,d||n||l,i||l,n||l]),ltrDecl=()=>r.cloneBefore({value:a.join(" ")});if(a.length<4||"ltr"===t)return ltrDecl(),void clean$6(r,o);const c=reduceValues([l,n||l,i||l,d||n||l]),rtlDecl=()=>r.cloneBefore({value:c.join(" ")});if("rtl"===t)return rtlDecl(),void clean$6(r,o);cloneRule(r,"ltr").append(ltrDecl()),cloneRule(r,"rtl").append(rtlDecl()),clean$6(r,o)};function clean$6(r,e){e||r.remove()}var transformFloat=(r,e,t,o)=>/^inline-start$/i.test(r.value)?"ltr"===t?(lDecl$2(r),void clean$5(r,o)):"rtl"===t?(rDecl$2(r),void clean$5(r,o)):(cloneRule(r,"ltr").append(lDecl$2(r)),cloneRule(r,"rtl").append(rDecl$2(r)),void clean$5(r,o)):/^inline-end$/i.test(r.value)?"ltr"===t?(rDecl$2(r),void clean$5(r,o)):"rtl"===t?(lDecl$2(r),void clean$5(r,o)):(cloneRule(r,"ltr").append(rDecl$2(r)),cloneRule(r,"rtl").append(lDecl$2(r)),void clean$5(r,o)):void 0;function lDecl$2(r){return r.cloneBefore({value:"left"})}function rDecl$2(r){return r.cloneBefore({value:"right"})}function clean$5(r,e){e||r.remove()}var transformInset=(r,e,t,o)=>{if("logical"!==e[0])return r.cloneBefore({prop:"top",value:e[0]}),r.cloneBefore({prop:"right",value:e[1]||e[0]}),r.cloneBefore({prop:"bottom",value:e[2]||e[0]}),r.cloneBefore({prop:"left",value:e[3]||e[1]||e[0]}),void clean$4(r,o);return!e[4]||e[4]===e[2]||"ltr"===t?(lDecl$1(r,e),void clean$4(r,o)):"rtl"===t?(rDecl$1(r,e),void clean$4(r,o)):(cloneRule(r,"ltr").append(lDecl$1(r,e)),cloneRule(r,"rtl").append(rDecl$1(r,e)),void clean$4(r,o))};function lDecl$1(r,e){return[r.cloneBefore({prop:"top",value:e[1]}),r.cloneBefore({prop:"left",value:e[2]||e[1]}),r.cloneBefore({prop:"bottom",value:e[3]||e[1]}),r.cloneBefore({prop:"right",value:e[4]||e[2]||e[1]})]}function rDecl$1(r,e){return[r.cloneBefore({prop:"top",value:e[1]}),r.cloneBefore({prop:"right",value:e[2]||e[1]}),r.cloneBefore({prop:"bottom",value:e[3]||e[1]}),r.cloneBefore({prop:"left",value:e[4]||e[2]||e[1]})]}function clean$4(r,e){e||r.remove()}var transformResize=(r,e,t,o)=>/^block$/i.test(r.value)?(r.cloneBefore({value:"vertical"}),void clean$3(r,o)):/^inline$/i.test(r.value)?(r.cloneBefore({value:"horizontal"}),void clean$3(r,o)):void 0;function clean$3(r,e){e||r.remove()}var n=/^(inset|margin|padding)(?:-(block|block-start|block-end|inline|inline-start|inline-end|start|end))$/i,i=/^inset-/i,cloneDeclBefore=(r,e,t)=>r.cloneBefore({prop:`${r.prop.replace(n,"$1")}${e}`.replace(i,""),value:t}),transformSide_block=(r,e,t,o)=>{cloneDeclBefore(r,"-top",e[0]),cloneDeclBefore(r,"-bottom",e[1]||e[0]),clean$2(r,o)},transformSide_block_start=(r,e,t,o)=>{r.cloneBefore({prop:r.prop.replace(n,"$1-top").replace(i,"")}),clean$2(r,o)},transformSide_block_end=(r,e,t,o)=>{r.cloneBefore({prop:r.prop.replace(n,"$1-bottom").replace(i,"")}),clean$2(r,o)},transformSide_inline=(r,e,t,o)=>{const ltrDecls=()=>[cloneDeclBefore(r,"-left",e[0]),cloneDeclBefore(r,"-right",e[1]||e[0])],rtlDecls=()=>[cloneDeclBefore(r,"-right",e[0]),cloneDeclBefore(r,"-left",e[1]||e[0])];return 1===e.length||2===e.length&&e[0]===e[1]||"ltr"===t?(ltrDecls(),void clean$2(r,o)):"rtl"===t?(rtlDecls(),void clean$2(r,o)):(cloneRule(r,"ltr").append(ltrDecls()),cloneRule(r,"rtl").append(rtlDecls()),void clean$2(r,o))},transformSide_inline_start=(r,e,t,o)=>{const ltrDecl=()=>cloneDeclBefore(r,"-left",r.value),rtlDecl=()=>cloneDeclBefore(r,"-right",r.value);return"ltr"===t?(ltrDecl(),void clean$2(r,o)):"rtl"===t?(rtlDecl(),void clean$2(r,o)):(cloneRule(r,"ltr").append(ltrDecl()),cloneRule(r,"rtl").append(rtlDecl()),void clean$2(r,o))},transformSide_inline_end=(r,e,t,o)=>{const ltrDecl=()=>cloneDeclBefore(r,"-right",r.value),rtlDecl=()=>cloneDeclBefore(r,"-left",r.value);return"ltr"===t?(ltrDecl(),void clean$2(r,o)):"rtl"===t?(rtlDecl(),void clean$2(r,o)):(cloneRule(r,"ltr").append(ltrDecl()),cloneRule(r,"rtl").append(rtlDecl()),void clean$2(r,o))};function clean$2(r,e){e||r.remove()}var d=/^(min-|max-)?(block|inline)-(size)$/i,transformSize=(r,e,t,o)=>{r.cloneBefore({prop:r.prop.replace(d,((r,e,t)=>`${e||""}${"block"===t?"height":"width"}`))}),o||r.remove()},transformTextAlign=(r,e,t,o)=>/^start$/i.test(r.value)?"ltr"===t?(lDecl(r),void clean$1(r,o)):"rtl"===t?(rDecl(r),void clean$1(r,o)):(cloneRule(r,"ltr").append(lDecl(r)),cloneRule(r,"rtl").append(rDecl(r)),void clean$1(r,o)):/^end$/i.test(r.value)?"ltr"===t?(rDecl(r),void clean$1(r,o)):"rtl"===t?(lDecl(r),void clean$1(r,o)):(cloneRule(r,"ltr").append(rDecl(r)),cloneRule(r,"rtl").append(lDecl(r)),void clean$1(r,o)):void 0;function lDecl(r){return r.cloneBefore({value:"left"})}function rDecl(r){return r.cloneBefore({value:"right"})}function clean$1(r,e){e||r.remove()}function splitBySpace(r,e){return splitByRegExp(r,/^\s$/,e)}function splitByRegExp(r,e,t){const o=[];let l="",n=!1,i=0,d=-1;for(;++d0&&(i-=1):0===i&&e.test(a)&&(n=!0),n?(t&&!l.trim()||o.push(t?l.trim():l),t||o.push(a),l="",n=!1):l+=a}return""!==l&&o.push(t?l.trim():l),o}var transformTransition=(r,e,t,o)=>{const l=[],n=[];var i,d;return(i=r.value,splitByRegExp(i,/^,$/,d)).forEach((r=>{let e=!1;splitBySpace(r).forEach(((r,t,o)=>{r in a&&(e=!0,a[r].ltr.forEach((r=>{const e=o.slice();e.splice(t,1,r),l.length&&!/^,$/.test(l[l.length-1])&&l.push(","),l.push(e.join(""))})),a[r].rtl.forEach((r=>{const e=o.slice();e.splice(t,1,r),n.length&&!/^,$/.test(n[n.length-1])&&n.push(","),n.push(e.join(""))})))})),e||(l.push(r),n.push(r))})),l.length&&"ltr"===t?(o&&r.cloneBefore({}),void(r.value=l.join(""))):n.length&&"rtl"===t?(o&&r.cloneBefore({}),void(r.value=n.join(""))):l.join("")!==n.join("")?(cloneRule(r,"ltr").append(r.cloneBefore({value:l.join("")})),cloneRule(r,"rtl").append(r.cloneBefore({value:n.join("")})),void clean(r,o)):void 0};function clean(r,e){e||r.remove()}const a={"block-size":{ltr:["height"],rtl:["height"]},"inline-size":{ltr:["width"],rtl:["width"]},"margin-block-end":{ltr:["margin-bottom"],rtl:["margin-bottom"]},"margin-block-start":{ltr:["margin-top"],rtl:["margin-top"]},"margin-block":{ltr:["margin-top","margin-bottom"],rtl:["margin-top","margin-bottom"]},"margin-inline-end":{ltr:["margin-right"],rtl:["margin-left"]},"margin-inline-start":{ltr:["margin-left"],rtl:["margin-right"]},"margin-inline":{ltr:["margin-left","margin-right"],rtl:["margin-left","margin-right"]},"inset-block-end":{ltr:["bottom"],rtl:["bottom"]},"inset-block-start":{ltr:["top"],rtl:["top"]},"inset-block":{ltr:["top","bottom"],rtl:["top","bottom"]},"inset-inline-end":{ltr:["right"],rtl:["left"]},"inset-inline-start":{ltr:["left"],rtl:["right"]},"inset-inline":{ltr:["left","right"],rtl:["left","right"]},inset:{ltr:["top","right","bottom","left"],rtl:["top","right","bottom","left"]},"padding-block-end":{ltr:["padding-bottom"],rtl:["padding-bottom"]},"padding-block-start":{ltr:["padding-top"],rtl:["padding-top"]},"padding-block":{ltr:["padding-top","padding-bottom"],rtl:["padding-top","padding-bottom"]},"padding-inline-end":{ltr:["padding-right"],rtl:["padding-left"]},"padding-inline-start":{ltr:["padding-left"],rtl:["padding-right"]},"padding-inline":{ltr:["padding-left","padding-right"],rtl:["padding-left","padding-right"]},"border-block-color":{ltr:["border-top-color","border-bottom-color"],rtl:["border-top-color","border-bottom-color"]},"border-block-end-color":{ltr:["border-bottom-color"],rtl:["border-bottom-color"]},"border-block-end-style":{ltr:["border-bottom-style"],rtl:["border-bottom-style"]},"border-block-end-width":{ltr:["border-bottom-width"],rtl:["border-bottom-width"]},"border-block-end":{ltr:["border-bottom"],rtl:["border-bottom"]},"border-block-start-color":{ltr:["border-top-color"],rtl:["border-top-color"]},"border-block-start-style":{ltr:["border-top-style"],rtl:["border-top-style"]},"border-block-start-width":{ltr:["border-top-width"],rtl:["border-top-width"]},"border-block-start":{ltr:["border-top"],rtl:["border-top"]},"border-block-style":{ltr:["border-top-style","border-bottom-style"],rtl:["border-top-style","border-bottom-style"]},"border-block-width":{ltr:["border-top-width","border-bottom-width"],rtl:["border-top-width","border-bottom-width"]},"border-block":{ltr:["border-top","border-bottom"],rtl:["border-top","border-bottom"]},"border-inline-color":{ltr:["border-left-color","border-right-color"],rtl:["border-left-color","border-right-color"]},"border-inline-end-color":{ltr:["border-right-color"],rtl:["border-left-color"]},"border-inline-end-style":{ltr:["border-right-style"],rtl:["border-left-style"]},"border-inline-end-width":{ltr:["border-right-width"],rtl:["border-left-width"]},"border-inline-end":{ltr:["border-right"],rtl:["border-left"]},"border-inline-start-color":{ltr:["border-left-color"],rtl:["border-right-color"]},"border-inline-start-style":{ltr:["border-left-style"],rtl:["border-right-style"]},"border-inline-start-width":{ltr:["border-left-width"],rtl:["border-right-width"]},"border-inline-start":{ltr:["border-left"],rtl:["border-right"]},"border-inline-style":{ltr:["border-left-style","border-right-style"],rtl:["border-left-style","border-right-style"]},"border-inline-width":{ltr:["border-left-width","border-right-width"],rtl:["border-left-width","border-right-width"]},"border-inline":{ltr:["border-left","border-right"],rtl:["border-left","border-right"]},"border-end-end-radius":{ltr:["border-bottom-right-radius"],rtl:["border-bottom-left-radius"]},"border-end-start-radius":{ltr:["border-bottom-left-radius"],rtl:["border-bottom-right-radius"]},"border-start-end-radius":{ltr:["border-top-right-radius"],rtl:["border-top-left-radius"]},"border-start-start-radius":{ltr:["border-top-left-radius"],rtl:["border-top-right-radius"]}};function hasKeyframesAtRuleAncestor(r){let e=r.parent;for(;e;)if("atrule"===e.type){if("keyframes"===e.name)return!0;e=e.parent}else e=e.parent;return!1}function postcssLogicalProperties(r){r=Object(r);const e=Boolean(r.preserve),t=!e&&"string"==typeof r.dir&&(/^rtl$/i.test(r.dir)?"rtl":"ltr"),makeTransform=r=>o=>{if(hasKeyframesAtRuleAncestor(o))return;const l=o.parent,n=splitBySpace(o.value,!0);r(o,n,t,e),l.nodes.length||l.remove()},makeTransformWithoutSplittingValues=r=>o=>{if(hasKeyframesAtRuleAncestor(o))return;const l=o.parent,n=[o.value];r(o,n,t,e),l.nodes.length||l.remove()};return{postcssPlugin:"postcss-logical-properties",Declaration:{clear:makeTransform(transformFloat),float:makeTransform(transformFloat),resize:makeTransform(transformResize),"text-align":makeTransform(transformTextAlign),"block-size":makeTransform(transformSize),"max-block-size":makeTransform(transformSize),"min-block-size":makeTransform(transformSize),"inline-size":makeTransform(transformSize),"max-inline-size":makeTransform(transformSize),"min-inline-size":makeTransform(transformSize),margin:makeTransform(transformDirectionalShorthands),"margin-inline":makeTransform(transformSide_inline),"margin-inline-end":makeTransform(transformSide_inline_end),"margin-inline-start":makeTransform(transformSide_inline_start),"margin-block":makeTransform(transformSide_block),"margin-block-end":makeTransform(transformSide_block_end),"margin-block-start":makeTransform(transformSide_block_start),inset:makeTransform(transformInset),"inset-inline":makeTransform(transformSide_inline),"inset-inline-end":makeTransform(transformSide_inline_end),"inset-inline-start":makeTransform(transformSide_inline_start),"inset-block":makeTransform(transformSide_block),"inset-block-end":makeTransform(transformSide_block_end),"inset-block-start":makeTransform(transformSide_block_start),padding:makeTransform(transformDirectionalShorthands),"padding-inline":makeTransform(transformSide_inline),"padding-inline-end":makeTransform(transformSide_inline_end),"padding-inline-start":makeTransform(transformSide_inline_start),"padding-block":makeTransform(transformSide_block),"padding-block-end":makeTransform(transformSide_block_end),"padding-block-start":makeTransform(transformSide_block_start),"border-block":makeTransformWithoutSplittingValues(transformBorder_border_block),"border-block-color":makeTransform(transformBorder_border_block),"border-block-style":makeTransform(transformBorder_border_block),"border-block-width":makeTransform(transformBorder_border_block),"border-block-end":makeTransformWithoutSplittingValues(transformBorder_border_block_end),"border-block-end-color":makeTransform(transformBorder_border_block_end),"border-block-end-style":makeTransform(transformBorder_border_block_end),"border-block-end-width":makeTransform(transformBorder_border_block_end),"border-block-start":makeTransformWithoutSplittingValues(transformBorder_border_block_start),"border-block-start-color":makeTransform(transformBorder_border_block_start),"border-block-start-style":makeTransform(transformBorder_border_block_start),"border-block-start-width":makeTransform(transformBorder_border_block_start),"border-inline":makeTransformWithoutSplittingValues(transformBorder_border_inline),"border-inline-color":makeTransform(transformBorder_border_inline),"border-inline-style":makeTransform(transformBorder_border_inline),"border-inline-width":makeTransform(transformBorder_border_inline),"border-inline-end":makeTransformWithoutSplittingValues(transformBorder_border_inline_end),"border-inline-end-color":makeTransform(transformBorder_border_inline_end),"border-inline-end-style":makeTransform(transformBorder_border_inline_end),"border-inline-end-width":makeTransform(transformBorder_border_inline_end),"border-inline-start":makeTransformWithoutSplittingValues(transformBorder_border_inline_start),"border-inline-start-color":makeTransform(transformBorder_border_inline_start),"border-inline-start-style":makeTransform(transformBorder_border_inline_start),"border-inline-start-width":makeTransform(transformBorder_border_inline_start),"border-end-end-radius":makeTransform(transformBorderRadius),"border-end-start-radius":makeTransform(transformBorderRadius),"border-start-end-radius":makeTransform(transformBorderRadius),"border-start-start-radius":makeTransform(transformBorderRadius),"border-color":makeTransform(transformDirectionalShorthands),"border-style":makeTransform(transformDirectionalShorthands),"border-width":makeTransform(transformDirectionalShorthands),transition:makeTransform(transformTransition),"transition-property":makeTransform(transformTransition)}}}postcssLogicalProperties.postcss=!0,module.exports=postcssLogicalProperties; +"use strict";var r,o,n=require("postcss-value-parser");!function(r){r.Block="block",r.Inline="inline"}(r||(r={})),function(r){r.Start="start",r.End="end"}(o||(o={}));const t={BlockStart:"block-start",BlockEnd:"block-end",InlineStart:"inline-start",InlineEnd:"inline-end"};var e,i;function cloneDeclaration(r,o,n){r.parent&&r.parent.some((r=>"decl"==r.type&&r.prop===n&&r.value===o))||r.cloneBefore({value:o,prop:n})}function parseValueCouple(r){const o=n(r.value).nodes.filter((r=>"space"!==r.type));if(o.length>2){const n=`[postcss-logical] Invalid number of values for ${r.prop}. Found ${o.length} values, expected 1 or 2.`;throw r.error(n)}let t,e;return 1===o.length&&(t=n.stringify(o[0]),e=t),2===o.length&&(t=n.stringify(o[0]),e=n.stringify(o[1])),[t,e]}function transformBorder(r,o){return n=>(cloneDeclaration(n,n.value,`border-${o}-${r}`),!0)}function transformBorderProperty(r,o){return n=>{const[t,e]=o,[i,a]=parseValueCouple(n);return cloneDeclaration(n,i,`border-${t}-${r}`),cloneDeclaration(n,a,`border-${e}-${r}`),!0}}function transformBorderShorthand(r){return o=>(r.forEach((r=>cloneDeclaration(o,o.value,`border-${r}`))),!0)}function transformBorderRadius(r){return o=>{let n;switch(o.prop.toLowerCase()){case"border-start-start-radius":n=`border-${r.inlineIsHorizontal?`${r.block[0]}-${r.inline[0]}`:`${r.inline[0]}-${r.block[0]}`}-radius`;break;case"border-start-end-radius":n=`border-${r.inlineIsHorizontal?`${r.block[0]}-${r.inline[1]}`:`${r.inline[1]}-${r.block[0]}`}-radius`;break;case"border-end-start-radius":n=`border-${r.inlineIsHorizontal?`${r.block[1]}-${r.inline[0]}`:`${r.inline[0]}-${r.block[1]}`}-radius`;break;case"border-end-end-radius":n=`border-${r.inlineIsHorizontal?`${r.block[1]}-${r.inline[1]}`:`${r.inline[1]}-${r.block[1]}`}-radius`;break}return cloneDeclaration(o,o.value,n),!0}}function transformLogicalSize(r){return o=>{const{value:n}=o,t=r.inlineIsHorizontal?"width":"height",e=r.inlineIsHorizontal?"height":"width";return cloneDeclaration(o,n,"block-size"===o.prop?e:t),!0}}function transformOffset(r){return o=>(cloneDeclaration(o,o.value,r),!0)}function transformOffsetShorthand(r){return o=>{const[n,t]=r,[e,i]=parseValueCouple(o);return cloneDeclaration(o,e,n),cloneDeclaration(o,i,t),!0}}function transformSide(r,o){return n=>(cloneDeclaration(n,n.value,`${r}-${o}`),!0)}function transformSideShorthand(r,o){return n=>{const[t,e]=o,[i,a]=parseValueCouple(n);return cloneDeclaration(n,i,`${r}-${t}`),cloneDeclaration(n,a,`${r}-${e}`),!0}}function logicalToPhysical(r,o){const[n,e]=o.block,[i,a]=o.inline;switch(r){case t.BlockStart:return n;case t.BlockEnd:return e;case t.InlineStart:return i;case t.InlineEnd:return a}}function doTransform(r,o,t){const{prop:e,value:i}=r,a=n(i);a.nodes.forEach((r=>{if("word"===r.type){const n=r.value.toLowerCase();o.includes(n)&&(r.value=logicalToPhysical(n,t))}}));const l=a.toString();return l!==i&&(cloneDeclaration(r,l,e),!0)}function directionFlowToAxes(r){switch(r){case e.TopToBottom:return[i.Top,i.Bottom];case e.BottomToTop:return[i.Bottom,i.Top];case e.RightToLeft:return[i.Right,i.Left];case e.LeftToRight:return[i.Left,i.Right]}}!function(r){r.TopToBottom="top-to-bottom",r.BottomToTop="bottom-to-top",r.RightToLeft="right-to-left",r.LeftToRight="left-to-right"}(e||(e={})),function(r){r.Top="top",r.Right="right",r.Bottom="bottom",r.Left="left"}(i||(i={}));const creator=r=>{const a=Object.assign({blockDirection:e.TopToBottom,inlineDirection:e.LeftToRight},r),l=Object.values(e);if(!l.includes(a.blockDirection))throw new Error(`[postcss-logical] "blockDirection" must be one of ${l.join(", ")}`);if(!l.includes(a.inlineDirection))throw new Error(`[postcss-logical] "inlineDirection" must be one of ${l.join(", ")}`);const[s,d]=directionFlowToAxes(a.blockDirection),[c,f]=directionFlowToAxes(a.inlineDirection);if(!Object.values(i).every((r=>[s,d,c,f].includes(r))))throw new Error('[postcss-logical] "blockDirection" and "inlineDirection" must be on separate axes');const u={block:[s,d],inline:[c,f],inlineIsHorizontal:[e.LeftToRight,e.RightToLeft].includes(a.inlineDirection)},makeTransform=r=>(o,{result:n})=>{if(!r)return;let t=!1;try{t=r(o)}catch(r){return void o.warn(n,r.message)}t&&o.remove()};return{postcssPlugin:"postcss-logical",Declaration:{"caption-side":makeTransform((m=u,r=>doTransform(r,Object.values(t),m))),"text-align":makeTransform(u.inlineIsHorizontal?(b=u.inline,r=>{const{prop:t,value:e}=r,i=n(e),[a,l]=b;i.nodes.forEach((r=>{if("word"===r.type){const n=r.value.toLowerCase();if(n===o.End)return void(r.value=l);n===o.Start&&(r.value=a)}}));const s=i.toString();return s!==e&&(cloneDeclaration(r,s,t),!0)}):null),"block-size":makeTransform(transformLogicalSize(u)),"inline-size":makeTransform(transformLogicalSize(u)),"margin-block-start":makeTransform(transformSide("margin",s)),"margin-block-end":makeTransform(transformSide("margin",d)),"margin-inline-start":makeTransform(transformSide("margin",c)),"margin-inline-end":makeTransform(transformSide("margin",f)),"margin-block":makeTransform(transformSideShorthand("margin",u.block)),"margin-inline":makeTransform(transformSideShorthand("margin",u.inline)),"inset-block":makeTransform(transformOffsetShorthand(u.block)),"inset-block-start":makeTransform(transformOffset(s)),"inset-block-end":makeTransform(transformOffset(d)),"inset-inline":makeTransform(transformOffsetShorthand(u.inline)),"inset-inline-start":makeTransform(transformOffset(c)),"inset-inline-end":makeTransform(transformOffset(f)),inset:makeTransform((r=>{const o=n(r.value).nodes.filter((r=>"space"!==r.type&&"comment"!==r.type));if(o.length>4){const n=`[postcss-logical] Invalid number of values for ${r.prop}. Found ${o.length} values, expected up to 4 values.`;throw r.error(n)}const t={top:"",right:"",bottom:"",left:""};return 1===o.length&&(t.top=n.stringify(o[0]),t.right=t.top,t.bottom=t.top,t.left=t.top),2===o.length&&(t.top=n.stringify(o[0]),t.right=n.stringify(o[1]),t.bottom=t.top,t.left=t.right),3===o.length&&(t.top=n.stringify(o[0]),t.right=n.stringify(o[1]),t.left=t.right,t.bottom=n.stringify(o[2])),4===o.length&&(t.top=n.stringify(o[0]),t.right=n.stringify(o[1]),t.bottom=n.stringify(o[2]),t.left=n.stringify(o[3])),Object.keys(t).forEach((o=>{cloneDeclaration(r,t[o],o)})),!0})),"padding-block-start":makeTransform(transformSide("padding",s)),"padding-block-end":makeTransform(transformSide("padding",d)),"padding-inline-start":makeTransform(transformSide("padding",c)),"padding-inline-end":makeTransform(transformSide("padding",f)),"padding-block":makeTransform(transformSideShorthand("padding",u.block)),"padding-inline":makeTransform(transformSideShorthand("padding",u.inline)),"border-block-start-width":makeTransform(transformBorder("width",s)),"border-block-end-width":makeTransform(transformBorder("width",d)),"border-inline-start-width":makeTransform(transformBorder("width",c)),"border-inline-end-width":makeTransform(transformBorder("width",f)),"border-block-width":makeTransform(transformBorderProperty("width",u.block)),"border-inline-width":makeTransform(transformBorderProperty("width",u.inline)),"border-block-start-style":makeTransform(transformBorder("style",s)),"border-block-end-style":makeTransform(transformBorder("style",d)),"border-inline-start-style":makeTransform(transformBorder("style",c)),"border-inline-end-style":makeTransform(transformBorder("style",f)),"border-block-style":makeTransform(transformBorderProperty("style",u.block)),"border-inline-style":makeTransform(transformBorderProperty("style",u.inline)),"border-block-start-color":makeTransform(transformBorder("color",s)),"border-block-end-color":makeTransform(transformBorder("color",d)),"border-inline-start-color":makeTransform(transformBorder("color",c)),"border-inline-end-color":makeTransform(transformBorder("color",f)),"border-block-color":makeTransform(transformBorderProperty("color",u.block)),"border-inline-color":makeTransform(transformBorderProperty("color",u.inline)),"border-block":makeTransform(transformBorderShorthand(u.block)),"border-block-start":makeTransform(transformBorderShorthand([s])),"border-block-end":makeTransform(transformBorderShorthand([d])),"border-inline":makeTransform(transformBorderShorthand(u.inline)),"border-inline-start":makeTransform(transformBorderShorthand([c])),"border-inline-end":makeTransform(transformBorderShorthand([f])),"border-start-start-radius":makeTransform(transformBorderRadius(u)),"border-start-end-radius":makeTransform(transformBorderRadius(u)),"border-end-start-radius":makeTransform(transformBorderRadius(u)),"border-end-end-radius":makeTransform(transformBorderRadius(u))}};var b,m};creator.postcss=!0,module.exports=creator; diff --git a/plugins/postcss-logical/dist/index.d.ts b/plugins/postcss-logical/dist/index.d.ts new file mode 100644 index 000000000..8e84fd80d --- /dev/null +++ b/plugins/postcss-logical/dist/index.d.ts @@ -0,0 +1,11 @@ +import type { PluginCreator } from 'postcss'; +import { DirectionFlow } from './lib/types'; +/** postcss-logical plugin options */ +export type pluginOptions = { + /** Sets the direction for block. default: top-to-bottom */ + blockDirection?: DirectionFlow; + /** Sets the direction for inline. default: left-to-right */ + inlineDirection?: DirectionFlow; +}; +declare const creator: PluginCreator; +export default creator; diff --git a/plugins/postcss-logical/dist/index.mjs b/plugins/postcss-logical/dist/index.mjs index 1c4c11a94..ac188eedd 100644 --- a/plugins/postcss-logical/dist/index.mjs +++ b/plugins/postcss-logical/dist/index.mjs @@ -1 +1 @@ -import r from"postcss";var cloneRule=(e,t)=>{const o="rule"===Object(e.parent).type?e.parent.cloneBefore({raws:{}}).removeAll():r.rule({selector:"&"});return o.selectors=o.selectors.map((r=>`${r}:dir(${t})`)),o};const e=/^border-(block|block-start|block-end|inline|inline-start|inline-end)(-(width|style|color))?$/i;var transformBorder_border_block=(r,t,o,l)=>{r.cloneBefore({prop:`border-top${r.prop.replace(e,"$2")}`,value:t[0]}),r.cloneBefore({prop:`border-bottom${r.prop.replace(e,"$2")}`,value:t[1]||t[0]}),clean$8(r,l)},transformBorder_border_block_start=(r,t,o,l)=>{r.cloneBefore({prop:`border-top${r.prop.replace(e,"$2")}`}),clean$8(r,l)},transformBorder_border_block_end=(r,t,o,l)=>{r.cloneBefore({prop:`border-bottom${r.prop.replace(e,"$2")}`}),clean$8(r,l)},transformBorder_border_inline=(r,t,o,l)=>{const ltrDecls=()=>[r.cloneBefore({prop:`border-left${r.prop.replace(e,"$2")}`,value:t[0]}),r.cloneBefore({prop:`border-right${r.prop.replace(e,"$2")}`,value:t[1]||t[0]})],rtlDecls=()=>[r.clone({prop:`border-right${r.prop.replace(e,"$2")}`,value:t[0]}),r.clone({prop:`border-left${r.prop.replace(e,"$2")}`,value:t[1]||t[0]})];return 1===t.length||2===t.length&&t[0]===t[1]||"ltr"===o?(ltrDecls(),void clean$8(r,l)):"rtl"===o?(rtlDecls(),void clean$8(r,l)):(cloneRule(r,"ltr").append(ltrDecls()),cloneRule(r,"rtl").append(rtlDecls()),void clean$8(r,l))},transformBorder_border_inline_start=(r,t,o,l)=>{const ltrDecl=()=>r.cloneBefore({prop:`border-left${r.prop.replace(e,"$2")}`}),rtlDecl=()=>r.cloneBefore({prop:`border-right${r.prop.replace(e,"$2")}`});return"ltr"===o?(ltrDecl(),void clean$8(r,l)):"rtl"===o?(rtlDecl(),void clean$8(r,l)):(cloneRule(r,"ltr").append(ltrDecl()),cloneRule(r,"rtl").append(rtlDecl()),void clean$8(r,l))},transformBorder_border_inline_end=(r,t,o,l)=>{const ltrDecl=()=>r.cloneBefore({prop:`border-right${r.prop.replace(e,"$2")}`}),rtlDecl=()=>r.cloneBefore({prop:`border-left${r.prop.replace(e,"$2")}`});return"ltr"===o?(ltrDecl(),void clean$8(r,l)):"rtl"===o?(rtlDecl(),void clean$8(r,l)):(cloneRule(r,"ltr").append(ltrDecl()),cloneRule(r,"rtl").append(rtlDecl()),void clean$8(r,l))};function clean$8(r,e){e||r.remove()}const t=/^(border-)(end-end|end-start|start-end|start-start)(-radius)$/i,o={"end-end":"bottom-right","end-start":"bottom-left","start-end":"top-right","start-start":"top-left"},l={"end-end":"bottom-left","end-start":"bottom-right","start-end":"top-left","start-start":"top-right"};var transformBorderRadius=(r,e,t,o)=>"ltr"===t?(lDecl$3(r),void clean$7(r,o)):"rtl"===t?(rDecl$3(r),void clean$7(r,o)):(cloneRule(r,"ltr").append(lDecl$3(r)),cloneRule(r,"rtl").append(rDecl$3(r)),void clean$7(r,o));function lDecl$3(r){return r.cloneBefore({prop:r.prop.replace(t,((r,e,t,l)=>`${e}${o[t]}${l}`))})}function rDecl$3(r){return r.cloneBefore({prop:r.prop.replace(t,((r,e,t,o)=>`${e}${l[t]}${o}`))})}function clean$7(r,e){e||r.remove()}var reduceValues=r=>{const e=r.slice();return 4===e.length&&e[3]===e[1]&&e.pop(),3===e.length&&e[2]===e[0]&&e.pop(),2===e.length&&e[1]===e[0]&&e.pop(),e},transformDirectionalShorthands=(r,e,t,o)=>{if("logical"!==e[0])return null;const[,l,n,i,d]=e,a=reduceValues([l,d||n||l,i||l,n||l]),ltrDecl=()=>r.cloneBefore({value:a.join(" ")});if(a.length<4||"ltr"===t)return ltrDecl(),void clean$6(r,o);const c=reduceValues([l,n||l,i||l,d||n||l]),rtlDecl=()=>r.cloneBefore({value:c.join(" ")});if("rtl"===t)return rtlDecl(),void clean$6(r,o);cloneRule(r,"ltr").append(ltrDecl()),cloneRule(r,"rtl").append(rtlDecl()),clean$6(r,o)};function clean$6(r,e){e||r.remove()}var transformFloat=(r,e,t,o)=>/^inline-start$/i.test(r.value)?"ltr"===t?(lDecl$2(r),void clean$5(r,o)):"rtl"===t?(rDecl$2(r),void clean$5(r,o)):(cloneRule(r,"ltr").append(lDecl$2(r)),cloneRule(r,"rtl").append(rDecl$2(r)),void clean$5(r,o)):/^inline-end$/i.test(r.value)?"ltr"===t?(rDecl$2(r),void clean$5(r,o)):"rtl"===t?(lDecl$2(r),void clean$5(r,o)):(cloneRule(r,"ltr").append(rDecl$2(r)),cloneRule(r,"rtl").append(lDecl$2(r)),void clean$5(r,o)):void 0;function lDecl$2(r){return r.cloneBefore({value:"left"})}function rDecl$2(r){return r.cloneBefore({value:"right"})}function clean$5(r,e){e||r.remove()}var transformInset=(r,e,t,o)=>{if("logical"!==e[0])return r.cloneBefore({prop:"top",value:e[0]}),r.cloneBefore({prop:"right",value:e[1]||e[0]}),r.cloneBefore({prop:"bottom",value:e[2]||e[0]}),r.cloneBefore({prop:"left",value:e[3]||e[1]||e[0]}),void clean$4(r,o);return!e[4]||e[4]===e[2]||"ltr"===t?(lDecl$1(r,e),void clean$4(r,o)):"rtl"===t?(rDecl$1(r,e),void clean$4(r,o)):(cloneRule(r,"ltr").append(lDecl$1(r,e)),cloneRule(r,"rtl").append(rDecl$1(r,e)),void clean$4(r,o))};function lDecl$1(r,e){return[r.cloneBefore({prop:"top",value:e[1]}),r.cloneBefore({prop:"left",value:e[2]||e[1]}),r.cloneBefore({prop:"bottom",value:e[3]||e[1]}),r.cloneBefore({prop:"right",value:e[4]||e[2]||e[1]})]}function rDecl$1(r,e){return[r.cloneBefore({prop:"top",value:e[1]}),r.cloneBefore({prop:"right",value:e[2]||e[1]}),r.cloneBefore({prop:"bottom",value:e[3]||e[1]}),r.cloneBefore({prop:"left",value:e[4]||e[2]||e[1]})]}function clean$4(r,e){e||r.remove()}var transformResize=(r,e,t,o)=>/^block$/i.test(r.value)?(r.cloneBefore({value:"vertical"}),void clean$3(r,o)):/^inline$/i.test(r.value)?(r.cloneBefore({value:"horizontal"}),void clean$3(r,o)):void 0;function clean$3(r,e){e||r.remove()}var n=/^(inset|margin|padding)(?:-(block|block-start|block-end|inline|inline-start|inline-end|start|end))$/i,i=/^inset-/i,cloneDeclBefore=(r,e,t)=>r.cloneBefore({prop:`${r.prop.replace(n,"$1")}${e}`.replace(i,""),value:t}),transformSide_block=(r,e,t,o)=>{cloneDeclBefore(r,"-top",e[0]),cloneDeclBefore(r,"-bottom",e[1]||e[0]),clean$2(r,o)},transformSide_block_start=(r,e,t,o)=>{r.cloneBefore({prop:r.prop.replace(n,"$1-top").replace(i,"")}),clean$2(r,o)},transformSide_block_end=(r,e,t,o)=>{r.cloneBefore({prop:r.prop.replace(n,"$1-bottom").replace(i,"")}),clean$2(r,o)},transformSide_inline=(r,e,t,o)=>{const ltrDecls=()=>[cloneDeclBefore(r,"-left",e[0]),cloneDeclBefore(r,"-right",e[1]||e[0])],rtlDecls=()=>[cloneDeclBefore(r,"-right",e[0]),cloneDeclBefore(r,"-left",e[1]||e[0])];return 1===e.length||2===e.length&&e[0]===e[1]||"ltr"===t?(ltrDecls(),void clean$2(r,o)):"rtl"===t?(rtlDecls(),void clean$2(r,o)):(cloneRule(r,"ltr").append(ltrDecls()),cloneRule(r,"rtl").append(rtlDecls()),void clean$2(r,o))},transformSide_inline_start=(r,e,t,o)=>{const ltrDecl=()=>cloneDeclBefore(r,"-left",r.value),rtlDecl=()=>cloneDeclBefore(r,"-right",r.value);return"ltr"===t?(ltrDecl(),void clean$2(r,o)):"rtl"===t?(rtlDecl(),void clean$2(r,o)):(cloneRule(r,"ltr").append(ltrDecl()),cloneRule(r,"rtl").append(rtlDecl()),void clean$2(r,o))},transformSide_inline_end=(r,e,t,o)=>{const ltrDecl=()=>cloneDeclBefore(r,"-right",r.value),rtlDecl=()=>cloneDeclBefore(r,"-left",r.value);return"ltr"===t?(ltrDecl(),void clean$2(r,o)):"rtl"===t?(rtlDecl(),void clean$2(r,o)):(cloneRule(r,"ltr").append(ltrDecl()),cloneRule(r,"rtl").append(rtlDecl()),void clean$2(r,o))};function clean$2(r,e){e||r.remove()}var d=/^(min-|max-)?(block|inline)-(size)$/i,transformSize=(r,e,t,o)=>{r.cloneBefore({prop:r.prop.replace(d,((r,e,t)=>`${e||""}${"block"===t?"height":"width"}`))}),o||r.remove()},transformTextAlign=(r,e,t,o)=>/^start$/i.test(r.value)?"ltr"===t?(lDecl(r),void clean$1(r,o)):"rtl"===t?(rDecl(r),void clean$1(r,o)):(cloneRule(r,"ltr").append(lDecl(r)),cloneRule(r,"rtl").append(rDecl(r)),void clean$1(r,o)):/^end$/i.test(r.value)?"ltr"===t?(rDecl(r),void clean$1(r,o)):"rtl"===t?(lDecl(r),void clean$1(r,o)):(cloneRule(r,"ltr").append(rDecl(r)),cloneRule(r,"rtl").append(lDecl(r)),void clean$1(r,o)):void 0;function lDecl(r){return r.cloneBefore({value:"left"})}function rDecl(r){return r.cloneBefore({value:"right"})}function clean$1(r,e){e||r.remove()}function splitBySpace(r,e){return splitByRegExp(r,/^\s$/,e)}function splitByRegExp(r,e,t){const o=[];let l="",n=!1,i=0,d=-1;for(;++d0&&(i-=1):0===i&&e.test(a)&&(n=!0),n?(t&&!l.trim()||o.push(t?l.trim():l),t||o.push(a),l="",n=!1):l+=a}return""!==l&&o.push(t?l.trim():l),o}var transformTransition=(r,e,t,o)=>{const l=[],n=[];var i,d;return(i=r.value,splitByRegExp(i,/^,$/,d)).forEach((r=>{let e=!1;splitBySpace(r).forEach(((r,t,o)=>{r in a&&(e=!0,a[r].ltr.forEach((r=>{const e=o.slice();e.splice(t,1,r),l.length&&!/^,$/.test(l[l.length-1])&&l.push(","),l.push(e.join(""))})),a[r].rtl.forEach((r=>{const e=o.slice();e.splice(t,1,r),n.length&&!/^,$/.test(n[n.length-1])&&n.push(","),n.push(e.join(""))})))})),e||(l.push(r),n.push(r))})),l.length&&"ltr"===t?(o&&r.cloneBefore({}),void(r.value=l.join(""))):n.length&&"rtl"===t?(o&&r.cloneBefore({}),void(r.value=n.join(""))):l.join("")!==n.join("")?(cloneRule(r,"ltr").append(r.cloneBefore({value:l.join("")})),cloneRule(r,"rtl").append(r.cloneBefore({value:n.join("")})),void clean(r,o)):void 0};function clean(r,e){e||r.remove()}const a={"block-size":{ltr:["height"],rtl:["height"]},"inline-size":{ltr:["width"],rtl:["width"]},"margin-block-end":{ltr:["margin-bottom"],rtl:["margin-bottom"]},"margin-block-start":{ltr:["margin-top"],rtl:["margin-top"]},"margin-block":{ltr:["margin-top","margin-bottom"],rtl:["margin-top","margin-bottom"]},"margin-inline-end":{ltr:["margin-right"],rtl:["margin-left"]},"margin-inline-start":{ltr:["margin-left"],rtl:["margin-right"]},"margin-inline":{ltr:["margin-left","margin-right"],rtl:["margin-left","margin-right"]},"inset-block-end":{ltr:["bottom"],rtl:["bottom"]},"inset-block-start":{ltr:["top"],rtl:["top"]},"inset-block":{ltr:["top","bottom"],rtl:["top","bottom"]},"inset-inline-end":{ltr:["right"],rtl:["left"]},"inset-inline-start":{ltr:["left"],rtl:["right"]},"inset-inline":{ltr:["left","right"],rtl:["left","right"]},inset:{ltr:["top","right","bottom","left"],rtl:["top","right","bottom","left"]},"padding-block-end":{ltr:["padding-bottom"],rtl:["padding-bottom"]},"padding-block-start":{ltr:["padding-top"],rtl:["padding-top"]},"padding-block":{ltr:["padding-top","padding-bottom"],rtl:["padding-top","padding-bottom"]},"padding-inline-end":{ltr:["padding-right"],rtl:["padding-left"]},"padding-inline-start":{ltr:["padding-left"],rtl:["padding-right"]},"padding-inline":{ltr:["padding-left","padding-right"],rtl:["padding-left","padding-right"]},"border-block-color":{ltr:["border-top-color","border-bottom-color"],rtl:["border-top-color","border-bottom-color"]},"border-block-end-color":{ltr:["border-bottom-color"],rtl:["border-bottom-color"]},"border-block-end-style":{ltr:["border-bottom-style"],rtl:["border-bottom-style"]},"border-block-end-width":{ltr:["border-bottom-width"],rtl:["border-bottom-width"]},"border-block-end":{ltr:["border-bottom"],rtl:["border-bottom"]},"border-block-start-color":{ltr:["border-top-color"],rtl:["border-top-color"]},"border-block-start-style":{ltr:["border-top-style"],rtl:["border-top-style"]},"border-block-start-width":{ltr:["border-top-width"],rtl:["border-top-width"]},"border-block-start":{ltr:["border-top"],rtl:["border-top"]},"border-block-style":{ltr:["border-top-style","border-bottom-style"],rtl:["border-top-style","border-bottom-style"]},"border-block-width":{ltr:["border-top-width","border-bottom-width"],rtl:["border-top-width","border-bottom-width"]},"border-block":{ltr:["border-top","border-bottom"],rtl:["border-top","border-bottom"]},"border-inline-color":{ltr:["border-left-color","border-right-color"],rtl:["border-left-color","border-right-color"]},"border-inline-end-color":{ltr:["border-right-color"],rtl:["border-left-color"]},"border-inline-end-style":{ltr:["border-right-style"],rtl:["border-left-style"]},"border-inline-end-width":{ltr:["border-right-width"],rtl:["border-left-width"]},"border-inline-end":{ltr:["border-right"],rtl:["border-left"]},"border-inline-start-color":{ltr:["border-left-color"],rtl:["border-right-color"]},"border-inline-start-style":{ltr:["border-left-style"],rtl:["border-right-style"]},"border-inline-start-width":{ltr:["border-left-width"],rtl:["border-right-width"]},"border-inline-start":{ltr:["border-left"],rtl:["border-right"]},"border-inline-style":{ltr:["border-left-style","border-right-style"],rtl:["border-left-style","border-right-style"]},"border-inline-width":{ltr:["border-left-width","border-right-width"],rtl:["border-left-width","border-right-width"]},"border-inline":{ltr:["border-left","border-right"],rtl:["border-left","border-right"]},"border-end-end-radius":{ltr:["border-bottom-right-radius"],rtl:["border-bottom-left-radius"]},"border-end-start-radius":{ltr:["border-bottom-left-radius"],rtl:["border-bottom-right-radius"]},"border-start-end-radius":{ltr:["border-top-right-radius"],rtl:["border-top-left-radius"]},"border-start-start-radius":{ltr:["border-top-left-radius"],rtl:["border-top-right-radius"]}};function hasKeyframesAtRuleAncestor(r){let e=r.parent;for(;e;)if("atrule"===e.type){if("keyframes"===e.name)return!0;e=e.parent}else e=e.parent;return!1}function postcssLogicalProperties(r){r=Object(r);const e=Boolean(r.preserve),t=!e&&"string"==typeof r.dir&&(/^rtl$/i.test(r.dir)?"rtl":"ltr"),makeTransform=r=>o=>{if(hasKeyframesAtRuleAncestor(o))return;const l=o.parent,n=splitBySpace(o.value,!0);r(o,n,t,e),l.nodes.length||l.remove()},makeTransformWithoutSplittingValues=r=>o=>{if(hasKeyframesAtRuleAncestor(o))return;const l=o.parent,n=[o.value];r(o,n,t,e),l.nodes.length||l.remove()};return{postcssPlugin:"postcss-logical-properties",Declaration:{clear:makeTransform(transformFloat),float:makeTransform(transformFloat),resize:makeTransform(transformResize),"text-align":makeTransform(transformTextAlign),"block-size":makeTransform(transformSize),"max-block-size":makeTransform(transformSize),"min-block-size":makeTransform(transformSize),"inline-size":makeTransform(transformSize),"max-inline-size":makeTransform(transformSize),"min-inline-size":makeTransform(transformSize),margin:makeTransform(transformDirectionalShorthands),"margin-inline":makeTransform(transformSide_inline),"margin-inline-end":makeTransform(transformSide_inline_end),"margin-inline-start":makeTransform(transformSide_inline_start),"margin-block":makeTransform(transformSide_block),"margin-block-end":makeTransform(transformSide_block_end),"margin-block-start":makeTransform(transformSide_block_start),inset:makeTransform(transformInset),"inset-inline":makeTransform(transformSide_inline),"inset-inline-end":makeTransform(transformSide_inline_end),"inset-inline-start":makeTransform(transformSide_inline_start),"inset-block":makeTransform(transformSide_block),"inset-block-end":makeTransform(transformSide_block_end),"inset-block-start":makeTransform(transformSide_block_start),padding:makeTransform(transformDirectionalShorthands),"padding-inline":makeTransform(transformSide_inline),"padding-inline-end":makeTransform(transformSide_inline_end),"padding-inline-start":makeTransform(transformSide_inline_start),"padding-block":makeTransform(transformSide_block),"padding-block-end":makeTransform(transformSide_block_end),"padding-block-start":makeTransform(transformSide_block_start),"border-block":makeTransformWithoutSplittingValues(transformBorder_border_block),"border-block-color":makeTransform(transformBorder_border_block),"border-block-style":makeTransform(transformBorder_border_block),"border-block-width":makeTransform(transformBorder_border_block),"border-block-end":makeTransformWithoutSplittingValues(transformBorder_border_block_end),"border-block-end-color":makeTransform(transformBorder_border_block_end),"border-block-end-style":makeTransform(transformBorder_border_block_end),"border-block-end-width":makeTransform(transformBorder_border_block_end),"border-block-start":makeTransformWithoutSplittingValues(transformBorder_border_block_start),"border-block-start-color":makeTransform(transformBorder_border_block_start),"border-block-start-style":makeTransform(transformBorder_border_block_start),"border-block-start-width":makeTransform(transformBorder_border_block_start),"border-inline":makeTransformWithoutSplittingValues(transformBorder_border_inline),"border-inline-color":makeTransform(transformBorder_border_inline),"border-inline-style":makeTransform(transformBorder_border_inline),"border-inline-width":makeTransform(transformBorder_border_inline),"border-inline-end":makeTransformWithoutSplittingValues(transformBorder_border_inline_end),"border-inline-end-color":makeTransform(transformBorder_border_inline_end),"border-inline-end-style":makeTransform(transformBorder_border_inline_end),"border-inline-end-width":makeTransform(transformBorder_border_inline_end),"border-inline-start":makeTransformWithoutSplittingValues(transformBorder_border_inline_start),"border-inline-start-color":makeTransform(transformBorder_border_inline_start),"border-inline-start-style":makeTransform(transformBorder_border_inline_start),"border-inline-start-width":makeTransform(transformBorder_border_inline_start),"border-end-end-radius":makeTransform(transformBorderRadius),"border-end-start-radius":makeTransform(transformBorderRadius),"border-start-end-radius":makeTransform(transformBorderRadius),"border-start-start-radius":makeTransform(transformBorderRadius),"border-color":makeTransform(transformDirectionalShorthands),"border-style":makeTransform(transformDirectionalShorthands),"border-width":makeTransform(transformDirectionalShorthands),transition:makeTransform(transformTransition),"transition-property":makeTransform(transformTransition)}}}postcssLogicalProperties.postcss=!0;export{postcssLogicalProperties as default}; +import r from"postcss-value-parser";var o,n;!function(r){r.Block="block",r.Inline="inline"}(o||(o={})),function(r){r.Start="start",r.End="end"}(n||(n={}));const t={BlockStart:"block-start",BlockEnd:"block-end",InlineStart:"inline-start",InlineEnd:"inline-end"};var e,i;function cloneDeclaration(r,o,n){r.parent&&r.parent.some((r=>"decl"==r.type&&r.prop===n&&r.value===o))||r.cloneBefore({value:o,prop:n})}function parseValueCouple(o){const n=r(o.value).nodes.filter((r=>"space"!==r.type));if(n.length>2){const r=`[postcss-logical] Invalid number of values for ${o.prop}. Found ${n.length} values, expected 1 or 2.`;throw o.error(r)}let t,e;return 1===n.length&&(t=r.stringify(n[0]),e=t),2===n.length&&(t=r.stringify(n[0]),e=r.stringify(n[1])),[t,e]}function transformBorder(r,o){return n=>(cloneDeclaration(n,n.value,`border-${o}-${r}`),!0)}function transformBorderProperty(r,o){return n=>{const[t,e]=o,[i,a]=parseValueCouple(n);return cloneDeclaration(n,i,`border-${t}-${r}`),cloneDeclaration(n,a,`border-${e}-${r}`),!0}}function transformBorderShorthand(r){return o=>(r.forEach((r=>cloneDeclaration(o,o.value,`border-${r}`))),!0)}function transformBorderRadius(r){return o=>{let n;switch(o.prop.toLowerCase()){case"border-start-start-radius":n=`border-${r.inlineIsHorizontal?`${r.block[0]}-${r.inline[0]}`:`${r.inline[0]}-${r.block[0]}`}-radius`;break;case"border-start-end-radius":n=`border-${r.inlineIsHorizontal?`${r.block[0]}-${r.inline[1]}`:`${r.inline[1]}-${r.block[0]}`}-radius`;break;case"border-end-start-radius":n=`border-${r.inlineIsHorizontal?`${r.block[1]}-${r.inline[0]}`:`${r.inline[0]}-${r.block[1]}`}-radius`;break;case"border-end-end-radius":n=`border-${r.inlineIsHorizontal?`${r.block[1]}-${r.inline[1]}`:`${r.inline[1]}-${r.block[1]}`}-radius`;break}return cloneDeclaration(o,o.value,n),!0}}function transformLogicalSize(r){return o=>{const{value:n}=o,t=r.inlineIsHorizontal?"width":"height",e=r.inlineIsHorizontal?"height":"width";return cloneDeclaration(o,n,"block-size"===o.prop?e:t),!0}}function transformOffset(r){return o=>(cloneDeclaration(o,o.value,r),!0)}function transformOffsetShorthand(r){return o=>{const[n,t]=r,[e,i]=parseValueCouple(o);return cloneDeclaration(o,e,n),cloneDeclaration(o,i,t),!0}}function transformSide(r,o){return n=>(cloneDeclaration(n,n.value,`${r}-${o}`),!0)}function transformSideShorthand(r,o){return n=>{const[t,e]=o,[i,a]=parseValueCouple(n);return cloneDeclaration(n,i,`${r}-${t}`),cloneDeclaration(n,a,`${r}-${e}`),!0}}function logicalToPhysical(r,o){const[n,e]=o.block,[i,a]=o.inline;switch(r){case t.BlockStart:return n;case t.BlockEnd:return e;case t.InlineStart:return i;case t.InlineEnd:return a}}function doTransform(o,n,t){const{prop:e,value:i}=o,a=r(i);a.nodes.forEach((r=>{if("word"===r.type){const o=r.value.toLowerCase();n.includes(o)&&(r.value=logicalToPhysical(o,t))}}));const l=a.toString();return l!==i&&(cloneDeclaration(o,l,e),!0)}function directionFlowToAxes(r){switch(r){case e.TopToBottom:return[i.Top,i.Bottom];case e.BottomToTop:return[i.Bottom,i.Top];case e.RightToLeft:return[i.Right,i.Left];case e.LeftToRight:return[i.Left,i.Right]}}!function(r){r.TopToBottom="top-to-bottom",r.BottomToTop="bottom-to-top",r.RightToLeft="right-to-left",r.LeftToRight="left-to-right"}(e||(e={})),function(r){r.Top="top",r.Right="right",r.Bottom="bottom",r.Left="left"}(i||(i={}));const creator=o=>{const a=Object.assign({blockDirection:e.TopToBottom,inlineDirection:e.LeftToRight},o),l=Object.values(e);if(!l.includes(a.blockDirection))throw new Error(`[postcss-logical] "blockDirection" must be one of ${l.join(", ")}`);if(!l.includes(a.inlineDirection))throw new Error(`[postcss-logical] "inlineDirection" must be one of ${l.join(", ")}`);const[s,d]=directionFlowToAxes(a.blockDirection),[c,f]=directionFlowToAxes(a.inlineDirection);if(!Object.values(i).every((r=>[s,d,c,f].includes(r))))throw new Error('[postcss-logical] "blockDirection" and "inlineDirection" must be on separate axes');const u={block:[s,d],inline:[c,f],inlineIsHorizontal:[e.LeftToRight,e.RightToLeft].includes(a.inlineDirection)},makeTransform=r=>(o,{result:n})=>{if(!r)return;let t=!1;try{t=r(o)}catch(r){return void o.warn(n,r.message)}t&&o.remove()};return{postcssPlugin:"postcss-logical",Declaration:{"caption-side":makeTransform((m=u,r=>doTransform(r,Object.values(t),m))),"text-align":makeTransform(u.inlineIsHorizontal?(b=u.inline,o=>{const{prop:t,value:e}=o,i=r(e),[a,l]=b;i.nodes.forEach((r=>{if("word"===r.type){const o=r.value.toLowerCase();if(o===n.End)return void(r.value=l);o===n.Start&&(r.value=a)}}));const s=i.toString();return s!==e&&(cloneDeclaration(o,s,t),!0)}):null),"block-size":makeTransform(transformLogicalSize(u)),"inline-size":makeTransform(transformLogicalSize(u)),"margin-block-start":makeTransform(transformSide("margin",s)),"margin-block-end":makeTransform(transformSide("margin",d)),"margin-inline-start":makeTransform(transformSide("margin",c)),"margin-inline-end":makeTransform(transformSide("margin",f)),"margin-block":makeTransform(transformSideShorthand("margin",u.block)),"margin-inline":makeTransform(transformSideShorthand("margin",u.inline)),"inset-block":makeTransform(transformOffsetShorthand(u.block)),"inset-block-start":makeTransform(transformOffset(s)),"inset-block-end":makeTransform(transformOffset(d)),"inset-inline":makeTransform(transformOffsetShorthand(u.inline)),"inset-inline-start":makeTransform(transformOffset(c)),"inset-inline-end":makeTransform(transformOffset(f)),inset:makeTransform((o=>{const n=r(o.value).nodes.filter((r=>"space"!==r.type&&"comment"!==r.type));if(n.length>4){const r=`[postcss-logical] Invalid number of values for ${o.prop}. Found ${n.length} values, expected up to 4 values.`;throw o.error(r)}const t={top:"",right:"",bottom:"",left:""};return 1===n.length&&(t.top=r.stringify(n[0]),t.right=t.top,t.bottom=t.top,t.left=t.top),2===n.length&&(t.top=r.stringify(n[0]),t.right=r.stringify(n[1]),t.bottom=t.top,t.left=t.right),3===n.length&&(t.top=r.stringify(n[0]),t.right=r.stringify(n[1]),t.left=t.right,t.bottom=r.stringify(n[2])),4===n.length&&(t.top=r.stringify(n[0]),t.right=r.stringify(n[1]),t.bottom=r.stringify(n[2]),t.left=r.stringify(n[3])),Object.keys(t).forEach((r=>{cloneDeclaration(o,t[r],r)})),!0})),"padding-block-start":makeTransform(transformSide("padding",s)),"padding-block-end":makeTransform(transformSide("padding",d)),"padding-inline-start":makeTransform(transformSide("padding",c)),"padding-inline-end":makeTransform(transformSide("padding",f)),"padding-block":makeTransform(transformSideShorthand("padding",u.block)),"padding-inline":makeTransform(transformSideShorthand("padding",u.inline)),"border-block-start-width":makeTransform(transformBorder("width",s)),"border-block-end-width":makeTransform(transformBorder("width",d)),"border-inline-start-width":makeTransform(transformBorder("width",c)),"border-inline-end-width":makeTransform(transformBorder("width",f)),"border-block-width":makeTransform(transformBorderProperty("width",u.block)),"border-inline-width":makeTransform(transformBorderProperty("width",u.inline)),"border-block-start-style":makeTransform(transformBorder("style",s)),"border-block-end-style":makeTransform(transformBorder("style",d)),"border-inline-start-style":makeTransform(transformBorder("style",c)),"border-inline-end-style":makeTransform(transformBorder("style",f)),"border-block-style":makeTransform(transformBorderProperty("style",u.block)),"border-inline-style":makeTransform(transformBorderProperty("style",u.inline)),"border-block-start-color":makeTransform(transformBorder("color",s)),"border-block-end-color":makeTransform(transformBorder("color",d)),"border-inline-start-color":makeTransform(transformBorder("color",c)),"border-inline-end-color":makeTransform(transformBorder("color",f)),"border-block-color":makeTransform(transformBorderProperty("color",u.block)),"border-inline-color":makeTransform(transformBorderProperty("color",u.inline)),"border-block":makeTransform(transformBorderShorthand(u.block)),"border-block-start":makeTransform(transformBorderShorthand([s])),"border-block-end":makeTransform(transformBorderShorthand([d])),"border-inline":makeTransform(transformBorderShorthand(u.inline)),"border-inline-start":makeTransform(transformBorderShorthand([c])),"border-inline-end":makeTransform(transformBorderShorthand([f])),"border-start-start-radius":makeTransform(transformBorderRadius(u)),"border-start-end-radius":makeTransform(transformBorderRadius(u)),"border-end-start-radius":makeTransform(transformBorderRadius(u)),"border-end-end-radius":makeTransform(transformBorderRadius(u))}};var b,m};creator.postcss=!0;export{creator as default}; diff --git a/plugins/postcss-logical/dist/lib/clone-declaration.d.ts b/plugins/postcss-logical/dist/lib/clone-declaration.d.ts new file mode 100644 index 000000000..1503bf6f1 --- /dev/null +++ b/plugins/postcss-logical/dist/lib/clone-declaration.d.ts @@ -0,0 +1,2 @@ +import type { Declaration } from 'postcss'; +export declare function cloneDeclaration(declaration: Declaration, value: string, prop: string): void; diff --git a/plugins/postcss-logical/dist/lib/transform-borders.d.ts b/plugins/postcss-logical/dist/lib/transform-borders.d.ts new file mode 100644 index 000000000..7ae12d185 --- /dev/null +++ b/plugins/postcss-logical/dist/lib/transform-borders.d.ts @@ -0,0 +1,6 @@ +import type { Declaration } from 'postcss'; +import { DirectionConfig } from './types'; +export declare function transformBorder(borderSetting: string, side: string): (declaration: Declaration) => boolean; +export declare function transformBorderProperty(borderSetting: string, side: [string, string]): (declaration: Declaration) => boolean; +export declare function transformBorderShorthand(side: [string] | [string, string]): (declaration: Declaration) => boolean; +export declare function transformBorderRadius(config: DirectionConfig): (declaration: Declaration) => boolean; diff --git a/plugins/postcss-logical/dist/lib/transform-inset.d.ts b/plugins/postcss-logical/dist/lib/transform-inset.d.ts new file mode 100644 index 000000000..10ab4ce21 --- /dev/null +++ b/plugins/postcss-logical/dist/lib/transform-inset.d.ts @@ -0,0 +1,2 @@ +import type { Declaration } from 'postcss'; +export declare function transformInset(): (declaration: Declaration) => boolean; diff --git a/plugins/postcss-logical/dist/lib/transform-logical-size.d.ts b/plugins/postcss-logical/dist/lib/transform-logical-size.d.ts new file mode 100644 index 000000000..3c4b8545c --- /dev/null +++ b/plugins/postcss-logical/dist/lib/transform-logical-size.d.ts @@ -0,0 +1,3 @@ +import type { Declaration } from 'postcss'; +import { DirectionConfig } from './types'; +export declare function transformLogicalSize(directionConfig: DirectionConfig): (declaration: Declaration) => boolean; diff --git a/plugins/postcss-logical/dist/lib/transform-offset.d.ts b/plugins/postcss-logical/dist/lib/transform-offset.d.ts new file mode 100644 index 000000000..16122b64c --- /dev/null +++ b/plugins/postcss-logical/dist/lib/transform-offset.d.ts @@ -0,0 +1,3 @@ +import type { Declaration } from 'postcss'; +export declare function transformOffset(prop: string): (declaration: Declaration) => boolean; +export declare function transformOffsetShorthand(side: [string, string]): (declaration: Declaration) => boolean; diff --git a/plugins/postcss-logical/dist/lib/transform-side.d.ts b/plugins/postcss-logical/dist/lib/transform-side.d.ts new file mode 100644 index 000000000..e49e46b14 --- /dev/null +++ b/plugins/postcss-logical/dist/lib/transform-side.d.ts @@ -0,0 +1,3 @@ +import type { Declaration } from 'postcss'; +export declare function transformSide(prop: string, side: string): (declaration: Declaration) => boolean; +export declare function transformSideShorthand(prop: string, side: [string, string]): (declaration: Declaration) => boolean; diff --git a/plugins/postcss-logical/dist/lib/transform-text-align.d.ts b/plugins/postcss-logical/dist/lib/transform-text-align.d.ts new file mode 100644 index 000000000..0ef11a152 --- /dev/null +++ b/plugins/postcss-logical/dist/lib/transform-text-align.d.ts @@ -0,0 +1,2 @@ +import type { Declaration } from 'postcss'; +export declare function transformTextAlign(inlineValues: [string, string]): (declaration: Declaration) => boolean; diff --git a/plugins/postcss-logical/dist/lib/transform-value.d.ts b/plugins/postcss-logical/dist/lib/transform-value.d.ts new file mode 100644 index 000000000..7bec316fe --- /dev/null +++ b/plugins/postcss-logical/dist/lib/transform-value.d.ts @@ -0,0 +1,3 @@ +import type { Declaration } from 'postcss'; +import { DirectionConfig } from './types'; +export declare function transformValue(config: DirectionConfig): (declaration: Declaration) => boolean; diff --git a/plugins/postcss-logical/dist/lib/types.d.ts b/plugins/postcss-logical/dist/lib/types.d.ts new file mode 100644 index 000000000..7f27fd46e --- /dev/null +++ b/plugins/postcss-logical/dist/lib/types.d.ts @@ -0,0 +1,31 @@ +export declare enum Direction { + Block = "block", + Inline = "inline" +} +export declare enum DirectionValue { + Start = "start", + End = "end" +} +export declare const DirectionValues: { + BlockStart: string; + BlockEnd: string; + InlineStart: string; + InlineEnd: string; +}; +export declare enum DirectionFlow { + TopToBottom = "top-to-bottom", + BottomToTop = "bottom-to-top", + RightToLeft = "right-to-left", + LeftToRight = "left-to-right" +} +export declare enum Axes { + Top = "top", + Right = "right", + Bottom = "bottom", + Left = "left" +} +export type DirectionConfig = { + [Direction.Block]: [Axes, Axes]; + [Direction.Inline]: [Axes, Axes]; + inlineIsHorizontal: boolean; +}; diff --git a/plugins/postcss-logical/dist/utils/direction-flow-to-axes.d.ts b/plugins/postcss-logical/dist/utils/direction-flow-to-axes.d.ts new file mode 100644 index 000000000..2652d71d8 --- /dev/null +++ b/plugins/postcss-logical/dist/utils/direction-flow-to-axes.d.ts @@ -0,0 +1,2 @@ +import { DirectionFlow, Axes } from '../lib/types'; +export declare function directionFlowToAxes(directionFlow: DirectionFlow): [Axes, Axes]; diff --git a/plugins/postcss-logical/dist/utils/logical-to-physical.d.ts b/plugins/postcss-logical/dist/utils/logical-to-physical.d.ts new file mode 100644 index 000000000..764ee732c --- /dev/null +++ b/plugins/postcss-logical/dist/utils/logical-to-physical.d.ts @@ -0,0 +1,2 @@ +import { DirectionConfig } from '../lib/types'; +export declare function logicalToPhysical(logical: string, config: DirectionConfig): string; diff --git a/plugins/postcss-logical/dist/utils/parse-value-couple.d.ts b/plugins/postcss-logical/dist/utils/parse-value-couple.d.ts new file mode 100644 index 000000000..124566572 --- /dev/null +++ b/plugins/postcss-logical/dist/utils/parse-value-couple.d.ts @@ -0,0 +1,2 @@ +import type { Declaration } from 'postcss'; +export declare function parseValueCouple(declaration: Declaration): [string, string]; diff --git a/plugins/postcss-logical/docs/README.md b/plugins/postcss-logical/docs/README.md new file mode 100644 index 000000000..107098e7a --- /dev/null +++ b/plugins/postcss-logical/docs/README.md @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + +
+ +[] lets you use logical, rather than physical, direction and dimension mappings in CSS, following the [CSS Logical Properties and Values] specification. + +```pcss + + +/* becomes */ + + +``` + + + + + +## Options + +### blockDirection & inlineDirection + +The `blockDirection` and `inlineDirection` options allow you to specify the direction of the block and inline axes. The default values are `top-to-bottom` and `left-to-right` respectively which would match any latin language. + +You might want to tweak these values if you are using a different writing system, such as Arabic, Hebrew or Chinese for example. + +```js +({ + blockDirection: 'right-to-left', + inlineDirection: 'top-to-bottom' +}) +``` + +```pcss + + +/* becomes */ + + +``` + +Each direction must be one of the following: + +- `top-to-bottom` +- `bottom-to-top` +- `left-to-right` +- `right-to-left` + +You can't mix two vertical directions or two horizontal directions so for example `top-to-bottom` and `right-to-left` are valid, but `top-to-bottom` and `bottom-to-top` are not. + +Please do note that `text-align` won't be transformed if `inlineDirection` becomes vertical. + + +[CSS Logical Properties and Values]: diff --git a/plugins/postcss-logical/package.json b/plugins/postcss-logical/package.json index dd84b54ec..a973578d2 100644 --- a/plugins/postcss-logical/package.json +++ b/plugins/postcss-logical/package.json @@ -2,7 +2,21 @@ "name": "postcss-logical", "description": "Use logical properties and values in CSS", "version": "5.0.4", - "author": "Jonathan Neal ", + "contributors": [ + { + "name": "Antonio Laguna", + "email": "antonio@laguna.es", + "url": "https://antonio.laguna.es" + }, + { + "name": "Romain Menke", + "email": "romainmenke@gmail.com" + }, + { + "name": "Jonathan Neal", + "email": "jonathantneal@hotmail.com" + } + ], "license": "CC0-1.0", "funding": { "type": "opencollective", @@ -13,6 +27,7 @@ }, "main": "dist/index.cjs", "module": "dist/index.mjs", + "types": "dist/index.d.ts", "exports": { ".": { "import": "./dist/index.mjs", @@ -26,6 +41,9 @@ "README.md", "dist" ], + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, "peerDependencies": { "postcss": "^8.4" }, @@ -33,7 +51,7 @@ "prebuild": "npm run clean", "build": "rollup -c ../../rollup/default.mjs", "clean": "node -e \"fs.rmSync('./dist', { recursive: true, force: true }); fs.mkdirSync('./dist');\"", - "docs": "node ../../.github/bin/generate-docs/install.mjs", + "docs": "node ../../.github/bin/generate-docs/install.mjs && node ../../.github/bin/generate-docs/readme.mjs", "lint": "npm run lint:eslint && npm run lint:package-json", "lint:eslint": "eslint ./src --ext .js --ext .ts --ext .mjs --no-error-on-unmatched-pattern", "lint:package-json": "node ../../.github/bin/format-package-json.mjs", @@ -53,13 +71,11 @@ "align", "block", "border", - "clear", "css", "dir", "directional", "directions", "end", - "float", "flow", "inline", "logical", @@ -78,8 +94,10 @@ "values" ], "csstools": { + "cssdbId": "logical-properties-and-values", "exportName": "postcssLogical", - "humanReadableName": "PostCSS Logical Properties and Values" + "humanReadableName": "PostCSS Logical Properties and Values", + "specUrl": "https://www.w3.org/TR/css-logical-1/" }, "volta": { "extends": "../../package.json" diff --git a/plugins/postcss-logical/src/index.js b/plugins/postcss-logical/src/index.js deleted file mode 100644 index 84c33c890..000000000 --- a/plugins/postcss-logical/src/index.js +++ /dev/null @@ -1,142 +0,0 @@ -import transformBorder from './lib/transform-border'; -import transformBorderRadius from './lib/transform-border-radius'; -import transformDirectionalShorthands from './lib/transform-directional-shorthands'; -import transformFloat from './lib/transform-float'; -import transformInset from './lib/transform-inset'; -import transformResize from './lib/transform-resize'; -import transformSide from './lib/transform-side'; -import transformSize from './lib/transform-size'; -import transformTextAlign from './lib/transform-text-align'; -import transformTransition from './lib/transform-transition'; -import { splitBySpace } from './lib/split'; -import { hasKeyframesAtRuleAncestor } from './lib/has-keyframes-atrule-ancestor'; - -// plugin -function postcssLogicalProperties(opts) { - opts = Object(opts); - - const preserve = Boolean(opts.preserve); - const dir = !preserve && typeof opts.dir === 'string' - ? /^rtl$/i.test(opts.dir) - ? 'rtl' - : 'ltr' - : false; - - const makeTransform = (transform) => { - return (decl) => { - if (hasKeyframesAtRuleAncestor(decl)) { - return; - } - const parent = decl.parent; - const values = splitBySpace(decl.value, true); - transform(decl, values, dir, preserve); - if (!parent.nodes.length) { - parent.remove(); - } - }; - }; - - const makeTransformWithoutSplittingValues = (transform) => { - return (decl) => { - if (hasKeyframesAtRuleAncestor(decl)) { - return; - } - const parent = decl.parent; - const values = [decl.value]; - transform(decl, values, dir, preserve); - if (!parent.nodes.length) { - parent.remove(); - } - }; - }; - - return { - postcssPlugin: 'postcss-logical-properties', - Declaration: { - // Flow-Relative Values - 'clear': makeTransform(transformFloat), - 'float': makeTransform(transformFloat), - 'resize': makeTransform(transformResize), - 'text-align': makeTransform(transformTextAlign), - - // Logical Height and Logical Width - 'block-size': makeTransform(transformSize), - 'max-block-size': makeTransform(transformSize), - 'min-block-size': makeTransform(transformSize), - 'inline-size': makeTransform(transformSize), - 'max-inline-size': makeTransform(transformSize), - 'min-inline-size': makeTransform(transformSize), - - // Flow-relative Margins - 'margin': makeTransform(transformDirectionalShorthands), - 'margin-inline': makeTransform(transformSide['inline']), - 'margin-inline-end': makeTransform(transformSide['inline-end']), - 'margin-inline-start': makeTransform(transformSide['inline-start']), - 'margin-block': makeTransform(transformSide['block']), - 'margin-block-end': makeTransform(transformSide['block-end']), - 'margin-block-start': makeTransform(transformSide['block-start']), - - // Flow-relative Offsets - 'inset': makeTransform(transformInset), - 'inset-inline': makeTransform(transformSide['inline']), - 'inset-inline-end': makeTransform(transformSide['inline-end']), - 'inset-inline-start': makeTransform(transformSide['inline-start']), - 'inset-block': makeTransform(transformSide['block']), - 'inset-block-end': makeTransform(transformSide['block-end']), - 'inset-block-start': makeTransform(transformSide['block-start']), - - // Flow-relative Padding - 'padding': makeTransform(transformDirectionalShorthands), - 'padding-inline': makeTransform(transformSide['inline']), - 'padding-inline-end': makeTransform(transformSide['inline-end']), - 'padding-inline-start': makeTransform(transformSide['inline-start']), - 'padding-block': makeTransform(transformSide['block']), - 'padding-block-end': makeTransform(transformSide['block-end']), - 'padding-block-start': makeTransform(transformSide['block-start']), - - // Flow-relative Borders - 'border-block': makeTransformWithoutSplittingValues(transformBorder['border-block']), - 'border-block-color': makeTransform(transformBorder['border-block']), - 'border-block-style': makeTransform(transformBorder['border-block']), - 'border-block-width': makeTransform(transformBorder['border-block']), - 'border-block-end': makeTransformWithoutSplittingValues(transformBorder['border-block-end']), - 'border-block-end-color': makeTransform(transformBorder['border-block-end']), - 'border-block-end-style': makeTransform(transformBorder['border-block-end']), - 'border-block-end-width': makeTransform(transformBorder['border-block-end']), - 'border-block-start': makeTransformWithoutSplittingValues(transformBorder['border-block-start']), - 'border-block-start-color': makeTransform(transformBorder['border-block-start']), - 'border-block-start-style': makeTransform(transformBorder['border-block-start']), - 'border-block-start-width': makeTransform(transformBorder['border-block-start']), - 'border-inline': makeTransformWithoutSplittingValues(transformBorder['border-inline']), - 'border-inline-color': makeTransform(transformBorder['border-inline']), - 'border-inline-style': makeTransform(transformBorder['border-inline']), - 'border-inline-width': makeTransform(transformBorder['border-inline']), - 'border-inline-end': makeTransformWithoutSplittingValues(transformBorder['border-inline-end']), - 'border-inline-end-color': makeTransform(transformBorder['border-inline-end']), - 'border-inline-end-style': makeTransform(transformBorder['border-inline-end']), - 'border-inline-end-width': makeTransform(transformBorder['border-inline-end']), - 'border-inline-start': makeTransformWithoutSplittingValues(transformBorder['border-inline-start']), - 'border-inline-start-color': makeTransform(transformBorder['border-inline-start']), - 'border-inline-start-style': makeTransform(transformBorder['border-inline-start']), - 'border-inline-start-width': makeTransform(transformBorder['border-inline-start']), - - // Flow-relative Corner Rounding - 'border-end-end-radius': makeTransform(transformBorderRadius), - 'border-end-start-radius': makeTransform(transformBorderRadius), - 'border-start-end-radius': makeTransform(transformBorderRadius), - 'border-start-start-radius': makeTransform(transformBorderRadius), - - // Four-Directional Shorthand Border Properties - 'border-color': makeTransform(transformDirectionalShorthands), - 'border-style': makeTransform(transformDirectionalShorthands), - 'border-width': makeTransform(transformDirectionalShorthands), - - // Transition helpers - 'transition': makeTransform(transformTransition), - 'transition-property': makeTransform(transformTransition), - }, - }; -} -postcssLogicalProperties.postcss = true; - -export default postcssLogicalProperties; diff --git a/plugins/postcss-logical/src/index.ts b/plugins/postcss-logical/src/index.ts new file mode 100644 index 000000000..983e33054 --- /dev/null +++ b/plugins/postcss-logical/src/index.ts @@ -0,0 +1,248 @@ +import type { Declaration, PluginCreator, Result } from 'postcss'; +import { Axes, DirectionConfig, DirectionFlow } from './lib/types'; +import { + transformBorder, + transformBorderProperty, + transformBorderShorthand, + transformBorderRadius, +} from './lib/transform-borders'; +import { transformLogicalSize } from './lib/transform-logical-size'; +import { + transformOffset, + transformOffsetShorthand, +} from './lib/transform-offset'; +import { transformInset } from './lib/transform-inset'; +import { + transformSide, + transformSideShorthand, +} from './lib/transform-side'; +import { transformTextAlign } from './lib/transform-text-align'; +import { transformValue } from './lib/transform-value'; +import { directionFlowToAxes } from './utils/direction-flow-to-axes'; + +/** postcss-logical plugin options */ +export type pluginOptions = { + /** Sets the direction for block. default: top-to-bottom */ + blockDirection?: DirectionFlow, + /** Sets the direction for inline. default: left-to-right */ + inlineDirection?: DirectionFlow, +}; + +const creator: PluginCreator = (opts?: pluginOptions) => { + const options = Object.assign( + // Default options + { + blockDirection: DirectionFlow.TopToBottom, + inlineDirection: DirectionFlow.LeftToRight, + }, + // Provided options + opts, + ); + const directionValues = Object.values(DirectionFlow); + + if (!directionValues.includes(options.blockDirection)) { + throw new Error(`[postcss-logical] "blockDirection" must be one of ${directionValues.join(', ')}`); + } + + if (!directionValues.includes(options.inlineDirection)) { + throw new Error(`[postcss-logical] "inlineDirection" must be one of ${directionValues.join(', ')}`); + } + + const [blockStart, blockEnd] = directionFlowToAxes(options.blockDirection); + const [inlineStart, inlineEnd] = directionFlowToAxes(options.inlineDirection); + const allAxesCovered = Object.values(Axes) + .every((axis) => [blockStart, blockEnd, inlineStart, inlineEnd].includes(axis)); + + if (!allAxesCovered) { + throw new Error('[postcss-logical] "blockDirection" and "inlineDirection" must be on separate axes'); + } + + const directionConfig: DirectionConfig = { + block: [blockStart, blockEnd], + inline: [inlineStart, inlineEnd], + inlineIsHorizontal: [DirectionFlow.LeftToRight, DirectionFlow.RightToLeft].includes(options.inlineDirection), + }; + + const makeTransform = (transform: (decl: Declaration) => boolean | null) => { + return ( + decl: Declaration, + { result }: { result: Result }, + ) => { + if (!transform) { + return; + } + + let transformed = false; + + try { + transformed = transform(decl); + } catch (error) { + decl.warn(result, error.message); + return; + } + + if (!transformed) { + return; + } + + decl.remove(); + }; + }; + + return { + postcssPlugin: 'postcss-logical', + Declaration: { + // 2.1 Caption + 'caption-side': makeTransform(transformValue(directionConfig)), + // 2.3 Text Align + 'text-align': makeTransform( + directionConfig.inlineIsHorizontal + ? transformTextAlign(directionConfig.inline) + : null, + ), + // 4.1 Block Size and Inline Size + 'block-size': makeTransform(transformLogicalSize(directionConfig)), + 'inline-size': makeTransform(transformLogicalSize(directionConfig)), + // 4.2 Margins + 'margin-block-start': makeTransform( + transformSide('margin', blockStart), + ), + 'margin-block-end': makeTransform( + transformSide('margin', blockEnd), + ), + 'margin-inline-start': makeTransform( + transformSide('margin', inlineStart), + ), + 'margin-inline-end': makeTransform( + transformSide('margin', inlineEnd), + ), + 'margin-block': makeTransform( + transformSideShorthand('margin', directionConfig.block), + ), + 'margin-inline': makeTransform( + transformSideShorthand('margin', directionConfig.inline), + ), + // 4.3 Offsets + 'inset-block': makeTransform(transformOffsetShorthand(directionConfig.block)), + 'inset-block-start': makeTransform(transformOffset(blockStart)), + 'inset-block-end': makeTransform(transformOffset(blockEnd)), + 'inset-inline': makeTransform(transformOffsetShorthand(directionConfig.inline)), + 'inset-inline-start': makeTransform(transformOffset(inlineStart)), + 'inset-inline-end': makeTransform(transformOffset(inlineEnd)), + 'inset': makeTransform(transformInset()), + // 4.4 Paddings + 'padding-block-start': makeTransform( + transformSide('padding', blockStart), + ), + 'padding-block-end': makeTransform( + transformSide('padding', blockEnd), + ), + 'padding-inline-start': makeTransform( + transformSide('padding', inlineStart), + ), + 'padding-inline-end': makeTransform( + transformSide('padding', inlineEnd), + ), + 'padding-block': makeTransform( + transformSideShorthand('padding', directionConfig.block), + ), + 'padding-inline': makeTransform( + transformSideShorthand('padding', directionConfig.inline), + ), + // 4.5 Borders + // 4.5.1 Border Width + 'border-block-start-width': makeTransform( + transformBorder('width', blockStart), + ), + 'border-block-end-width': makeTransform( + transformBorder('width', blockEnd), + ), + 'border-inline-start-width': makeTransform( + transformBorder('width', inlineStart), + ), + 'border-inline-end-width': makeTransform( + transformBorder('width', inlineEnd), + ), + 'border-block-width': makeTransform( + transformBorderProperty('width', directionConfig.block), + ), + 'border-inline-width': makeTransform( + transformBorderProperty('width', directionConfig.inline), + ), + // 4.5.2 Border Style + 'border-block-start-style': makeTransform( + transformBorder('style', blockStart), + ), + 'border-block-end-style': makeTransform( + transformBorder('style', blockEnd), + ), + 'border-inline-start-style': makeTransform( + transformBorder('style', inlineStart), + ), + 'border-inline-end-style': makeTransform( + transformBorder('style', inlineEnd), + ), + 'border-block-style': makeTransform( + transformBorderProperty('style', directionConfig.block), + ), + 'border-inline-style': makeTransform( + transformBorderProperty('style', directionConfig.inline), + ), + // 4.5.3 Border Color + 'border-block-start-color': makeTransform( + transformBorder('color', blockStart), + ), + 'border-block-end-color': makeTransform( + transformBorder('color', blockEnd), + ), + 'border-inline-start-color': makeTransform( + transformBorder('color', inlineStart), + ), + 'border-inline-end-color': makeTransform( + transformBorder('color', inlineEnd), + ), + 'border-block-color': makeTransform( + transformBorderProperty('color', directionConfig.block), + ), + 'border-inline-color': makeTransform( + transformBorderProperty('color', directionConfig.inline), + ), + // 4.5.4 Border Shorthand + 'border-block': makeTransform( + transformBorderShorthand(directionConfig.block), + ), + 'border-block-start': makeTransform( + transformBorderShorthand([blockStart]), + ), + 'border-block-end': makeTransform( + transformBorderShorthand([blockEnd]), + ), + 'border-inline': makeTransform( + transformBorderShorthand(directionConfig.inline), + ), + 'border-inline-start': makeTransform( + transformBorderShorthand([inlineStart]), + ), + 'border-inline-end': makeTransform( + transformBorderShorthand([inlineEnd]), + ), + // 4.6 Border Radius + 'border-start-start-radius': makeTransform( + transformBorderRadius(directionConfig), + ), + 'border-start-end-radius': makeTransform( + transformBorderRadius(directionConfig), + ), + 'border-end-start-radius': makeTransform( + transformBorderRadius(directionConfig), + ), + 'border-end-end-radius': makeTransform( + transformBorderRadius(directionConfig), + ), + }, + }; +}; + +creator.postcss = true; + +export default creator; diff --git a/plugins/postcss-logical/src/lib/clone-decl.js b/plugins/postcss-logical/src/lib/clone-decl.js deleted file mode 100644 index f864a7710..000000000 --- a/plugins/postcss-logical/src/lib/clone-decl.js +++ /dev/null @@ -1,7 +0,0 @@ -import matchSide from './match-side'; -import matchInsetPrefix from './match-inset-prefix'; - -export default (decl, suffix, value) => decl.cloneBefore({ - prop: `${decl.prop.replace(matchSide, '$1')}${suffix}`.replace(matchInsetPrefix, ''), - value, -}); diff --git a/plugins/postcss-logical/src/lib/clone-declaration.ts b/plugins/postcss-logical/src/lib/clone-declaration.ts new file mode 100644 index 000000000..b738ea4a9 --- /dev/null +++ b/plugins/postcss-logical/src/lib/clone-declaration.ts @@ -0,0 +1,15 @@ +import type { Declaration } from 'postcss'; + +export function cloneDeclaration( + declaration: Declaration, + value: string, + prop: string, +): void { + if (declaration.parent && declaration.parent.some((x) => { + return x.type == 'decl' && x.prop === prop && x.value === value; + })) { + return; + } + + declaration.cloneBefore({ value, prop }); +} diff --git a/plugins/postcss-logical/src/lib/clone-rule.js b/plugins/postcss-logical/src/lib/clone-rule.js deleted file mode 100644 index 64f554a43..000000000 --- a/plugins/postcss-logical/src/lib/clone-rule.js +++ /dev/null @@ -1,11 +0,0 @@ -import postcss from 'postcss'; - -export default (decl, dir) => { - const rule = Object(decl.parent).type === 'rule' ? decl.parent.cloneBefore({ - raws: {}, - }).removeAll() : postcss.rule({ selector: '&' }); - - rule.selectors = rule.selectors.map(selector => `${selector}:dir(${dir})`); - - return rule; -}; diff --git a/plugins/postcss-logical/src/lib/has-keyframes-atrule-ancestor.js b/plugins/postcss-logical/src/lib/has-keyframes-atrule-ancestor.js deleted file mode 100644 index 4ec394e63..000000000 --- a/plugins/postcss-logical/src/lib/has-keyframes-atrule-ancestor.js +++ /dev/null @@ -1,17 +0,0 @@ -export function hasKeyframesAtRuleAncestor(node) { - let parent = node.parent; - while (parent) { - if (parent.type !== 'atrule') { - parent = parent.parent; - continue; - } - - if (parent.name === 'keyframes') { - return true; - } - - parent = parent.parent; - } - - return false; -} diff --git a/plugins/postcss-logical/src/lib/match-inset-prefix.js b/plugins/postcss-logical/src/lib/match-inset-prefix.js deleted file mode 100644 index f0449be6d..000000000 --- a/plugins/postcss-logical/src/lib/match-inset-prefix.js +++ /dev/null @@ -1 +0,0 @@ -export default /^inset-/i; diff --git a/plugins/postcss-logical/src/lib/match-side.js b/plugins/postcss-logical/src/lib/match-side.js deleted file mode 100644 index 19b557e5a..000000000 --- a/plugins/postcss-logical/src/lib/match-side.js +++ /dev/null @@ -1 +0,0 @@ -export default /^(inset|margin|padding)(?:-(block|block-start|block-end|inline|inline-start|inline-end|start|end))$/i; diff --git a/plugins/postcss-logical/src/lib/match-size.js b/plugins/postcss-logical/src/lib/match-size.js deleted file mode 100644 index f53000b47..000000000 --- a/plugins/postcss-logical/src/lib/match-size.js +++ /dev/null @@ -1 +0,0 @@ -export default /^(min-|max-)?(block|inline)-(size)$/i; diff --git a/plugins/postcss-logical/src/lib/reduce-values.js b/plugins/postcss-logical/src/lib/reduce-values.js deleted file mode 100644 index 64adf0413..000000000 --- a/plugins/postcss-logical/src/lib/reduce-values.js +++ /dev/null @@ -1,20 +0,0 @@ -export default values => { - const reducedValues = values.slice(); - - // reduce [A, B, C, B] to [A, B, C] - if (reducedValues.length === 4 && reducedValues[3] === reducedValues[1]) { - reducedValues.pop(); - } - - // reduce [A, B, A] to [A, B] - if (reducedValues.length === 3 && reducedValues[2] === reducedValues[0]) { - reducedValues.pop(); - } - - // reduce [A, A] to [A] - if (reducedValues.length === 2 && reducedValues[1] === reducedValues[0]) { - reducedValues.pop(); - } - - return reducedValues; -}; diff --git a/plugins/postcss-logical/src/lib/split.js b/plugins/postcss-logical/src/lib/split.js deleted file mode 100644 index 8754d5a0a..000000000 --- a/plugins/postcss-logical/src/lib/split.js +++ /dev/null @@ -1,56 +0,0 @@ -export function splitByComma(string, isTrimmed) { - return splitByRegExp(string, /^,$/, isTrimmed); -} - -export function splitBySpace(string, isTrimmed) { - return splitByRegExp(string, /^\s$/, isTrimmed); -} - -export function splitBySlash(string, isTrimmed) { - return splitByRegExp(string, /^\/$/, isTrimmed); -} - -function splitByRegExp(string, re, isTrimmed) { - const array = []; - let buffer = ''; - let split = false; - let func = 0; - let i = -1; - - while (++i < string.length) { - const char = string[i]; - - if (char === '(') { - func += 1; - } else if (char === ')') { - if (func > 0) { - func -= 1; - } - } else if (func === 0) { - if (re.test(char)) { - split = true; - } - } - - if (split) { - if (!isTrimmed || buffer.trim()) { - array.push(isTrimmed ? buffer.trim() : buffer); - } - - if (!isTrimmed) { - array.push(char); - } - - buffer = ''; - split = false; - } else { - buffer += char; - } - } - - if (buffer !== '') { - array.push(isTrimmed ? buffer.trim() : buffer); - } - - return array; -} diff --git a/plugins/postcss-logical/src/lib/transform-border-radius.js b/plugins/postcss-logical/src/lib/transform-border-radius.js deleted file mode 100644 index 8efeee4dd..000000000 --- a/plugins/postcss-logical/src/lib/transform-border-radius.js +++ /dev/null @@ -1,41 +0,0 @@ -import cloneRule from './clone-rule'; - -const logicalRadii = /^(border-)(end-end|end-start|start-end|start-start)(-radius)$/i; -const ltrRadii = { 'end-end': 'bottom-right', 'end-start': 'bottom-left', 'start-end': 'top-right', 'start-start': 'top-left' }; -const rtlRadii = { 'end-end': 'bottom-left', 'end-start': 'bottom-right', 'start-end': 'top-left', 'start-start': 'top-right' }; - -export default (decl, values, dir, preserve) => { - if (dir === 'ltr') { - lDecl(decl); - clean(decl, preserve); - return; - } - - if (dir === 'rtl') { - rDecl(decl); - clean(decl, preserve); - return; - } - - cloneRule(decl, 'ltr').append(lDecl(decl)); - cloneRule(decl, 'rtl').append(rDecl(decl)); - clean(decl, preserve); -}; - -function lDecl(decl) { - return decl.cloneBefore({ - prop: decl.prop.replace(logicalRadii, ($, prefix, direction, suffix) => `${prefix}${ltrRadii[direction]}${suffix}`), - }); -} - -function rDecl(decl) { - return decl.cloneBefore({ - prop: decl.prop.replace(logicalRadii, ($, prefix, direction, suffix) => `${prefix}${rtlRadii[direction]}${suffix}`), - }); -} - -function clean(decl, preserve) { - if (!preserve) { - decl.remove(); - } -} diff --git a/plugins/postcss-logical/src/lib/transform-border.js b/plugins/postcss-logical/src/lib/transform-border.js deleted file mode 100644 index 07acb826f..000000000 --- a/plugins/postcss-logical/src/lib/transform-border.js +++ /dev/null @@ -1,145 +0,0 @@ -import cloneRule from './clone-rule'; - -const matchLogicalBorderSide = /^border-(block|block-start|block-end|inline|inline-start|inline-end)(-(width|style|color))?$/i; - -export default { - // border-block - 'border-block': (decl, values, dir, preserve) => { - decl.cloneBefore({ - prop: `border-top${decl.prop.replace(matchLogicalBorderSide, '$2')}`, - value: values[0], - }); - decl.cloneBefore({ - prop: `border-bottom${decl.prop.replace(matchLogicalBorderSide, '$2')}`, - value: values[1] || values[0], - }); - clean(decl, preserve); - }, - - // border-block-start - 'border-block-start': (decl, values, dir, preserve) => { - decl.cloneBefore({ - prop: `border-top${decl.prop.replace(matchLogicalBorderSide, '$2')}`, - }); - clean(decl, preserve); - }, - - // border-block-end - 'border-block-end': (decl, values, dir, preserve) => { - decl.cloneBefore({ - prop: `border-bottom${decl.prop.replace(matchLogicalBorderSide, '$2')}`, - }); - clean(decl, preserve); - }, - - // border-inline - 'border-inline': (decl, values, dir, preserve) => { - const ltrDecls = () => { - return [ - decl.cloneBefore({ - prop: `border-left${decl.prop.replace(matchLogicalBorderSide, '$2')}`, - value: values[0], - }), - decl.cloneBefore({ - prop: `border-right${decl.prop.replace(matchLogicalBorderSide, '$2')}`, - value: values[1] || values[0], - }), - ]; - }; - - const rtlDecls = () => { - return [ - decl.clone({ - prop: `border-right${decl.prop.replace(matchLogicalBorderSide, '$2')}`, - value: values[0], - }), - decl.clone({ - prop: `border-left${decl.prop.replace(matchLogicalBorderSide, '$2')}`, - value: values[1] || values[0], - }), - ]; - }; - - const isLTR = 1 === values.length || 2 === values.length && values[0] === values[1]; - if (isLTR || dir === 'ltr') { - ltrDecls(); - clean(decl, preserve); - return; - } else if (dir === 'rtl') { - rtlDecls(); - clean(decl, preserve); - return; - } else { - cloneRule(decl, 'ltr').append(ltrDecls()); - cloneRule(decl, 'rtl').append(rtlDecls()); - clean(decl, preserve); - return; - } - }, - - // border-inline-start - 'border-inline-start': (decl, values, dir, preserve) => { - const ltrDecl = () => { - return decl.cloneBefore({ - prop: `border-left${decl.prop.replace(matchLogicalBorderSide, '$2')}`, - }); - }; - - const rtlDecl = () => { - return decl.cloneBefore({ - prop: `border-right${decl.prop.replace(matchLogicalBorderSide, '$2')}`, - }); - }; - - if (dir === 'ltr') { - ltrDecl(); - clean(decl, preserve); - return; - } else if (dir === 'rtl') { - rtlDecl(); - clean(decl, preserve); - return; - } else { - cloneRule(decl, 'ltr').append(ltrDecl()); - cloneRule(decl, 'rtl').append(rtlDecl()); - clean(decl, preserve); - return; - } - }, - - // border-inline-end - 'border-inline-end': (decl, values, dir, preserve) => { - const ltrDecl = () => { - return decl.cloneBefore({ - prop: `border-right${decl.prop.replace(matchLogicalBorderSide, '$2')}`, - }); - }; - - const rtlDecl = () => { - return decl.cloneBefore({ - prop: `border-left${decl.prop.replace(matchLogicalBorderSide, '$2')}`, - }); - }; - - if (dir === 'ltr') { - ltrDecl(); - clean(decl, preserve); - return; - } else if (dir === 'rtl') { - rtlDecl(); - clean(decl, preserve); - return; - } else { - cloneRule(decl, 'ltr').append(ltrDecl()); - cloneRule(decl, 'rtl').append(rtlDecl()); - clean(decl, preserve); - return; - } - }, -}; - -function clean(decl, preserve) { - if (!preserve) { - decl.remove(); - } -} diff --git a/plugins/postcss-logical/src/lib/transform-borders.ts b/plugins/postcss-logical/src/lib/transform-borders.ts new file mode 100644 index 000000000..fa8d7b631 --- /dev/null +++ b/plugins/postcss-logical/src/lib/transform-borders.ts @@ -0,0 +1,108 @@ +import type { Declaration } from 'postcss'; +import { cloneDeclaration } from './clone-declaration'; +import { parseValueCouple } from '../utils/parse-value-couple'; +import { DirectionConfig } from './types'; + +export function transformBorder( + borderSetting: string, + side: string, +): (declaration: Declaration) => boolean { + return (declaration: Declaration) => { + cloneDeclaration( + declaration, + declaration.value, + `border-${side}-${borderSetting}`, + ); + + return true; + }; +} + +export function transformBorderProperty( + borderSetting: string, + side: [string, string], +): (declaration: Declaration) => boolean { + return (declaration: Declaration) => { + const [sideA, sideB] = side; + const [valueA, valueB] = parseValueCouple(declaration); + + cloneDeclaration( + declaration, + valueA, + `border-${sideA}-${borderSetting}`, + ); + + cloneDeclaration( + declaration, + valueB, + `border-${sideB}-${borderSetting}`, + ); + + return true; + }; +} + +export function transformBorderShorthand( + side: [string] | [string, string], +): (declaration: Declaration) => boolean { + return (declaration: Declaration) => { + side.forEach((sidePart) => cloneDeclaration( + declaration, + declaration.value, + `border-${sidePart}`, + )); + + return true; + }; +} + +export function transformBorderRadius( + config: DirectionConfig, +): (declaration: Declaration) => boolean { + return (declaration: Declaration) => { + let prop; + + switch (declaration.prop.toLowerCase()) { + case 'border-start-start-radius': { + const replacement = config.inlineIsHorizontal ? + `${config.block[0]}-${config.inline[0]}` : + `${config.inline[0]}-${config.block[0]}`; + + prop = `border-${replacement}-radius`; + break; + } + case 'border-start-end-radius': { + const replacement = config.inlineIsHorizontal ? + `${config.block[0]}-${config.inline[1]}` : + `${config.inline[1]}-${config.block[0]}`; + + prop = `border-${replacement}-radius`; + break; + } + case 'border-end-start-radius': { + const replacement = config.inlineIsHorizontal ? + `${config.block[1]}-${config.inline[0]}` : + `${config.inline[0]}-${config.block[1]}`; + + prop = `border-${replacement}-radius`; + break; + } + case 'border-end-end-radius': { + const replacement = config.inlineIsHorizontal ? + `${config.block[1]}-${config.inline[1]}` : + `${config.inline[1]}-${config.block[1]}`; + + prop = `border-${replacement}-radius`; + break; + } + } + + cloneDeclaration( + declaration, + declaration.value, + prop, + ); + + return true; + }; +} diff --git a/plugins/postcss-logical/src/lib/transform-directional-shorthands.js b/plugins/postcss-logical/src/lib/transform-directional-shorthands.js deleted file mode 100644 index 4e6a49bed..000000000 --- a/plugins/postcss-logical/src/lib/transform-directional-shorthands.js +++ /dev/null @@ -1,72 +0,0 @@ -import cloneRule from './clone-rule'; -import reduceValues from './reduce-values'; - -export default (decl, values, dir, preserve) => { - if ('logical' !== values[0]) { - return null; - } - - // get logical directions as all, inline, block-end, then inline-end - const [, all, inline, blockEnd, inlineEnd ] = values; - - // get left-to-right relative directions from logical directions as: - // → top from all - // → right from inline-end, inline, or all - // → bottom from block-end, block, or all - // → left from inline, or all - const ltrValues = reduceValues([ - all, - inlineEnd || inline || all, - blockEnd || all, - inline || all, - ]); - - const ltrDecl = () => { - return decl.cloneBefore({ - value: ltrValues.join(' '), - }); - }; - - // return the ltr values if the values are flow agnostic (where no second inline value was needed) - const isFlowAgnostic = ltrValues.length < 4; - - if (isFlowAgnostic || dir === 'ltr') { - ltrDecl(); - clean(decl, preserve); - return; - } - - // get right-to-left relative directions from logical directions as: - // → top from all - // → right from inline, or all - // → bottom from block-end, block, or all - // → left from inline-end, inline, or all - const rtlValues = reduceValues([ - all, - inline || all, - blockEnd || all, - inlineEnd || inline || all, - ]); - - const rtlDecl = () => { - return decl.cloneBefore({ - value: rtlValues.join(' '), - }); - }; - - if (dir === 'rtl') { - rtlDecl(); - clean(decl, preserve); - return; - } - - cloneRule(decl, 'ltr').append(ltrDecl()); - cloneRule(decl, 'rtl').append(rtlDecl()); - clean(decl, preserve); -}; - -function clean(decl, preserve) { - if (!preserve) { - decl.remove(); - } -} diff --git a/plugins/postcss-logical/src/lib/transform-float.js b/plugins/postcss-logical/src/lib/transform-float.js deleted file mode 100644 index ae81a8ecd..000000000 --- a/plugins/postcss-logical/src/lib/transform-float.js +++ /dev/null @@ -1,49 +0,0 @@ -import cloneRule from './clone-rule'; - -export default (decl, values, dir, preserve) => { - if (/^inline-start$/i.test(decl.value)) { - if (dir === 'ltr') { - lDecl(decl); - clean(decl, preserve); - return; - } else if (dir === 'rtl') { - rDecl(decl); - clean(decl, preserve); - return; - } else { - cloneRule(decl, 'ltr').append(lDecl(decl)); - cloneRule(decl, 'rtl').append(rDecl(decl)); - clean(decl, preserve); - return; - } - } if (/^inline-end$/i.test(decl.value)) { - if (dir === 'ltr') { - rDecl(decl); - clean(decl, preserve); - return; - } else if (dir === 'rtl') { - lDecl(decl); - clean(decl, preserve); - return; - } else { - cloneRule(decl, 'ltr').append(rDecl(decl)); - cloneRule(decl, 'rtl').append(lDecl(decl)); - clean(decl, preserve); - return; - } - } -}; - -function lDecl(decl) { - return decl.cloneBefore({ value: 'left' }); -} - -function rDecl(decl) { - return decl.cloneBefore({ value: 'right' }); -} - -function clean(decl, preserve) { - if (!preserve) { - decl.remove(); - } -} diff --git a/plugins/postcss-logical/src/lib/transform-inset.js b/plugins/postcss-logical/src/lib/transform-inset.js deleted file mode 100644 index a096cee6c..000000000 --- a/plugins/postcss-logical/src/lib/transform-inset.js +++ /dev/null @@ -1,53 +0,0 @@ -import cloneRule from './clone-rule'; - -export default (decl, values, dir, preserve) => { - if ('logical' !== values[0]) { - decl.cloneBefore({ prop: 'top', value: values[0] }); - decl.cloneBefore({ prop: 'right', value: values[1] || values[0] }); - decl.cloneBefore({ prop: 'bottom', value: values[2] || values[0] }); - decl.cloneBefore({ prop: 'left', value: values[3] || values[1] || values[0] }); - clean(decl, preserve); - return; - } - - const isLTR = !values[4] || values[4] === values[2]; - - if (isLTR || dir === 'ltr') { - lDecl(decl, values); - clean(decl, preserve); - return; - } else if (dir === 'rtl') { - rDecl(decl, values); - clean(decl, preserve); - return; - } else { - cloneRule(decl, 'ltr').append(lDecl(decl, values)); - cloneRule(decl, 'rtl').append(rDecl(decl, values)); - clean(decl, preserve); - return; - } -}; - -function lDecl(decl, values) { - return [ - decl.cloneBefore({ prop: 'top', value: values[1] }), - decl.cloneBefore({ prop: 'left', value: values[2] || values[1] }), - decl.cloneBefore({ prop: 'bottom', value: values[3] || values[1] }), - decl.cloneBefore({ prop: 'right', value: values[4] || values[2] || values[1] }), - ]; -} - -function rDecl(decl, values) { - return [ - decl.cloneBefore({ prop: 'top', value: values[1] }), - decl.cloneBefore({ prop: 'right', value: values[2] || values[1] }), - decl.cloneBefore({ prop: 'bottom', value: values[3] || values[1] }), - decl.cloneBefore({ prop: 'left', value: values[4] || values[2] || values[1] }), - ]; -} - -function clean(decl, preserve) { - if (!preserve) { - decl.remove(); - } -} diff --git a/plugins/postcss-logical/src/lib/transform-inset.ts b/plugins/postcss-logical/src/lib/transform-inset.ts new file mode 100644 index 000000000..9a1159b92 --- /dev/null +++ b/plugins/postcss-logical/src/lib/transform-inset.ts @@ -0,0 +1,56 @@ +import type { Declaration } from 'postcss'; +import { cloneDeclaration } from './clone-declaration'; +import valueParser from 'postcss-value-parser'; + +export function transformInset( +): (declaration: Declaration) => boolean { + return (declaration: Declaration) => { + const valuesAST = valueParser(declaration.value); + const values = valuesAST.nodes.filter((node) => node.type !== 'space' && node.type !== 'comment'); + if (values.length > 4) { + const errorMessage = `[postcss-logical] Invalid number of values for ${declaration.prop}. Found ${values.length} values, expected up to 4 values.`; + throw declaration.error(errorMessage); + } + + const newRules = { + 'top': '', + 'right': '', + 'bottom': '', + 'left': '', + }; + + if (values.length === 1) { + newRules.top = valueParser.stringify(values[0]); + newRules.right = newRules.top; + newRules.bottom = newRules.top; + newRules.left = newRules.top; + } + + if (values.length === 2) { + newRules.top = valueParser.stringify(values[0]); + newRules.right = valueParser.stringify(values[1]); + newRules.bottom = newRules.top; + newRules.left = newRules.right; + } + + if (values.length === 3) { + newRules.top = valueParser.stringify(values[0]); + newRules.right = valueParser.stringify(values[1]); + newRules.left = newRules.right; + newRules.bottom = valueParser.stringify(values[2]); + } + + if (values.length === 4) { + newRules.top = valueParser.stringify(values[0]); + newRules.right = valueParser.stringify(values[1]); + newRules.bottom = valueParser.stringify(values[2]); + newRules.left = valueParser.stringify(values[3]); + } + + Object.keys(newRules).forEach((side) => { + cloneDeclaration(declaration, newRules[side], side); + }); + + return true; + }; +} diff --git a/plugins/postcss-logical/src/lib/transform-logical-size.ts b/plugins/postcss-logical/src/lib/transform-logical-size.ts new file mode 100644 index 000000000..2c0571b57 --- /dev/null +++ b/plugins/postcss-logical/src/lib/transform-logical-size.ts @@ -0,0 +1,22 @@ +import type { Declaration } from 'postcss'; +import { cloneDeclaration } from './clone-declaration'; +import { DirectionConfig } from './types'; + +export function transformLogicalSize( + directionConfig: DirectionConfig, +): (declaration: Declaration) => boolean { + return (declaration: Declaration) => { + const { value } = declaration; + const inlineProp = directionConfig.inlineIsHorizontal ? 'width' : 'height'; + const blockProp = directionConfig.inlineIsHorizontal ? 'height' : 'width'; + const prop = declaration.prop === 'block-size' ? blockProp : inlineProp; + + cloneDeclaration( + declaration, + value, + prop, + ); + + return true; + }; +} diff --git a/plugins/postcss-logical/src/lib/transform-offset.ts b/plugins/postcss-logical/src/lib/transform-offset.ts new file mode 100644 index 000000000..c47fbf351 --- /dev/null +++ b/plugins/postcss-logical/src/lib/transform-offset.ts @@ -0,0 +1,40 @@ +import type { Declaration } from 'postcss'; +import { cloneDeclaration } from './clone-declaration'; +import { parseValueCouple } from '../utils/parse-value-couple'; + +export function transformOffset( + prop: string, +): (declaration: Declaration) => boolean { + return (declaration: Declaration) => { + cloneDeclaration( + declaration, + declaration.value, + prop, + ); + + return true; + }; +} + +export function transformOffsetShorthand( + side: [string,string], +): (declaration: Declaration) => boolean { + return (declaration: Declaration) => { + const [sideA, sideB] = side; + const [valueA, valueB] = parseValueCouple(declaration); + + cloneDeclaration( + declaration, + valueA, + sideA, + ); + + cloneDeclaration( + declaration, + valueB, + sideB, + ); + + return true; + }; +} diff --git a/plugins/postcss-logical/src/lib/transform-resize.js b/plugins/postcss-logical/src/lib/transform-resize.js deleted file mode 100644 index 6d94c4fe8..000000000 --- a/plugins/postcss-logical/src/lib/transform-resize.js +++ /dev/null @@ -1,17 +0,0 @@ -export default (decl, values, dir, preserve) => { - if (/^block$/i.test(decl.value)) { - decl.cloneBefore({ value: 'vertical' }); - clean(decl, preserve); - return; - } else if (/^inline$/i.test(decl.value)) { - decl.cloneBefore({ value: 'horizontal' }); - clean(decl, preserve); - return; - } -}; - -function clean(decl, preserve) { - if (!preserve) { - decl.remove(); - } -} diff --git a/plugins/postcss-logical/src/lib/transform-side.js b/plugins/postcss-logical/src/lib/transform-side.js deleted file mode 100644 index 00df0e575..000000000 --- a/plugins/postcss-logical/src/lib/transform-side.js +++ /dev/null @@ -1,115 +0,0 @@ -import cloneDeclBefore from './clone-decl'; -import cloneRule from './clone-rule'; -import matchSide from './match-side'; - -import matchInsetPrefix from './match-inset-prefix'; - -export default { - // inset-block, margin-block, padding-block - 'block': (decl, values, dir, preserve) => { - cloneDeclBefore(decl, '-top', values[0]); - cloneDeclBefore(decl, '-bottom', values[1] || values[0]); - clean(decl, preserve); - }, - - // inset-block-start, margin-block-start, padding-block-start - 'block-start': (decl, values, dir, preserve) => { - decl.cloneBefore({ prop: decl.prop.replace(matchSide, '$1-top').replace(matchInsetPrefix, '') }); - clean(decl, preserve); - }, - - // inset-block-end, margin-block-end, padding-block-end - 'block-end': (decl, values, dir, preserve) => { - decl.cloneBefore({ prop: decl.prop.replace(matchSide, '$1-bottom').replace(matchInsetPrefix, '') }); - clean(decl, preserve); - }, - - // inset-inline, margin-inline, padding-inline - 'inline': (decl, values, dir, preserve) => { - const ltrDecls = () => { - return [ - cloneDeclBefore(decl, '-left', values[0]), - cloneDeclBefore(decl, '-right', values[1] || values[0]), - ]; - }; - - const rtlDecls = () => { - return [ - cloneDeclBefore(decl, '-right', values[0]), - cloneDeclBefore(decl, '-left', values[1] || values[0]), - ]; - }; - - const isLTR = 1 === values.length || 2 === values.length && values[0] === values[1]; - if (isLTR || dir === 'ltr') { - ltrDecls(); - clean(decl, preserve); - return; - } else if (dir === 'rtl') { - rtlDecls(); - clean(decl, preserve); - return; - } else { - cloneRule(decl, 'ltr').append(ltrDecls()); - cloneRule(decl, 'rtl').append(rtlDecls()); - clean(decl, preserve); - return; - } - }, - - // inset-inline-start, margin-inline-start, padding-inline-start - 'inline-start': (decl, values, dir, preserve) => { - const ltrDecl = () => { - return cloneDeclBefore(decl, '-left', decl.value); - }; - const rtlDecl = () => { - return cloneDeclBefore(decl, '-right', decl.value); - }; - - if (dir === 'ltr') { - ltrDecl(); - clean(decl, preserve); - return; - } else if (dir === 'rtl') { - rtlDecl(); - clean(decl, preserve); - return; - } else { - cloneRule(decl, 'ltr').append(ltrDecl()); - cloneRule(decl, 'rtl').append(rtlDecl()); - clean(decl, preserve); - return; - } - }, - - // inset-inline-end, margin-inline-end, padding-inline-end - 'inline-end': (decl, values, dir, preserve) => { - const ltrDecl = () => { - return cloneDeclBefore(decl, '-right', decl.value); - }; - const rtlDecl = () => { - return cloneDeclBefore(decl, '-left', decl.value); - }; - - if (dir === 'ltr') { - ltrDecl(); - clean(decl, preserve); - return; - } else if (dir === 'rtl') { - rtlDecl(); - clean(decl, preserve); - return; - } else { - cloneRule(decl, 'ltr').append(ltrDecl()); - cloneRule(decl, 'rtl').append(rtlDecl()); - clean(decl, preserve); - return; - } - }, -}; - -function clean(decl, preserve) { - if (!preserve) { - decl.remove(); - } -} diff --git a/plugins/postcss-logical/src/lib/transform-side.ts b/plugins/postcss-logical/src/lib/transform-side.ts new file mode 100644 index 000000000..c627539a7 --- /dev/null +++ b/plugins/postcss-logical/src/lib/transform-side.ts @@ -0,0 +1,42 @@ +import type { Declaration } from 'postcss'; +import { cloneDeclaration } from './clone-declaration'; +import { parseValueCouple } from '../utils/parse-value-couple'; + +export function transformSide( + prop: string, + side: string, +): (declaration: Declaration) => boolean { + return (declaration: Declaration) => { + cloneDeclaration( + declaration, + declaration.value, + `${prop}-${side}`, + ); + + return true; + }; +} + +export function transformSideShorthand( + prop: string, + side: [string, string], +): (declaration: Declaration) => boolean { + return (declaration: Declaration) => { + const [sideA, sideB] = side; + const [valueA, valueB] = parseValueCouple(declaration); + + cloneDeclaration( + declaration, + valueA, + `${prop}-${sideA}`, + ); + + cloneDeclaration( + declaration, + valueB, + `${prop}-${sideB}`, + ); + + return true; + }; +} diff --git a/plugins/postcss-logical/src/lib/transform-size.js b/plugins/postcss-logical/src/lib/transform-size.js deleted file mode 100644 index c3be83ce6..000000000 --- a/plugins/postcss-logical/src/lib/transform-size.js +++ /dev/null @@ -1,14 +0,0 @@ -import matchSize from './match-size'; - -export default (decl, values, dir, preserve) => { - decl.cloneBefore({ - prop: decl.prop.replace( - matchSize, - ($0, minmax, flow) => `${minmax || ''}${'block' === flow ? 'height' : 'width'}`, - ), - }); - - if (!preserve) { - decl.remove(); - } -}; diff --git a/plugins/postcss-logical/src/lib/transform-text-align.js b/plugins/postcss-logical/src/lib/transform-text-align.js deleted file mode 100644 index e6fca164a..000000000 --- a/plugins/postcss-logical/src/lib/transform-text-align.js +++ /dev/null @@ -1,49 +0,0 @@ -import cloneRule from './clone-rule'; - -export default (decl, values, dir, preserve) => { - if (/^start$/i.test(decl.value)) { - if (dir === 'ltr') { - lDecl(decl); - clean(decl, preserve); - return; - } else if (dir === 'rtl') { - rDecl(decl); - clean(decl, preserve); - return; - } else { - cloneRule(decl, 'ltr').append(lDecl(decl)); - cloneRule(decl, 'rtl').append(rDecl(decl)); - clean(decl, preserve); - return; - } - } else if (/^end$/i.test(decl.value)) { - if (dir === 'ltr') { - rDecl(decl); - clean(decl, preserve); - return; - } else if (dir === 'rtl') { - lDecl(decl); - clean(decl, preserve); - return; - } else { - cloneRule(decl, 'ltr').append(rDecl(decl)); - cloneRule(decl, 'rtl').append(lDecl(decl)); - clean(decl, preserve); - return; - } - } -}; - -function lDecl(decl) { - return decl.cloneBefore({ value: 'left' }); -} - -function rDecl(decl) { - return decl.cloneBefore({ value: 'right' }); -} - -function clean(decl, preserve) { - if (!preserve) { - decl.remove(); - } -} diff --git a/plugins/postcss-logical/src/lib/transform-text-align.ts b/plugins/postcss-logical/src/lib/transform-text-align.ts new file mode 100644 index 000000000..9e50877cf --- /dev/null +++ b/plugins/postcss-logical/src/lib/transform-text-align.ts @@ -0,0 +1,37 @@ +import type { Declaration } from 'postcss'; +import valueParser from 'postcss-value-parser'; +import { DirectionValue } from './types'; +import { cloneDeclaration } from './clone-declaration'; + +export function transformTextAlign( + inlineValues: [string, string], +): (declaration: Declaration) => boolean { + return (declaration: Declaration) => { + const { prop, value } = declaration; + const valueAST = valueParser(value); + const [start, end] = inlineValues; + + valueAST.nodes.forEach((node) => { + if (node.type === 'word') { + const valueCandidate = node.value.toLowerCase(); + + if (valueCandidate === DirectionValue.End) { + node.value = end; + return; + } + + if (valueCandidate === DirectionValue.Start) { + node.value = start; + } + } + }); + + const modifiedValued = valueAST.toString(); + if (modifiedValued !== value) { + cloneDeclaration(declaration, modifiedValued, prop); + return true; + } + + return false; + }; +} diff --git a/plugins/postcss-logical/src/lib/transform-transition.js b/plugins/postcss-logical/src/lib/transform-transition.js deleted file mode 100644 index a8780ca9d..000000000 --- a/plugins/postcss-logical/src/lib/transform-transition.js +++ /dev/null @@ -1,135 +0,0 @@ -import cloneRule from './clone-rule'; -import { splitByComma, splitBySpace } from './split'; - -export default (decl, notValues, dir, preserve) => { - const ltrValues = []; - const rtlValues = []; - - splitByComma(decl.value).forEach(value => { - let hasBeenSplit = false; - - splitBySpace(value).forEach((word, index, words) => { - if (word in valueMap) { - hasBeenSplit = true; - - valueMap[word].ltr.forEach(replacement => { - const clone = words.slice(); - - clone.splice(index, 1, replacement); - - if (ltrValues.length && !/^,$/.test(ltrValues[ltrValues.length - 1])) { - ltrValues.push(','); - } - - ltrValues.push(clone.join('')); - }); - - valueMap[word].rtl.forEach(replacement => { - const clone = words.slice(); - - clone.splice(index, 1, replacement); - - if (rtlValues.length && !/^,$/.test(rtlValues[rtlValues.length - 1])) { - rtlValues.push(','); - } - - rtlValues.push(clone.join('')); - }); - } - }); - - if (!hasBeenSplit) { - ltrValues.push(value); - rtlValues.push(value); - } - }); - - if (ltrValues.length && dir === 'ltr') { - if (preserve) { - decl.cloneBefore({}); - } - decl.value = ltrValues.join(''); - return; - } else if (rtlValues.length && dir === 'rtl') { - if (preserve) { - decl.cloneBefore({}); - } - decl.value = rtlValues.join(''); - return; - } else if (ltrValues.join('') !== rtlValues.join('')) { - - cloneRule(decl, 'ltr').append(decl.cloneBefore({ value: ltrValues.join('') })); - cloneRule(decl, 'rtl').append(decl.cloneBefore({ value: rtlValues.join('') })); - clean(decl, preserve); - return; - } -}; - -function clean(decl, preserve) { - if (!preserve) { - decl.remove(); - } -} - -const valueMap = { - // Logical Height and Logical Width - 'block-size': { ltr: ['height'], rtl: ['height'] }, - 'inline-size': { ltr: ['width'], rtl: ['width'] }, - - // Flow-relative Margins - 'margin-block-end': { ltr: ['margin-bottom'], rtl: ['margin-bottom'] }, - 'margin-block-start': { ltr: ['margin-top'], rtl: ['margin-top'] }, - 'margin-block': { ltr: ['margin-top', 'margin-bottom'], rtl: ['margin-top', 'margin-bottom'] }, - 'margin-inline-end': { ltr: ['margin-right'], rtl: ['margin-left'] }, - 'margin-inline-start': { ltr: ['margin-left'], rtl: ['margin-right'] }, - 'margin-inline': { ltr: ['margin-left', 'margin-right'], rtl: ['margin-left', 'margin-right'] }, - - // Flow-relative Offsets - 'inset-block-end': { ltr: ['bottom'], rtl: ['bottom'] }, - 'inset-block-start': { ltr: ['top'], rtl: ['top'] }, - 'inset-block': { ltr: ['top', 'bottom'], rtl: ['top', 'bottom'] }, - 'inset-inline-end': { ltr: ['right'], rtl: ['left'] }, - 'inset-inline-start': { ltr: ['left'], rtl: ['right'] }, - 'inset-inline': { ltr: ['left', 'right'], rtl: ['left', 'right'] }, - 'inset': { ltr: ['top', 'right', 'bottom', 'left'], rtl: ['top', 'right', 'bottom', 'left'] }, - - // Flow-relative Padding - 'padding-block-end': { ltr: ['padding-bottom'], rtl: ['padding-bottom'] }, - 'padding-block-start': { ltr: ['padding-top'], rtl: ['padding-top'] }, - 'padding-block': { ltr: ['padding-top', 'padding-bottom'], rtl: ['padding-top', 'padding-bottom'] }, - 'padding-inline-end': { ltr: ['padding-right'], rtl: ['padding-left'] }, - 'padding-inline-start': { ltr: ['padding-left'], rtl: ['padding-right'] }, - 'padding-inline': { ltr: ['padding-left', 'padding-right'], rtl: ['padding-left', 'padding-right'] }, - - // Flow-relative Borders - 'border-block-color': { ltr: ['border-top-color', 'border-bottom-color'], rtl: ['border-top-color', 'border-bottom-color'] }, - 'border-block-end-color': { ltr: ['border-bottom-color'], rtl: ['border-bottom-color'] }, - 'border-block-end-style': { ltr: ['border-bottom-style'], rtl: ['border-bottom-style'] }, - 'border-block-end-width': { ltr: ['border-bottom-width'], rtl: ['border-bottom-width'] }, - 'border-block-end': { ltr: ['border-bottom'], rtl: ['border-bottom'] }, - 'border-block-start-color': { ltr: ['border-top-color'], rtl: ['border-top-color'] }, - 'border-block-start-style': { ltr: ['border-top-style'], rtl: ['border-top-style'] }, - 'border-block-start-width': { ltr: ['border-top-width'], rtl: ['border-top-width'] }, - 'border-block-start': { ltr: ['border-top'], rtl: ['border-top'] }, - 'border-block-style': { ltr: ['border-top-style', 'border-bottom-style'], rtl: ['border-top-style', 'border-bottom-style'] }, - 'border-block-width': { ltr: ['border-top-width', 'border-bottom-width'], rtl: ['border-top-width', 'border-bottom-width'] }, - 'border-block': { ltr: ['border-top', 'border-bottom'], rtl: ['border-top', 'border-bottom'] }, - 'border-inline-color': { ltr: ['border-left-color', 'border-right-color'], rtl: ['border-left-color', 'border-right-color'] }, - 'border-inline-end-color': { ltr: ['border-right-color'], rtl: ['border-left-color'] }, - 'border-inline-end-style': { ltr: ['border-right-style'], rtl: ['border-left-style'] }, - 'border-inline-end-width': { ltr: ['border-right-width'], rtl: ['border-left-width'] }, - 'border-inline-end': { ltr: ['border-right'], rtl: ['border-left'] }, - 'border-inline-start-color': { ltr: ['border-left-color'], rtl: ['border-right-color'] }, - 'border-inline-start-style': { ltr: ['border-left-style'], rtl: ['border-right-style'] }, - 'border-inline-start-width': { ltr: ['border-left-width'], rtl: ['border-right-width'] }, - 'border-inline-start': { ltr: ['border-left'], rtl: ['border-right'] }, - 'border-inline-style': { ltr: ['border-left-style', 'border-right-style'], rtl: ['border-left-style', 'border-right-style'] }, - 'border-inline-width': { ltr: ['border-left-width', 'border-right-width'], rtl: ['border-left-width', 'border-right-width'] }, - 'border-inline': { ltr: ['border-left', 'border-right'], rtl: ['border-left', 'border-right'] }, - - // Flow-relative Corner Rounding - 'border-end-end-radius': { ltr: ['border-bottom-right-radius'], rtl: ['border-bottom-left-radius'] }, - 'border-end-start-radius': { ltr: ['border-bottom-left-radius'], rtl: ['border-bottom-right-radius'] }, - 'border-start-end-radius': { ltr: ['border-top-right-radius'], rtl: ['border-top-left-radius'] }, - 'border-start-start-radius': { ltr: ['border-top-left-radius'], rtl: ['border-top-right-radius'] }, -}; diff --git a/plugins/postcss-logical/src/lib/transform-value.ts b/plugins/postcss-logical/src/lib/transform-value.ts new file mode 100644 index 000000000..3c4a35971 --- /dev/null +++ b/plugins/postcss-logical/src/lib/transform-value.ts @@ -0,0 +1,35 @@ +import type { Declaration } from 'postcss'; +import valueParser from 'postcss-value-parser'; +import { DirectionConfig, DirectionValues } from './types'; +import { logicalToPhysical } from '../utils/logical-to-physical'; +import { cloneDeclaration } from './clone-declaration'; + +function doTransform(declaration: Declaration, directionValues: Array, config: DirectionConfig) { + const { prop, value } = declaration; + const valueAST = valueParser(value); + + valueAST.nodes.forEach((node) => { + if (node.type === 'word') { + const valueCandidate = node.value.toLowerCase(); + if (directionValues.includes(valueCandidate)) { + node.value = logicalToPhysical(valueCandidate, config); + } + } + }); + + const modifiedValued = valueAST.toString(); + if (modifiedValued !== value) { + cloneDeclaration(declaration, modifiedValued, prop); + return true; + } + + return false; +} + +export function transformValue( + config: DirectionConfig, +): (declaration: Declaration) => boolean { + return (declaration: Declaration) => { + return doTransform(declaration, Object.values(DirectionValues), config); + }; +} diff --git a/plugins/postcss-logical/src/lib/types.ts b/plugins/postcss-logical/src/lib/types.ts new file mode 100644 index 000000000..23dadd9d6 --- /dev/null +++ b/plugins/postcss-logical/src/lib/types.ts @@ -0,0 +1,36 @@ +export enum Direction { + Block = 'block', + Inline = 'inline', +} + +export enum DirectionValue { + Start = 'start', + End = 'end', +} + +export const DirectionValues = { + BlockStart: 'block-start', + BlockEnd: 'block-end', + InlineStart: 'inline-start', + InlineEnd: 'inline-end', +}; + +export enum DirectionFlow { + TopToBottom = 'top-to-bottom', + BottomToTop = 'bottom-to-top', + RightToLeft = 'right-to-left', + LeftToRight = 'left-to-right', +} + +export enum Axes { + Top = 'top', + Right = 'right', + Bottom = 'bottom', + Left = 'left', +} + +export type DirectionConfig = { + [Direction.Block]: [Axes, Axes]; + [Direction.Inline]: [Axes, Axes]; + inlineIsHorizontal: boolean; +}; diff --git a/plugins/postcss-logical/src/utils/direction-flow-to-axes.ts b/plugins/postcss-logical/src/utils/direction-flow-to-axes.ts new file mode 100644 index 000000000..627a44479 --- /dev/null +++ b/plugins/postcss-logical/src/utils/direction-flow-to-axes.ts @@ -0,0 +1,17 @@ +import { DirectionFlow, Axes } from '../lib/types'; + +export function directionFlowToAxes(directionFlow: DirectionFlow): [Axes, Axes] { + switch (directionFlow) { + case DirectionFlow.TopToBottom: + return [Axes.Top, Axes.Bottom]; + + case DirectionFlow.BottomToTop: + return [Axes.Bottom, Axes.Top]; + + case DirectionFlow.RightToLeft: + return [Axes.Right, Axes.Left]; + + case DirectionFlow.LeftToRight: + return [Axes.Left, Axes.Right]; + } +} diff --git a/plugins/postcss-logical/src/utils/logical-to-physical.ts b/plugins/postcss-logical/src/utils/logical-to-physical.ts new file mode 100644 index 000000000..b7be25a97 --- /dev/null +++ b/plugins/postcss-logical/src/utils/logical-to-physical.ts @@ -0,0 +1,20 @@ +import { DirectionConfig, DirectionValues } from '../lib/types'; + +export function logicalToPhysical(logical: string, config: DirectionConfig): string { + const [blockStart, blockEnd] = config.block; + const [inlineStart, inlineEnd] = config.inline; + + switch (logical) { + case DirectionValues.BlockStart: + return blockStart; + + case DirectionValues.BlockEnd: + return blockEnd; + + case DirectionValues.InlineStart: + return inlineStart; + + case DirectionValues.InlineEnd: + return inlineEnd; + } +} diff --git a/plugins/postcss-logical/src/utils/parse-value-couple.ts b/plugins/postcss-logical/src/utils/parse-value-couple.ts new file mode 100644 index 000000000..37a7ea808 --- /dev/null +++ b/plugins/postcss-logical/src/utils/parse-value-couple.ts @@ -0,0 +1,27 @@ +import type { Declaration } from 'postcss'; +import valueParser from 'postcss-value-parser'; + +export function parseValueCouple(declaration: Declaration): [string, string] { + const valuesAST = valueParser(declaration.value); + const values = valuesAST.nodes.filter((node) => node.type !== 'space'); + + if (values.length > 2) { + const errorMessage = `[postcss-logical] Invalid number of values for ${declaration.prop}. Found ${values.length} values, expected 1 or 2.`; + throw declaration.error(errorMessage); + } + + let valueA; + let valueB; + + if (values.length === 1) { + valueA = valueParser.stringify(values[0]); + valueB = valueA; + } + + if (values.length === 2) { + valueA = valueParser.stringify(values[0]); + valueB = valueParser.stringify(values[1]); + } + + return [valueA, valueB]; +} diff --git a/plugins/postcss-logical/test/_import.mjs b/plugins/postcss-logical/test/_import.mjs index ae2dcf8cd..1f319722d 100644 --- a/plugins/postcss-logical/test/_import.mjs +++ b/plugins/postcss-logical/test/_import.mjs @@ -1,2 +1,6 @@ -import plugin from '../dist/index.mjs'; +import assert from 'assert'; +import plugin from 'postcss-logical'; plugin(); + +assert.ok(plugin.postcss, 'should have "postcss flag"'); +assert.equal(typeof plugin, 'function', 'should return a function'); diff --git a/plugins/postcss-logical/test/abstract.bt.expect.css b/plugins/postcss-logical/test/abstract.bt.expect.css new file mode 100644 index 000000000..5a4366ec3 --- /dev/null +++ b/plugins/postcss-logical/test/abstract.bt.expect.css @@ -0,0 +1,13 @@ +.abstract { + margin-bottom: block-start; + margin-right: inline-end; + margin-top: block-end; + margin-left: inline-start; +} + +.abstract { + border-bottom-left-radius: block-start inline-start; + border-bottom-right-radius: block-start inline-end; + border-top-left-radius: block-end inline-start; + border-top-right-radius: block-end inline-end; +} diff --git a/plugins/postcss-logical/test/abstract.chinese.expect.css b/plugins/postcss-logical/test/abstract.chinese.expect.css new file mode 100644 index 000000000..0f2fafce9 --- /dev/null +++ b/plugins/postcss-logical/test/abstract.chinese.expect.css @@ -0,0 +1,13 @@ +.abstract { + margin-right: block-start; + margin-bottom: inline-end; + margin-left: block-end; + margin-top: inline-start; +} + +.abstract { + border-top-right-radius: block-start inline-start; + border-bottom-right-radius: block-start inline-end; + border-top-left-radius: block-end inline-start; + border-bottom-left-radius: block-end inline-end; +} diff --git a/plugins/postcss-logical/test/abstract.css b/plugins/postcss-logical/test/abstract.css new file mode 100644 index 000000000..5182aec43 --- /dev/null +++ b/plugins/postcss-logical/test/abstract.css @@ -0,0 +1,13 @@ +.abstract { + margin-block-start: block-start; + margin-inline-end: inline-end; + margin-block-end: block-end; + margin-inline-start: inline-start; +} + +.abstract { + border-start-start-radius: block-start inline-start; + border-start-end-radius: block-start inline-end; + border-end-start-radius: block-end inline-start; + border-end-end-radius: block-end inline-end; +} diff --git a/plugins/postcss-logical/test/abstract.expect.css b/plugins/postcss-logical/test/abstract.expect.css new file mode 100644 index 000000000..f83781218 --- /dev/null +++ b/plugins/postcss-logical/test/abstract.expect.css @@ -0,0 +1,13 @@ +.abstract { + margin-top: block-start; + margin-right: inline-end; + margin-bottom: block-end; + margin-left: inline-start; +} + +.abstract { + border-top-left-radius: block-start inline-start; + border-top-right-radius: block-start inline-end; + border-bottom-left-radius: block-end inline-start; + border-bottom-right-radius: block-end inline-end; +} diff --git a/plugins/postcss-logical/test/abstract.rtl-and-bt.expect.css b/plugins/postcss-logical/test/abstract.rtl-and-bt.expect.css new file mode 100644 index 000000000..37bb6092f --- /dev/null +++ b/plugins/postcss-logical/test/abstract.rtl-and-bt.expect.css @@ -0,0 +1,13 @@ +.abstract { + margin-bottom: block-start; + margin-left: inline-end; + margin-top: block-end; + margin-right: inline-start; +} + +.abstract { + border-bottom-right-radius: block-start inline-start; + border-bottom-left-radius: block-start inline-end; + border-top-right-radius: block-end inline-start; + border-top-left-radius: block-end inline-end; +} diff --git a/plugins/postcss-logical/test/abstract.rtl.expect.css b/plugins/postcss-logical/test/abstract.rtl.expect.css new file mode 100644 index 000000000..182990843 --- /dev/null +++ b/plugins/postcss-logical/test/abstract.rtl.expect.css @@ -0,0 +1,13 @@ +.abstract { + margin-top: block-start; + margin-left: inline-end; + margin-bottom: block-end; + margin-right: inline-start; +} + +.abstract { + border-top-right-radius: block-start inline-start; + border-top-left-radius: block-start inline-end; + border-bottom-right-radius: block-end inline-start; + border-bottom-left-radius: block-end inline-end; +} diff --git a/plugins/postcss-logical/test/border.chinese.expect.css b/plugins/postcss-logical/test/border.chinese.expect.css new file mode 100644 index 000000000..e83fd995d --- /dev/null +++ b/plugins/postcss-logical/test/border.chinese.expect.css @@ -0,0 +1,133 @@ +.border-width { + border-right-width: 1px; + border-left-width: 2px; + border-top-width: 3px; + border-bottom-width: 4px; +} + +.border-width-block { + border-right-width: 1px; + border-left-width: 1px; +} + +.border-width-block { + border-right-width: 1px; + border-left-width: var(--border-width); +} + +.border-width-block { + border-block-width: 1px 2px 3px; +} + +.border-width-inline { + border-top-width: 1px; + border-bottom-width: 1px; +} + +.border-width-inline { + border-top-width: var(--border-width); + border-bottom-width: 2px; +} + +.border-width-inline { + border-inline-width: 1px 2px 3px; +} + +.border-style { + border-right-style: dotted; + border-left-style: dashed; + border-top-style: solid; + border-bottom-style: double; +} + +.border-style-block { + border-right-style: dotted; + border-left-style: dotted; +} + +.border-style-block { + border-right-style: dotted; + border-left-style: var(--border-style); +} + +.border-style-block { + border-block-style: dotted dashed solid; +} + +.border-style-inline { + border-top-style: dotted; + border-bottom-style: dotted; +} + +.border-style-inline { + border-top-style: var(--border-style); + border-bottom-style: dotted; +} + +.border-style-inline { + border-inline-style: dotted dashed solid; +} + +.border-color { + border-right-color: red; + border-left-color: yellow; + border-top-color: green; + border-bottom-color: blue; +} + +.border-color-block { + border-right-color: red; + border-left-color: red; +} + +.border-color-block { + border-right-color: red; + border-left-color: var(--border-color); +} + +.border-color-block { + border-block-color: red yellow green; +} + +.border-color-inline { + border-top-color: red; + border-bottom-color: red; +} + +.border-color-inline { + border-top-color: var(--border-color); + border-bottom-color: yellow; +} + +.border-color-inline { + border-inline-color: red yellow green; +} + +.border-shorthand { + border-right: 1px dotted red; + border-left: 2px dashed yellow; + border-top: 3px solid green; + border-bottom: 4px double blue; +} + +.border-shorthand-block { + border-right: 1px dotted red; + border-left: 1px dotted red; +} + +.border-shorthand-inline { + border-top: 1px dotted red; + border-bottom: 1px dotted red; +} + +.border-shorthand { + border-right: var(--some-var); + border-left: var(--some-var); +} + +.border-radius { + border-top-right-radius: 1px; + border-bottom-right-radius: 2px; + border-top-left-radius: 3px; + border-bottom-left-radius: 4px; +} diff --git a/plugins/postcss-logical/test/border.css b/plugins/postcss-logical/test/border.css index 77d7df9c8..b436c726f 100644 --- a/plugins/postcss-logical/test/border.css +++ b/plugins/postcss-logical/test/border.css @@ -1,54 +1,116 @@ -test-border { - border: inherit; - border-block: 1px solid black; - border: inherit; - border-block-start: 2px solid black; - border: inherit; - border-block-end: 3px solid black; - border: inherit; - border-inline: 4px solid black; - border: inherit; -} - -test-flowing-border { - border: inherit; - border-inline-start: 1px solid black; - border: inherit; - border-inline-end: 2px solid black; - border: inherit; -} - -test-border-color { - border-color: inherit; - border-color: logical red; - border-color: inherit; - border-color: logical orange yellow; - border-color: inherit; - border-color: logical green blue indigo; - border-color: inherit; - border-block-color: violet; - border-color: inherit; - border-block-start-color: white; - border-color: inherit; - border-block-end-color: black; - border-color: inherit; - border-inline-color: grey; - border-color: inherit; -} - -test-flowing-border-width { - border-width: logical 1px 2px 3px 4px; - border-width: inherit; - border-inline-width: 2px 4px; - border-width: inherit; - border-inline-start-width: 2px; - border-width: inherit; +.border-width { + border-block-start-width: 1px; + border-block-end-width: 2px; + border-inline-start-width: 3px; border-inline-end-width: 4px; - border-width: inherit; - border-block-width: 2px 4px; } -test-flowing-border-radius { +.border-width-block { + border-block-width: 1px; +} + +.border-width-block { + border-block-width: 1px var(--border-width); +} + +.border-width-block { + border-block-width: 1px 2px 3px; +} + +.border-width-inline { + border-inline-width: 1px; +} + +.border-width-inline { + border-inline-width: var(--border-width) 2px; +} + +.border-width-inline { + border-inline-width: 1px 2px 3px; +} + +.border-style { + border-block-start-style: dotted; + border-block-end-style: dashed; + border-inline-start-style: solid; + border-inline-end-style: double; +} + +.border-style-block { + border-block-style: dotted; +} + +.border-style-block { + border-block-style: dotted var(--border-style); +} + +.border-style-block { + border-block-style: dotted dashed solid; +} + +.border-style-inline { + border-inline-style: dotted; +} + +.border-style-inline { + border-inline-style: var(--border-style) dotted; +} + +.border-style-inline { + border-inline-style: dotted dashed solid; +} + +.border-color { + border-block-start-color: red; + border-block-end-color: yellow; + border-inline-start-color: green; + border-inline-end-color: blue; +} + +.border-color-block { + border-block-color: red; +} + +.border-color-block { + border-block-color: red var(--border-color); +} + +.border-color-block { + border-block-color: red yellow green; +} + +.border-color-inline { + border-inline-color: red; +} + +.border-color-inline { + border-inline-color: var(--border-color) yellow; +} + +.border-color-inline { + border-inline-color: red yellow green; +} + +.border-shorthand { + border-block-start: 1px dotted red; + border-block-end: 2px dashed yellow; + border-inline-start: 3px solid green; + border-inline-end: 4px double blue; +} + +.border-shorthand-block { + border-block: 1px dotted red; +} + +.border-shorthand-inline { + border-inline: 1px dotted red; +} + +.border-shorthand { + border-block: var(--some-var); +} + +.border-radius { border-start-start-radius: 1px; border-start-end-radius: 2px; border-end-start-radius: 3px; diff --git a/plugins/postcss-logical/test/border.expect.css b/plugins/postcss-logical/test/border.expect.css index 30cbd3efd..63299f927 100644 --- a/plugins/postcss-logical/test/border.expect.css +++ b/plugins/postcss-logical/test/border.expect.css @@ -1,130 +1,133 @@ -test-border { - border: inherit; - border-top: 1px solid black; - border-bottom: 1px solid black; - border: inherit; - border-top: 2px solid black; - border: inherit; - border-bottom: 3px solid black; - border: inherit; - border-left: 4px solid black; - border-right: 4px solid black; - border: inherit; +.border-width { + border-top-width: 1px; + border-bottom-width: 2px; + border-left-width: 3px; + border-right-width: 4px; } -test-flowing-border:dir(ltr) { - border-left: 1px solid black; +.border-width-block { + border-top-width: 1px; + border-bottom-width: 1px; } -test-flowing-border:dir(rtl) { - border-right: 1px solid black; +.border-width-block { + border-top-width: 1px; + border-bottom-width: var(--border-width); } -test-flowing-border:dir(ltr) { - border-right: 2px solid black; +.border-width-block { + border-block-width: 1px 2px 3px; } -test-flowing-border:dir(rtl) { - border-left: 2px solid black; +.border-width-inline { + border-left-width: 1px; + border-right-width: 1px; } -test-flowing-border { - border: inherit; - border: inherit; - border: inherit; +.border-width-inline { + border-left-width: var(--border-width); + border-right-width: 2px; } -test-border-color { - border-color: inherit; - border-color: red; - border-color: inherit; - border-color: orange yellow; - border-color: inherit; - border-color: green blue indigo; - border-color: inherit; - border-top-color: violet; - border-bottom-color: violet; - border-color: inherit; - border-top-color: white; - border-color: inherit; - border-bottom-color: black; - border-color: inherit; - border-left-color: grey; - border-right-color: grey; - border-color: inherit; +.border-width-inline { + border-inline-width: 1px 2px 3px; } -test-flowing-border-width:dir(ltr) { - border-width: 1px 4px 3px 2px; +.border-style { + border-top-style: dotted; + border-bottom-style: dashed; + border-left-style: solid; + border-right-style: double; } -test-flowing-border-width:dir(rtl) { - border-width: 1px 2px 3px 4px; +.border-style-block { + border-top-style: dotted; + border-bottom-style: dotted; } -test-flowing-border-width:dir(ltr) { - border-left-width: 2px; - border-right-width: 4px; +.border-style-block { + border-top-style: dotted; + border-bottom-style: var(--border-style); } -test-flowing-border-width:dir(rtl) { - border-right-width: 2px; - border-left-width: 4px; +.border-style-block { + border-block-style: dotted dashed solid; } -test-flowing-border-width:dir(ltr) { - border-left-width: 2px; +.border-style-inline { + border-left-style: dotted; + border-right-style: dotted; } -test-flowing-border-width:dir(rtl) { - border-right-width: 2px; +.border-style-inline { + border-left-style: var(--border-style); + border-right-style: dotted; } -test-flowing-border-width:dir(ltr) { - border-right-width: 4px; +.border-style-inline { + border-inline-style: dotted dashed solid; } -test-flowing-border-width:dir(rtl) { - border-left-width: 4px; +.border-color { + border-top-color: red; + border-bottom-color: yellow; + border-left-color: green; + border-right-color: blue; } -test-flowing-border-width { - border-width: inherit; - border-width: inherit; - border-width: inherit; - border-width: inherit; - border-top-width: 2px; - border-bottom-width: 4px; +.border-color-block { + border-top-color: red; + border-bottom-color: red; } -test-flowing-border-radius:dir(ltr) { - border-top-left-radius: 1px; +.border-color-block { + border-top-color: red; + border-bottom-color: var(--border-color); } -test-flowing-border-radius:dir(rtl) { - border-top-right-radius: 1px; +.border-color-block { + border-block-color: red yellow green; } -test-flowing-border-radius:dir(ltr) { - border-top-right-radius: 2px; +.border-color-inline { + border-left-color: red; + border-right-color: red; } -test-flowing-border-radius:dir(rtl) { - border-top-left-radius: 2px; +.border-color-inline { + border-left-color: var(--border-color); + border-right-color: yellow; } -test-flowing-border-radius:dir(ltr) { - border-bottom-left-radius: 3px; +.border-color-inline { + border-inline-color: red yellow green; } -test-flowing-border-radius:dir(rtl) { - border-bottom-right-radius: 3px; +.border-shorthand { + border-top: 1px dotted red; + border-bottom: 2px dashed yellow; + border-left: 3px solid green; + border-right: 4px double blue; } -test-flowing-border-radius:dir(ltr) { - border-bottom-right-radius: 4px; +.border-shorthand-block { + border-top: 1px dotted red; + border-bottom: 1px dotted red; +} + +.border-shorthand-inline { + border-left: 1px dotted red; + border-right: 1px dotted red; +} + +.border-shorthand { + border-top: var(--some-var); + border-bottom: var(--some-var); } -test-flowing-border-radius:dir(rtl) { - border-bottom-left-radius: 4px; +.border-radius { + border-top-left-radius: 1px; + border-top-right-radius: 2px; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 4px; } diff --git a/plugins/postcss-logical/test/border.ltr.expect.css b/plugins/postcss-logical/test/border.ltr.expect.css deleted file mode 100644 index 3ee90fa24..000000000 --- a/plugins/postcss-logical/test/border.ltr.expect.css +++ /dev/null @@ -1,62 +0,0 @@ -test-border { - border: inherit; - border-top: 1px solid black; - border-bottom: 1px solid black; - border: inherit; - border-top: 2px solid black; - border: inherit; - border-bottom: 3px solid black; - border: inherit; - border-left: 4px solid black; - border-right: 4px solid black; - border: inherit; -} - -test-flowing-border { - border: inherit; - border-left: 1px solid black; - border: inherit; - border-right: 2px solid black; - border: inherit; -} - -test-border-color { - border-color: inherit; - border-color: red; - border-color: inherit; - border-color: orange yellow; - border-color: inherit; - border-color: green blue indigo; - border-color: inherit; - border-top-color: violet; - border-bottom-color: violet; - border-color: inherit; - border-top-color: white; - border-color: inherit; - border-bottom-color: black; - border-color: inherit; - border-left-color: grey; - border-right-color: grey; - border-color: inherit; -} - -test-flowing-border-width { - border-width: 1px 4px 3px 2px; - border-width: inherit; - border-left-width: 2px; - border-right-width: 4px; - border-width: inherit; - border-left-width: 2px; - border-width: inherit; - border-right-width: 4px; - border-width: inherit; - border-top-width: 2px; - border-bottom-width: 4px; -} - -test-flowing-border-radius { - border-top-left-radius: 1px; - border-top-right-radius: 2px; - border-bottom-left-radius: 3px; - border-bottom-right-radius: 4px; -} diff --git a/plugins/postcss-logical/test/border.preserve.expect.css b/plugins/postcss-logical/test/border.preserve.expect.css deleted file mode 100644 index 66d01de7f..000000000 --- a/plugins/postcss-logical/test/border.preserve.expect.css +++ /dev/null @@ -1,155 +0,0 @@ -test-border { - border: inherit; - border-top: 1px solid black; - border-bottom: 1px solid black; - border-block: 1px solid black; - border: inherit; - border-top: 2px solid black; - border-block-start: 2px solid black; - border: inherit; - border-bottom: 3px solid black; - border-block-end: 3px solid black; - border: inherit; - border-left: 4px solid black; - border-right: 4px solid black; - border-inline: 4px solid black; - border: inherit; -} - -test-flowing-border:dir(ltr) { - border-left: 1px solid black; -} - -test-flowing-border:dir(rtl) { - border-right: 1px solid black; -} - -test-flowing-border:dir(ltr) { - border-right: 2px solid black; -} - -test-flowing-border:dir(rtl) { - border-left: 2px solid black; -} - -test-flowing-border { - border: inherit; - border-inline-start: 1px solid black; - border: inherit; - border-inline-end: 2px solid black; - border: inherit; -} - -test-border-color { - border-color: inherit; - border-color: red; - border-color: logical red; - border-color: inherit; - border-color: orange yellow; - border-color: logical orange yellow; - border-color: inherit; - border-color: green blue indigo; - border-color: logical green blue indigo; - border-color: inherit; - border-top-color: violet; - border-bottom-color: violet; - border-block-color: violet; - border-color: inherit; - border-top-color: white; - border-block-start-color: white; - border-color: inherit; - border-bottom-color: black; - border-block-end-color: black; - border-color: inherit; - border-left-color: grey; - border-right-color: grey; - border-inline-color: grey; - border-color: inherit; -} - -test-flowing-border-width:dir(ltr) { - border-width: 1px 4px 3px 2px; -} - -test-flowing-border-width:dir(rtl) { - border-width: 1px 2px 3px 4px; -} - -test-flowing-border-width:dir(ltr) { - border-left-width: 2px; - border-right-width: 4px; -} - -test-flowing-border-width:dir(rtl) { - border-right-width: 2px; - border-left-width: 4px; -} - -test-flowing-border-width:dir(ltr) { - border-left-width: 2px; -} - -test-flowing-border-width:dir(rtl) { - border-right-width: 2px; -} - -test-flowing-border-width:dir(ltr) { - border-right-width: 4px; -} - -test-flowing-border-width:dir(rtl) { - border-left-width: 4px; -} - -test-flowing-border-width { - border-width: logical 1px 2px 3px 4px; - border-width: inherit; - border-inline-width: 2px 4px; - border-width: inherit; - border-inline-start-width: 2px; - border-width: inherit; - border-inline-end-width: 4px; - border-width: inherit; - border-top-width: 2px; - border-bottom-width: 4px; - border-block-width: 2px 4px; -} - -test-flowing-border-radius:dir(ltr) { - border-top-left-radius: 1px; -} - -test-flowing-border-radius:dir(rtl) { - border-top-right-radius: 1px; -} - -test-flowing-border-radius:dir(ltr) { - border-top-right-radius: 2px; -} - -test-flowing-border-radius:dir(rtl) { - border-top-left-radius: 2px; -} - -test-flowing-border-radius:dir(ltr) { - border-bottom-left-radius: 3px; -} - -test-flowing-border-radius:dir(rtl) { - border-bottom-right-radius: 3px; -} - -test-flowing-border-radius:dir(ltr) { - border-bottom-right-radius: 4px; -} - -test-flowing-border-radius:dir(rtl) { - border-bottom-left-radius: 4px; -} - -test-flowing-border-radius { - border-start-start-radius: 1px; - border-start-end-radius: 2px; - border-end-start-radius: 3px; - border-end-end-radius: 4px; -} diff --git a/plugins/postcss-logical/test/caption-side.chinese.expect.css b/plugins/postcss-logical/test/caption-side.chinese.expect.css new file mode 100644 index 000000000..e877253e0 --- /dev/null +++ b/plugins/postcss-logical/test/caption-side.chinese.expect.css @@ -0,0 +1,27 @@ +.foo { + caption-side: right; +} + +.foo { + caption-side: left; +} + +.foo { + caption-side: top; +} + +.foo { + caption-side: bottom; +} + +.foo { + caption-side: top; +} + +.foo { + caption-side: right; +} + +.foo { + caption-side: block-ending; +} diff --git a/plugins/postcss-logical/test/caption-side.css b/plugins/postcss-logical/test/caption-side.css new file mode 100644 index 000000000..2d1d32af9 --- /dev/null +++ b/plugins/postcss-logical/test/caption-side.css @@ -0,0 +1,27 @@ +.foo { + caption-side: block-start; +} + +.foo { + caption-side: block-end; +} + +.foo { + caption-side: inline-start; +} + +.foo { + caption-side: inline-end; +} + +.foo { + caption-side: top; +} + +.foo { + caption-side: blOcK-START; +} + +.foo { + caption-side: block-ending; +} diff --git a/plugins/postcss-logical/test/caption-side.expect.css b/plugins/postcss-logical/test/caption-side.expect.css new file mode 100644 index 000000000..7c617161c --- /dev/null +++ b/plugins/postcss-logical/test/caption-side.expect.css @@ -0,0 +1,27 @@ +.foo { + caption-side: top; +} + +.foo { + caption-side: bottom; +} + +.foo { + caption-side: left; +} + +.foo { + caption-side: right; +} + +.foo { + caption-side: top; +} + +.foo { + caption-side: top; +} + +.foo { + caption-side: block-ending; +} diff --git a/plugins/postcss-logical/test/clear.css b/plugins/postcss-logical/test/clear.css deleted file mode 100644 index 69f0de1a8..000000000 --- a/plugins/postcss-logical/test/clear.css +++ /dev/null @@ -1,7 +0,0 @@ -test-clear { - clear: both; - clear: left; - clear: inline-start; - clear: inline-end; - clear: right; -} diff --git a/plugins/postcss-logical/test/clear.expect.css b/plugins/postcss-logical/test/clear.expect.css deleted file mode 100644 index 43741d2c8..000000000 --- a/plugins/postcss-logical/test/clear.expect.css +++ /dev/null @@ -1,17 +0,0 @@ -test-clear:dir(ltr) { - clear: left; -} -test-clear:dir(rtl) { - clear: right; -} -test-clear:dir(ltr) { - clear: right; -} -test-clear:dir(rtl) { - clear: left; -} -test-clear { - clear: both; - clear: left; - clear: right; -} diff --git a/plugins/postcss-logical/test/clear.ltr.expect.css b/plugins/postcss-logical/test/clear.ltr.expect.css deleted file mode 100644 index d05d2411b..000000000 --- a/plugins/postcss-logical/test/clear.ltr.expect.css +++ /dev/null @@ -1,7 +0,0 @@ -test-clear { - clear: both; - clear: left; - clear: left; - clear: right; - clear: right; -} diff --git a/plugins/postcss-logical/test/examples/example.chinese.expect.css b/plugins/postcss-logical/test/examples/example.chinese.expect.css new file mode 100644 index 000000000..677249c12 --- /dev/null +++ b/plugins/postcss-logical/test/examples/example.chinese.expect.css @@ -0,0 +1,12 @@ +.element { + width: 100px; + height: 200px; + padding-right: 10px; + padding-left: 20px; + margin-top: auto; + margin-bottom: auto; + border-right-width: 2px; + border-left-width: 2px; + border-right-style: solid; + border-left-style: solid; +} diff --git a/plugins/postcss-logical/test/examples/example.css b/plugins/postcss-logical/test/examples/example.css new file mode 100644 index 000000000..2309188d9 --- /dev/null +++ b/plugins/postcss-logical/test/examples/example.css @@ -0,0 +1,8 @@ +.element { + block-size: 100px; + inline-size: 200px; + padding-block: 10px 20px; + margin-inline: auto; + border-block-width: 2px; + border-block-style: solid; +} diff --git a/plugins/postcss-logical/test/examples/example.expect.css b/plugins/postcss-logical/test/examples/example.expect.css new file mode 100644 index 000000000..fe28dd5e0 --- /dev/null +++ b/plugins/postcss-logical/test/examples/example.expect.css @@ -0,0 +1,12 @@ +.element { + height: 100px; + width: 200px; + padding-top: 10px; + padding-bottom: 20px; + margin-left: auto; + margin-right: auto; + border-top-width: 2px; + border-bottom-width: 2px; + border-top-style: solid; + border-bottom-style: solid; +} diff --git a/plugins/postcss-logical/test/float.css b/plugins/postcss-logical/test/float.css deleted file mode 100644 index c6bc1a5ae..000000000 --- a/plugins/postcss-logical/test/float.css +++ /dev/null @@ -1,6 +0,0 @@ -test-float { - float: left; - float: inline-start; - float: inline-end; - float: right; -} diff --git a/plugins/postcss-logical/test/float.expect.css b/plugins/postcss-logical/test/float.expect.css deleted file mode 100644 index 37c4e1350..000000000 --- a/plugins/postcss-logical/test/float.expect.css +++ /dev/null @@ -1,16 +0,0 @@ -test-float:dir(ltr) { - float: left; -} -test-float:dir(rtl) { - float: right; -} -test-float:dir(ltr) { - float: right; -} -test-float:dir(rtl) { - float: left; -} -test-float { - float: left; - float: right; -} diff --git a/plugins/postcss-logical/test/float.ltr.expect.css b/plugins/postcss-logical/test/float.ltr.expect.css deleted file mode 100644 index 590760eca..000000000 --- a/plugins/postcss-logical/test/float.ltr.expect.css +++ /dev/null @@ -1,6 +0,0 @@ -test-float { - float: left; - float: left; - float: right; - float: right; -} diff --git a/plugins/postcss-logical/test/generated-declaration-cases.css b/plugins/postcss-logical/test/generated-declaration-cases.css deleted file mode 100644 index 502a33106..000000000 --- a/plugins/postcss-logical/test/generated-declaration-cases.css +++ /dev/null @@ -1,48 +0,0 @@ -.order-0 { - -webkit-inset-inline-start: 0; -} - -.order-1 { - -moz-inset-inline-start: 0; -} - -.order-2 { - -ms-inset-inline-start: 0; -} - -.order-3 { - -o-inset-inline-start: 0; -} - -.order-4 { - --inset-inline-start: 0; -} - -.order-5 { - foo-inset-inline-start: 0; -} - -/* inset-inline-start: 0; */ - -.content { - content: 'inset-inline-start: 0;'; -} - -.transition { - transition: 1s inset-inline-start ease; -} - -.important { - inset-inline-start: 0 !important; -} - -@supports (inset-inline-start: 0) { - .support { - inset-inline-start: 0; - } -} -@keyframes KEYFRAMES { - 50% { - inset-inline-start: 0; - } -} diff --git a/plugins/postcss-logical/test/generated-declaration-cases.expect.css b/plugins/postcss-logical/test/generated-declaration-cases.expect.css deleted file mode 100644 index 93ccbf7ee..000000000 --- a/plugins/postcss-logical/test/generated-declaration-cases.expect.css +++ /dev/null @@ -1,59 +0,0 @@ -.order-0 { - -webkit-inset-inline-start: 0; -} - -.order-1 { - -moz-inset-inline-start: 0; -} - -.order-2 { - -ms-inset-inline-start: 0; -} - -.order-3 { - -o-inset-inline-start: 0; -} - -.order-4 { - --inset-inline-start: 0; -} - -.order-5 { - foo-inset-inline-start: 0; -} - -/* inset-inline-start: 0; */ - -.content { - content: 'inset-inline-start: 0;'; -} - -.transition:dir(ltr) { - transition: 1s left ease; -} - -.transition:dir(rtl) { - transition: 1s right ease; -} - -.important:dir(ltr) { - left: 0 !important; -} - -.important:dir(rtl) { - right: 0 !important; -} - -@supports (inset-inline-start: 0) { - .support:dir(ltr) { - left: 0; - } - .support:dir(rtl) { - right: 0; - } -} -@keyframes KEYFRAMES { - 50% { - inset-inline-start: 0; - } -} diff --git a/plugins/postcss-logical/test/generated-declaration-cases.preserve.expect.css b/plugins/postcss-logical/test/generated-declaration-cases.preserve.expect.css deleted file mode 100644 index 3cf357b71..000000000 --- a/plugins/postcss-logical/test/generated-declaration-cases.preserve.expect.css +++ /dev/null @@ -1,70 +0,0 @@ -.order-0 { - -webkit-inset-inline-start: 0; -} - -.order-1 { - -moz-inset-inline-start: 0; -} - -.order-2 { - -ms-inset-inline-start: 0; -} - -.order-3 { - -o-inset-inline-start: 0; -} - -.order-4 { - --inset-inline-start: 0; -} - -.order-5 { - foo-inset-inline-start: 0; -} - -/* inset-inline-start: 0; */ - -.content { - content: 'inset-inline-start: 0;'; -} - -.transition:dir(ltr) { - transition: 1s left ease; -} - -.transition:dir(rtl) { - transition: 1s right ease; -} - -.transition { - transition: 1s inset-inline-start ease; -} - -.important:dir(ltr) { - left: 0 !important; -} - -.important:dir(rtl) { - right: 0 !important; -} - -.important { - inset-inline-start: 0 !important; -} - -@supports (inset-inline-start: 0) { - .support:dir(ltr) { - left: 0; - } - .support:dir(rtl) { - right: 0; - } - .support { - inset-inline-start: 0; - } -} -@keyframes KEYFRAMES { - 50% { - inset-inline-start: 0; - } -} diff --git a/plugins/postcss-logical/test/inset.css b/plugins/postcss-logical/test/inset.css deleted file mode 100644 index 4bff1b4c5..000000000 --- a/plugins/postcss-logical/test/inset.css +++ /dev/null @@ -1,19 +0,0 @@ -test-inset { - inset: 0; - inset: logical 1px; - inset: logical 2px 3px; - inset: logical 4px 5px 6px; - inset: logical 7px 8px 9px 8px; -} - -test-flowing-inset { - inset: auto; - inset: logical 1px 2px 3px 4px; - inset: auto; - inset-inline: 5px 6px; - inset: auto; - inset-inline-start: 7px; - inset: auto; - inset-inline-end: 8px; - inset: auto; -} diff --git a/plugins/postcss-logical/test/inset.expect.css b/plugins/postcss-logical/test/inset.expect.css deleted file mode 100644 index a1f35af18..000000000 --- a/plugins/postcss-logical/test/inset.expect.css +++ /dev/null @@ -1,85 +0,0 @@ -test-inset { - top: 0; - right: 0; - bottom: 0; - left: 0; - top: 1px; - left: 1px; - bottom: 1px; - right: 1px; - top: 2px; - left: 3px; - bottom: 2px; - right: 3px; - top: 4px; - left: 5px; - bottom: 6px; - right: 5px; - top: 7px; - left: 8px; - bottom: 9px; - right: 8px; -} - -test-flowing-inset:dir(ltr) { - top: 1px; - left: 2px; - bottom: 3px; - right: 4px; -} - -test-flowing-inset:dir(rtl) { - top: 1px; - right: 2px; - bottom: 3px; - left: 4px; -} - -test-flowing-inset:dir(ltr) { - left: 5px; - right: 6px; -} - -test-flowing-inset:dir(rtl) { - right: 5px; - left: 6px; -} - -test-flowing-inset:dir(ltr) { - left: 7px; -} - -test-flowing-inset:dir(rtl) { - right: 7px; -} - -test-flowing-inset:dir(ltr) { - right: 8px; -} - -test-flowing-inset:dir(rtl) { - left: 8px; -} - -test-flowing-inset { - top: auto; - right: auto; - bottom: auto; - left: auto; - top: auto; - right: auto; - bottom: auto; - left: auto; - top: auto; - right: auto; - bottom: auto; - left: auto; - top: auto; - right: auto; - bottom: auto; - left: auto; - top: auto; - right: auto; - bottom: auto; - left: auto; -} diff --git a/plugins/postcss-logical/test/inset.ltr.expect.css b/plugins/postcss-logical/test/inset.ltr.expect.css deleted file mode 100644 index 87fd4e266..000000000 --- a/plugins/postcss-logical/test/inset.ltr.expect.css +++ /dev/null @@ -1,53 +0,0 @@ -test-inset { - top: 0; - right: 0; - bottom: 0; - left: 0; - top: 1px; - left: 1px; - bottom: 1px; - right: 1px; - top: 2px; - left: 3px; - bottom: 2px; - right: 3px; - top: 4px; - left: 5px; - bottom: 6px; - right: 5px; - top: 7px; - left: 8px; - bottom: 9px; - right: 8px; -} - -test-flowing-inset { - top: auto; - right: auto; - bottom: auto; - left: auto; - top: 1px; - left: 2px; - bottom: 3px; - right: 4px; - top: auto; - right: auto; - bottom: auto; - left: auto; - left: 5px; - right: 6px; - top: auto; - right: auto; - bottom: auto; - left: auto; - left: 7px; - top: auto; - right: auto; - bottom: auto; - left: auto; - right: 8px; - top: auto; - right: auto; - bottom: auto; - left: auto; -} diff --git a/plugins/postcss-logical/test/logical-size.chinese.expect.css b/plugins/postcss-logical/test/logical-size.chinese.expect.css new file mode 100644 index 000000000..2f9ae52fd --- /dev/null +++ b/plugins/postcss-logical/test/logical-size.chinese.expect.css @@ -0,0 +1,4 @@ +.foo { + width: 1px; + height: 2px; +} diff --git a/plugins/postcss-logical/test/logical-size.css b/plugins/postcss-logical/test/logical-size.css new file mode 100644 index 000000000..1dc23dec2 --- /dev/null +++ b/plugins/postcss-logical/test/logical-size.css @@ -0,0 +1,4 @@ +.foo { + block-size: 1px; + inline-size: 2px; +} diff --git a/plugins/postcss-logical/test/logical-size.expect.css b/plugins/postcss-logical/test/logical-size.expect.css new file mode 100644 index 000000000..68e55ebed --- /dev/null +++ b/plugins/postcss-logical/test/logical-size.expect.css @@ -0,0 +1,4 @@ +.foo { + height: 1px; + width: 2px; +} diff --git a/plugins/postcss-logical/test/margin.chinese.expect.css b/plugins/postcss-logical/test/margin.chinese.expect.css new file mode 100644 index 000000000..cb6f1827f --- /dev/null +++ b/plugins/postcss-logical/test/margin.chinese.expect.css @@ -0,0 +1,33 @@ +.block-side { + margin-right: 1px; + margin-left: 2px; +} + +.inline-side { + margin-top: 1px; + margin-bottom: 2px; +} + +.block-single { + margin-right: 1px; + margin-left: 1px; +} + +.block-double { + margin-right: 1px; + margin-left: 2px; +} + +.inline-single { + margin-top: 1px; + margin-bottom: 1px; +} + +.inline-double { + margin-top: 1px; + margin-bottom: 2px; +} + +.error-1 { + margin-block: 1px 2px 3px 4px; +} diff --git a/plugins/postcss-logical/test/margin.css b/plugins/postcss-logical/test/margin.css index 4de66e712..cbd04afb9 100644 --- a/plugins/postcss-logical/test/margin.css +++ b/plugins/postcss-logical/test/margin.css @@ -1,24 +1,29 @@ -test-margin { - margin: logical 1px; - margin: logical 2px 3px; - margin: logical 4px 5px 6px; - margin: logical 7px 8px 9px 8px; - margin-inline: 10px; - margin-inline: 11px 11px; - margin-block: 12px; - margin-block: 13px 14px; - margin-block-start: 15px; - margin-block-end: 16px; +.block-side { + margin-block-start: 1px; + margin-block-end: 2px; } -test-flowing-margin { - margin: auto; - margin: logical 1px 2px 3px 4px; - margin: auto; - margin-inline: 5px 6px; - margin: auto; - margin-inline-start: 7px; - margin: auto; - margin-inline-end: 8px; - margin: auto; +.inline-side { + margin-inline-start: 1px; + margin-inline-end: 2px; +} + +.block-single { + margin-block: 1px; +} + +.block-double { + margin-block: 1px 2px; +} + +.inline-single { + margin-inline: 1px; +} + +.inline-double { + margin-inline: 1px 2px; +} + +.error-1 { + margin-block: 1px 2px 3px 4px; } diff --git a/plugins/postcss-logical/test/margin.expect.css b/plugins/postcss-logical/test/margin.expect.css index 12fcfe28c..0ee65c261 100644 --- a/plugins/postcss-logical/test/margin.expect.css +++ b/plugins/postcss-logical/test/margin.expect.css @@ -1,58 +1,33 @@ -test-margin { - margin: 1px; - margin: 2px 3px; - margin: 4px 5px 6px; - margin: 7px 8px 9px; - margin-left: 10px; - margin-right: 10px; - margin-left: 11px; - margin-right: 11px; - margin-top: 12px; - margin-bottom: 12px; - margin-top: 13px; - margin-bottom: 14px; - margin-top: 15px; - margin-bottom: 16px; +.block-side { + margin-top: 1px; + margin-bottom: 2px; } -test-flowing-margin:dir(ltr) { - margin: 1px 4px 3px 2px; +.inline-side { + margin-left: 1px; + margin-right: 2px; } -test-flowing-margin:dir(rtl) { - margin: 1px 2px 3px 4px; +.block-single { + margin-top: 1px; + margin-bottom: 1px; } -test-flowing-margin:dir(ltr) { - margin-left: 5px; - margin-right: 6px; +.block-double { + margin-top: 1px; + margin-bottom: 2px; } -test-flowing-margin:dir(rtl) { - margin-right: 5px; - margin-left: 6px; +.inline-single { + margin-left: 1px; + margin-right: 1px; } -test-flowing-margin:dir(ltr) { - margin-left: 7px; +.inline-double { + margin-left: 1px; + margin-right: 2px; } -test-flowing-margin:dir(rtl) { - margin-right: 7px; -} - -test-flowing-margin:dir(ltr) { - margin-right: 8px; -} - -test-flowing-margin:dir(rtl) { - margin-left: 8px; -} - -test-flowing-margin { - margin: auto; - margin: auto; - margin: auto; - margin: auto; - margin: auto; +.error-1 { + margin-block: 1px 2px 3px 4px; } diff --git a/plugins/postcss-logical/test/margin.ltr.expect.css b/plugins/postcss-logical/test/margin.ltr.expect.css deleted file mode 100644 index 9f17d0eaa..000000000 --- a/plugins/postcss-logical/test/margin.ltr.expect.css +++ /dev/null @@ -1,29 +0,0 @@ -test-margin { - margin: 1px; - margin: 2px 3px; - margin: 4px 5px 6px; - margin: 7px 8px 9px; - margin-left: 10px; - margin-right: 10px; - margin-left: 11px; - margin-right: 11px; - margin-top: 12px; - margin-bottom: 12px; - margin-top: 13px; - margin-bottom: 14px; - margin-top: 15px; - margin-bottom: 16px; -} - -test-flowing-margin { - margin: auto; - margin: 1px 4px 3px 2px; - margin: auto; - margin-left: 5px; - margin-right: 6px; - margin: auto; - margin-left: 7px; - margin: auto; - margin-right: 8px; - margin: auto; -} diff --git a/plugins/postcss-logical/test/offsets.chinese.expect.css b/plugins/postcss-logical/test/offsets.chinese.expect.css new file mode 100644 index 000000000..871719a01 --- /dev/null +++ b/plugins/postcss-logical/test/offsets.chinese.expect.css @@ -0,0 +1,99 @@ +.foo { + right: 1px; + left: 2px; + top: 3px; + bottom: 4px; +} + +.foo { + right: var(--var-1); + left: var(--var-2); + top: var(--var-2); + bottom: var(--var-3); +} + +.foo { + right: 1px; + left: 1px; +} + +.foo { + right: 1px; + left: var(--foo); +} + +.foo { + right: var(--foo); + left: var(--foo); +} + +.foo { + inset-block: 1px 2px 3px; +} + +.foo { + top: 1px; + bottom: 1px; +} + +.foo { + top: 1px; + bottom: 2px; +} + +.foo { + inset-inline: 1px 2px 3px; +} + +.foo { + top: 1px; + right: 1px; + bottom: 1px; + left: 1px; +} + +.foo { + top: var(--foo); + right: var(--foo); + bottom: var(--foo); + left: var(--foo); +} + +.foo { + top: 1px; + right: 2px; + bottom: 1px; + left: 2px; +} + +.foo { + top: var(--foo); + right: 2px; + bottom: var(--foo); + left: 2px; +} + +.foo { + top: 1px; + right: 2px; + bottom: 3px; + left: 2px; +} + +.foo { + top: 1px; + right: var(--foo); + bottom: 3px; + left: var(--foo); +} + +.foo { + top: 1px; + right: var(--foo); + bottom: 3px; + left: 4px; +} + +.foo { + inset: 1px 2px 3px 4px 5px; +} diff --git a/plugins/postcss-logical/test/offsets.css b/plugins/postcss-logical/test/offsets.css new file mode 100644 index 000000000..d215b2f66 --- /dev/null +++ b/plugins/postcss-logical/test/offsets.css @@ -0,0 +1,73 @@ +.foo { + inset-block-start: 1px; + inset-block-end: 2px; + inset-inline-start: 3px; + inset-inline-end: 4px; +} + +.foo { + inset-block-start: var(--var-1); + inset-block-end: var(--var-2); + inset-inline-start: var(--var-2); + inset-inline-end: var(--var-3); +} + +.foo { + inset-block: 1px; +} + +.foo { + inset-block: 1px var(--foo); +} + +.foo { + inset-block: var(--foo); +} + +.foo { + inset-block: 1px 2px 3px; +} + +.foo { + inset-inline: 1px; +} + +.foo { + inset-inline: 1px 2px; +} + +.foo { + inset-inline: 1px 2px 3px; +} + +.foo { + inset: 1px; +} + +.foo { + inset: var(--foo); +} + +.foo { + inset: 1px 2px; +} + +.foo { + inset: var(--foo) 2px; +} + +.foo { + inset: 1px 2px 3px; +} + +.foo { + inset: 1px var(--foo) 3px; +} + +.foo { + inset: 1px var(--foo) 3px 4px; +} + +.foo { + inset: 1px 2px 3px 4px 5px; +} diff --git a/plugins/postcss-logical/test/offsets.expect.css b/plugins/postcss-logical/test/offsets.expect.css new file mode 100644 index 000000000..f63c58b29 --- /dev/null +++ b/plugins/postcss-logical/test/offsets.expect.css @@ -0,0 +1,99 @@ +.foo { + top: 1px; + bottom: 2px; + left: 3px; + right: 4px; +} + +.foo { + top: var(--var-1); + bottom: var(--var-2); + left: var(--var-2); + right: var(--var-3); +} + +.foo { + top: 1px; + bottom: 1px; +} + +.foo { + top: 1px; + bottom: var(--foo); +} + +.foo { + top: var(--foo); + bottom: var(--foo); +} + +.foo { + inset-block: 1px 2px 3px; +} + +.foo { + left: 1px; + right: 1px; +} + +.foo { + left: 1px; + right: 2px; +} + +.foo { + inset-inline: 1px 2px 3px; +} + +.foo { + top: 1px; + right: 1px; + bottom: 1px; + left: 1px; +} + +.foo { + top: var(--foo); + right: var(--foo); + bottom: var(--foo); + left: var(--foo); +} + +.foo { + top: 1px; + right: 2px; + bottom: 1px; + left: 2px; +} + +.foo { + top: var(--foo); + right: 2px; + bottom: var(--foo); + left: 2px; +} + +.foo { + top: 1px; + right: 2px; + bottom: 3px; + left: 2px; +} + +.foo { + top: 1px; + right: var(--foo); + bottom: 3px; + left: var(--foo); +} + +.foo { + top: 1px; + right: var(--foo); + bottom: 3px; + left: 4px; +} + +.foo { + inset: 1px 2px 3px 4px 5px; +} diff --git a/plugins/postcss-logical/test/padding.chinese.expect.css b/plugins/postcss-logical/test/padding.chinese.expect.css new file mode 100644 index 000000000..93edfae04 --- /dev/null +++ b/plugins/postcss-logical/test/padding.chinese.expect.css @@ -0,0 +1,33 @@ +.block-side { + padding-right: 1px; + padding-left: 2px; +} + +.inline-side { + padding-top: 1px; + padding-bottom: 2px; +} + +.block-single { + padding-right: 1px; + padding-left: 1px; +} + +.block-double { + padding-right: 1px; + padding-left: 2px; +} + +.inline-single { + padding-top: 1px; + padding-bottom: 1px; +} + +.inline-double { + padding-top: 1px; + padding-bottom: 2px; +} + +.error-1 { + padding-block: 1px 2px 3px 4px; +} diff --git a/plugins/postcss-logical/test/padding.css b/plugins/postcss-logical/test/padding.css index 9f040e0e6..e637f255c 100644 --- a/plugins/postcss-logical/test/padding.css +++ b/plugins/postcss-logical/test/padding.css @@ -1,32 +1,29 @@ -test-padding { - padding: logical 1px; - padding: logical 2px 3px; - padding: logical 4px 5px 6px; - padding: logical 7px 8px 9px 8px; - padding-inline: 10px; - padding-inline: 11px 11px; - padding-block: 12px; - padding-block: 13px 14px; - padding-block-start: 15px; - padding-block-end: 16px; +.block-side { + padding-block-start: 1px; + padding-block-end: 2px; } -test-flowing-padding { - padding: auto; - padding: logical 1px 2px 3px 4px; - padding: auto; - padding-inline: 5px 6px; - padding: auto; - padding-inline-start: 7px; - padding: auto; - padding-inline-end: 8px; - padding: auto; - padding-start: 9px; - padding: auto; - padding-start: 10px 11px; - padding: auto; - padding-end: 12px; - padding: auto; - padding-end: 13px 14px; - padding: auto; +.inline-side { + padding-inline-start: 1px; + padding-inline-end: 2px; +} + +.block-single { + padding-block: 1px; +} + +.block-double { + padding-block: 1px 2px; +} + +.inline-single { + padding-inline: 1px; +} + +.inline-double { + padding-inline: 1px 2px; +} + +.error-1 { + padding-block: 1px 2px 3px 4px; } diff --git a/plugins/postcss-logical/test/padding.expect.css b/plugins/postcss-logical/test/padding.expect.css index cc0adf365..585f38c0b 100644 --- a/plugins/postcss-logical/test/padding.expect.css +++ b/plugins/postcss-logical/test/padding.expect.css @@ -1,66 +1,33 @@ -test-padding { - padding: 1px; - padding: 2px 3px; - padding: 4px 5px 6px; - padding: 7px 8px 9px; - padding-left: 10px; - padding-right: 10px; - padding-left: 11px; - padding-right: 11px; - padding-top: 12px; - padding-bottom: 12px; - padding-top: 13px; - padding-bottom: 14px; - padding-top: 15px; - padding-bottom: 16px; +.block-side { + padding-top: 1px; + padding-bottom: 2px; } -test-flowing-padding:dir(ltr) { - padding: 1px 4px 3px 2px; +.inline-side { + padding-left: 1px; + padding-right: 2px; } -test-flowing-padding:dir(rtl) { - padding: 1px 2px 3px 4px; +.block-single { + padding-top: 1px; + padding-bottom: 1px; } -test-flowing-padding:dir(ltr) { - padding-left: 5px; - padding-right: 6px; +.block-double { + padding-top: 1px; + padding-bottom: 2px; } -test-flowing-padding:dir(rtl) { - padding-right: 5px; - padding-left: 6px; +.inline-single { + padding-left: 1px; + padding-right: 1px; } -test-flowing-padding:dir(ltr) { - padding-left: 7px; +.inline-double { + padding-left: 1px; + padding-right: 2px; } -test-flowing-padding:dir(rtl) { - padding-right: 7px; -} - -test-flowing-padding:dir(ltr) { - padding-right: 8px; -} - -test-flowing-padding:dir(rtl) { - padding-left: 8px; -} - -test-flowing-padding { - padding: auto; - padding: auto; - padding: auto; - padding: auto; - padding: auto; - padding-start: 9px; - padding: auto; - padding-start: 10px 11px; - padding: auto; - padding-end: 12px; - padding: auto; - padding-end: 13px 14px; - padding: auto; +.error-1 { + padding-block: 1px 2px 3px 4px; } diff --git a/plugins/postcss-logical/test/padding.ltr.expect.css b/plugins/postcss-logical/test/padding.ltr.expect.css deleted file mode 100644 index ebb445dfa..000000000 --- a/plugins/postcss-logical/test/padding.ltr.expect.css +++ /dev/null @@ -1,37 +0,0 @@ -test-padding { - padding: 1px; - padding: 2px 3px; - padding: 4px 5px 6px; - padding: 7px 8px 9px; - padding-left: 10px; - padding-right: 10px; - padding-left: 11px; - padding-right: 11px; - padding-top: 12px; - padding-bottom: 12px; - padding-top: 13px; - padding-bottom: 14px; - padding-top: 15px; - padding-bottom: 16px; -} - -test-flowing-padding { - padding: auto; - padding: 1px 4px 3px 2px; - padding: auto; - padding-left: 5px; - padding-right: 6px; - padding: auto; - padding-left: 7px; - padding: auto; - padding-right: 8px; - padding: auto; - padding-start: 9px; - padding: auto; - padding-start: 10px 11px; - padding: auto; - padding-end: 12px; - padding: auto; - padding-end: 13px 14px; - padding: auto; -} diff --git a/plugins/postcss-logical/test/resize.css b/plugins/postcss-logical/test/resize.css deleted file mode 100644 index 1503859af..000000000 --- a/plugins/postcss-logical/test/resize.css +++ /dev/null @@ -1,4 +0,0 @@ -test-resize { - resize: block; - resize: inline; -} diff --git a/plugins/postcss-logical/test/size.css b/plugins/postcss-logical/test/size.css deleted file mode 100644 index 6ec7dbffe..000000000 --- a/plugins/postcss-logical/test/size.css +++ /dev/null @@ -1,14 +0,0 @@ -test-size { - block-size: 320px; - inline-size: 180px; -} - -text-max-size { - max-block-size: 320px; - max-inline-size: 180px; -} - -text-min-size { - min-block-size: 320px; - min-inline-size: 180px; -} diff --git a/plugins/postcss-logical/test/size.expect.css b/plugins/postcss-logical/test/size.expect.css deleted file mode 100644 index 70c4d2639..000000000 --- a/plugins/postcss-logical/test/size.expect.css +++ /dev/null @@ -1,14 +0,0 @@ -test-size { - height: 320px; - width: 180px; -} - -text-max-size { - max-height: 320px; - max-width: 180px; -} - -text-min-size { - min-height: 320px; - min-width: 180px; -} diff --git a/plugins/postcss-logical/test/size.preserve.expect.css b/plugins/postcss-logical/test/size.preserve.expect.css deleted file mode 100644 index fc9859edb..000000000 --- a/plugins/postcss-logical/test/size.preserve.expect.css +++ /dev/null @@ -1,20 +0,0 @@ -test-size { - height: 320px; - block-size: 320px; - width: 180px; - inline-size: 180px; -} - -text-max-size { - max-height: 320px; - max-block-size: 320px; - max-width: 180px; - max-inline-size: 180px; -} - -text-min-size { - min-height: 320px; - min-block-size: 320px; - min-width: 180px; - min-inline-size: 180px; -} diff --git a/plugins/postcss-logical/test/text-align.chinese.expect.css b/plugins/postcss-logical/test/text-align.chinese.expect.css new file mode 100644 index 000000000..e56eb6d24 --- /dev/null +++ b/plugins/postcss-logical/test/text-align.chinese.expect.css @@ -0,0 +1,7 @@ +.text { + text-align: end; +} + +.other-text { + text-align: start; +} diff --git a/plugins/postcss-logical/test/text-align.css b/plugins/postcss-logical/test/text-align.css index 950d748ab..e56eb6d24 100644 --- a/plugins/postcss-logical/test/text-align.css +++ b/plugins/postcss-logical/test/text-align.css @@ -1,6 +1,7 @@ -test-text-align { - text-align: left; - text-align: start; +.text { text-align: end; - text-align: right; +} + +.other-text { + text-align: start; } diff --git a/plugins/postcss-logical/test/text-align.expect.css b/plugins/postcss-logical/test/text-align.expect.css index f33230f7e..0c418e367 100644 --- a/plugins/postcss-logical/test/text-align.expect.css +++ b/plugins/postcss-logical/test/text-align.expect.css @@ -1,16 +1,7 @@ -test-text-align:dir(ltr) { - text-align: left; -} -test-text-align:dir(rtl) { - text-align: right; -} -test-text-align:dir(ltr) { +.text { text-align: right; } -test-text-align:dir(rtl) { + +.other-text { text-align: left; } -test-text-align { - text-align: left; - text-align: right; -} diff --git a/plugins/postcss-logical/test/text-align.hebrew.expect.css b/plugins/postcss-logical/test/text-align.hebrew.expect.css new file mode 100644 index 000000000..f5df1af26 --- /dev/null +++ b/plugins/postcss-logical/test/text-align.hebrew.expect.css @@ -0,0 +1,7 @@ +.text { + text-align: left; +} + +.other-text { + text-align: right; +} diff --git a/plugins/postcss-logical/test/text-align.ltr.expect.css b/plugins/postcss-logical/test/text-align.ltr.expect.css deleted file mode 100644 index 7318c05c7..000000000 --- a/plugins/postcss-logical/test/text-align.ltr.expect.css +++ /dev/null @@ -1,6 +0,0 @@ -test-text-align { - text-align: left; - text-align: left; - text-align: right; - text-align: right; -} diff --git a/plugins/postcss-logical/test/transition.css b/plugins/postcss-logical/test/transition.css deleted file mode 100644 index 4f5c40894..000000000 --- a/plugins/postcss-logical/test/transition.css +++ /dev/null @@ -1,33 +0,0 @@ -.transition { - transition: 1s opacity ease; -} - -.transition-block { - transition: 1s inset-block ease; - transition: 1s margin-block ease; - transition: 1s padding-block ease; - transition-property: border-block, border-block-color, border-block-style, border-block-width; -} - -.transition-inline { - transition: 1s inset-inline ease; - transition: 1s margin-inline ease; - transition: 1s padding-inline ease; - transition-property: border-inline, border-inline-color, border-inline-style, border-inline-width; -} - -.transition-block-start { - transition: 1s inset-block-start ease; - transition: 1s margin-block-start ease; - transition: 1s padding-block-start ease; -} - -.transition-inline-end { - transition: 1s inset-inline-end ease; - transition: 1s margin-inline-end ease; - transition: 1s padding-inline-end ease; -} - -.transition-mixed { - transition: 1s opacity ease, 1s inset-inline-start ease; -} diff --git a/plugins/postcss-logical/test/transition.expect.css b/plugins/postcss-logical/test/transition.expect.css deleted file mode 100644 index 749ca5d24..000000000 --- a/plugins/postcss-logical/test/transition.expect.css +++ /dev/null @@ -1,55 +0,0 @@ -.transition { - transition: 1s opacity ease; -} - -.transition-block { - transition: 1s inset-block ease; - transition: 1s margin-block ease; - transition: 1s padding-block ease; - transition-property: border-block, border-block-color, border-block-style, border-block-width; -} - -.transition-inline { - transition: 1s inset-inline ease; - transition: 1s margin-inline ease; - transition: 1s padding-inline ease; - transition-property: border-inline, border-inline-color, border-inline-style, border-inline-width; -} - -.transition-block-start { - transition: 1s inset-block-start ease; - transition: 1s margin-block-start ease; - transition: 1s padding-block-start ease; -} - -.transition-inline-end:dir(ltr) { - transition: 1s right ease; -} - -.transition-inline-end:dir(rtl) { - transition: 1s left ease; -} - -.transition-inline-end:dir(ltr) { - transition: 1s margin-right ease; -} - -.transition-inline-end:dir(rtl) { - transition: 1s margin-left ease; -} - -.transition-inline-end:dir(ltr) { - transition: 1s padding-right ease; -} - -.transition-inline-end:dir(rtl) { - transition: 1s padding-left ease; -} - -.transition-mixed:dir(ltr) { - transition: 1s opacity ease, 1s left ease; -} - -.transition-mixed:dir(rtl) { - transition: 1s opacity ease, 1s right ease; -} diff --git a/plugins/postcss-logical/test/transition.ltr.expect.css b/plugins/postcss-logical/test/transition.ltr.expect.css deleted file mode 100644 index a2047002f..000000000 --- a/plugins/postcss-logical/test/transition.ltr.expect.css +++ /dev/null @@ -1,33 +0,0 @@ -.transition { - transition: 1s opacity ease; -} - -.transition-block { - transition: 1s top ease,1s bottom ease; - transition: 1s margin-top ease,1s margin-bottom ease; - transition: 1s padding-top ease,1s padding-bottom ease; - transition-property: border-top,border-bottom, border-top-color, border-bottom-color, border-top-style, border-bottom-style, border-top-width, border-bottom-width; -} - -.transition-inline { - transition: 1s left ease,1s right ease; - transition: 1s margin-left ease,1s margin-right ease; - transition: 1s padding-left ease,1s padding-right ease; - transition-property: border-left,border-right, border-left-color, border-right-color, border-left-style, border-right-style, border-left-width, border-right-width; -} - -.transition-block-start { - transition: 1s top ease; - transition: 1s margin-top ease; - transition: 1s padding-top ease; -} - -.transition-inline-end { - transition: 1s right ease; - transition: 1s margin-right ease; - transition: 1s padding-right ease; -} - -.transition-mixed { - transition: 1s opacity ease, 1s left ease; -} diff --git a/plugins/postcss-logical/test/transition.preserve.ltr.expect.css b/plugins/postcss-logical/test/transition.preserve.ltr.expect.css deleted file mode 100644 index cf2304339..000000000 --- a/plugins/postcss-logical/test/transition.preserve.ltr.expect.css +++ /dev/null @@ -1,65 +0,0 @@ -.transition { - transition: 1s opacity ease; -} - -.transition-block { - transition: 1s inset-block ease; - transition: 1s margin-block ease; - transition: 1s padding-block ease; - transition-property: border-block, border-block-color, border-block-style, border-block-width; -} - -.transition-inline { - transition: 1s inset-inline ease; - transition: 1s margin-inline ease; - transition: 1s padding-inline ease; - transition-property: border-inline, border-inline-color, border-inline-style, border-inline-width; -} - -.transition-block-start { - transition: 1s inset-block-start ease; - transition: 1s margin-block-start ease; - transition: 1s padding-block-start ease; -} - -.transition-inline-end:dir(ltr) { - transition: 1s right ease; -} - -.transition-inline-end:dir(rtl) { - transition: 1s left ease; -} - -.transition-inline-end:dir(ltr) { - transition: 1s margin-right ease; -} - -.transition-inline-end:dir(rtl) { - transition: 1s margin-left ease; -} - -.transition-inline-end:dir(ltr) { - transition: 1s padding-right ease; -} - -.transition-inline-end:dir(rtl) { - transition: 1s padding-left ease; -} - -.transition-inline-end { - transition: 1s inset-inline-end ease; - transition: 1s margin-inline-end ease; - transition: 1s padding-inline-end ease; -} - -.transition-mixed:dir(ltr) { - transition: 1s opacity ease, 1s left ease; -} - -.transition-mixed:dir(rtl) { - transition: 1s opacity ease, 1s right ease; -} - -.transition-mixed { - transition: 1s opacity ease, 1s inset-inline-start ease; -} diff --git a/plugins/postcss-logical/tsconfig.json b/plugins/postcss-logical/tsconfig.json new file mode 100644 index 000000000..e0d06239c --- /dev/null +++ b/plugins/postcss-logical/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "declarationDir": "." + }, + "include": ["./src/**/*"], + "exclude": ["dist"], +} diff --git a/rollup/configs/externals.mjs b/rollup/configs/externals.mjs index 2e9a967b7..f44d473d3 100644 --- a/rollup/configs/externals.mjs +++ b/rollup/configs/externals.mjs @@ -19,6 +19,9 @@ export const externalsForCLI = [ '@csstools/postcss-hwb-function', '@csstools/postcss-ic-unit', '@csstools/postcss-is-pseudo-class', + '@csstools/postcss-logical-float-and-clear', + '@csstools/postcss-logical-resize', + '@csstools/postcss-logical-viewport-units', '@csstools/postcss-media-queries-aspect-ratio-number-values', '@csstools/postcss-nested-calc', '@csstools/postcss-normalize-display-values', @@ -93,6 +96,9 @@ export const externalsForPlugin = [ '@csstools/postcss-hwb-function', '@csstools/postcss-ic-unit', '@csstools/postcss-is-pseudo-class', + '@csstools/postcss-logical-float-and-clear', + '@csstools/postcss-logical-resize', + '@csstools/postcss-logical-viewport-units', '@csstools/postcss-media-queries-aspect-ratio-number-values', '@csstools/postcss-nested-calc', '@csstools/postcss-normalize-display-values',