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]
+
+[
][npm-url] [
][css-url] [
][cli-url] [
][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]
+
+[
][npm-url] [
][css-url] [
][cli-url] [
][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]
+# PostCSS Logical Properties and Values [
][PostCSS]
-[![NPM Version][npm-img]][npm-url]
-[![CSS Standard Status][css-img]][css-url]
-[![Build Status][cli-img]][cli-url]
-[
][discord]
+[
][npm-url] [
][css-url] [
][cli-url] [
][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.
-
-[](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',