├── .gitignore ├── lib ├── rule-name.js ├── messages.js ├── validate.js ├── walk.js └── maps.js ├── .rollup.mjs ├── .editorconfig ├── .github └── workflows │ └── test.yml ├── CHANGELOG.md ├── package.json ├── .eslintcache ├── CONTRIBUTING.md ├── index.js ├── README.md ├── .tape.js ├── LICENSE.md ├── index.mjs ├── index.cjs ├── index.mjs.map └── index.cjs.map /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log* 3 | 4 | -------------------------------------------------------------------------------- /lib/rule-name.js: -------------------------------------------------------------------------------- 1 | export default 'csstools/use-logical'; 2 | -------------------------------------------------------------------------------- /.rollup.mjs: -------------------------------------------------------------------------------- 1 | export default { 2 | input: 'index.js', 3 | output: [ 4 | { file: 'index.cjs', format: 'cjs', sourcemap: true }, 5 | { file: 'index.mjs', format: 'es', sourcemap: true } 6 | ] 7 | }; 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_style = tab 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | 10 | [*.md] 11 | trim_trailing_whitespace = false 12 | 13 | [*.{json,md,yml}] 14 | indent_size = 2 15 | indent_style = space 16 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: test 2 | on: 3 | push: 4 | 5 | jobs: 6 | test: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 10 | - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 11 | with: 12 | node-version: 'lts/*' 13 | 14 | - run: npm ci 15 | - run: npm run build 16 | - run: npm run test 17 | -------------------------------------------------------------------------------- /lib/messages.js: -------------------------------------------------------------------------------- 1 | import stylelint from 'stylelint'; 2 | import ruleName from './rule-name'; 3 | 4 | export default stylelint.utils.ruleMessages(ruleName, { 5 | unexpectedProp(physicalProperty, logicalProperty) { 6 | return `Unexpected "${physicalProperty}" property. Use "${logicalProperty}".`; 7 | }, 8 | unexpectedValue(property, physicalValue, logicalValue) { 9 | return `Unexpected "${physicalValue}" value in "${property}" property. Use "${logicalValue}".`; 10 | } 11 | }); 12 | -------------------------------------------------------------------------------- /lib/validate.js: -------------------------------------------------------------------------------- 1 | export const validateRuleWithProps = (root, props, fn) => { 2 | // conditionally walk nodes with children 3 | if (root.nodes && root.nodes.length) { 4 | const args = []; 5 | 6 | const hasProps = props.every(prop => { 7 | const declIndex = root.nodes.findIndex(child => child.type === 'decl' && child.prop === prop); 8 | const decl = root.nodes[declIndex]; 9 | 10 | if (decl) { 11 | args.push(decl, declIndex); 12 | } 13 | 14 | return decl; 15 | }); 16 | 17 | if (hasProps) { 18 | fn(...args); 19 | } 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /lib/walk.js: -------------------------------------------------------------------------------- 1 | // walk all container nodes 2 | export default function walk(node, fn) { 3 | if (node.nodes && node.nodes.length) { 4 | const nodes = node.nodes.slice(); 5 | const length = nodes.length; 6 | let index = -1; 7 | 8 | while (++index < length) { 9 | const child = nodes[index]; 10 | 11 | if (!isDirRule(child)) { 12 | fn(child); 13 | 14 | walk(child, fn); 15 | } 16 | } 17 | } 18 | } 19 | 20 | const dirSelectorRegExp = /:dir\(ltr|rtl\)/i; 21 | const isDirRule = node => node.type === 'rule' && dirSelectorRegExp.test(node.selector); 22 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changes to Property Use Logical 2 | 3 | ### 2.1.2 (March 3, 2024) 4 | 5 | - Fix `exports` in `package.json` [#25](https://github.com/csstools/stylelint-use-logical/issues/25) 6 | - Fix `except` plugin option [#3](https://github.com/csstools/stylelint-use-logical/issues/3) 7 | 8 | ### 2.1.1 (February 19, 2024) 9 | 10 | - Updated: peer `stylelint` to `>= 11 < 17` (patch) [#22](https://github.com/csstools/stylelint-use-logical/pull/22) 11 | - Fixed: compatibility with `stylelint` 16 (patch) [#22](https://github.com/csstools/stylelint-use-logical/pull/22) 12 | 13 | ### 2.1.0 (March 8, 2022) 14 | 15 | - Updated: peer `stylelint` to >= 11 < 16 (patch) 16 | - Added: Support for `width`, `height`, `min-width`, `min-height`, `max-width`, `max-height`. 17 | 18 | ### 2.0.0 (May 12, 2018) 19 | 20 | - Updated: peer `stylelint` to >= 11 < 15 (major) 21 | - Updated: Node 14+ compatibility (major) 22 | 23 | ### 1.1.0 (September 29, 2018) 24 | 25 | - Added: `direction` option to control whether properties and values are 26 | reported or autofixed using _left to right_ or _right to left_ counterparts 27 | - Fixed: Physical properties and values within `:dir(ltr)` or `:dir(rtl)` are 28 | ignored 29 | 30 | ### 1.0.1 (September 28, 2018) 31 | 32 | - Fix usage name 33 | 34 | ### 1.0.0 (September 26, 2018) 35 | 36 | - Initial version 37 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stylelint-use-logical", 3 | "version": "2.1.2", 4 | "description": "Enforce usage of logical properties and values in CSS", 5 | "license": "CC0-1.0", 6 | "author": "Jonathan Neal ", 7 | "repository": "csstools/stylelint-use-logical", 8 | "homepage": "https://github.com/csstools/stylelint-use-logical#readme", 9 | "bugs": "https://github.com/csstools/stylelint-use-logical/issues", 10 | "main": "index.cjs", 11 | "module": "index.mjs", 12 | "exports": { 13 | ".": { 14 | "import": "./index.mjs", 15 | "require": "./index.cjs" 16 | } 17 | }, 18 | "files": [ 19 | "index.cjs", 20 | "index.cjs.map", 21 | "index.mjs", 22 | "index.mjs.map" 23 | ], 24 | "scripts": { 25 | "build": "rollup -c .rollup.mjs --silent", 26 | "prepublishOnly": "npm test", 27 | "pretest": "npm run build", 28 | "test": "stylelint-tape --cwd ./ --plugin index.mjs" 29 | }, 30 | "engines": { 31 | "node": ">=14.0.0" 32 | }, 33 | "dependencies": {}, 34 | "devDependencies": { 35 | "rollup": "^4.0.0", 36 | "stylelint": "^16.0.0", 37 | "stylelint-tape": "^5.1.0" 38 | }, 39 | "peerDependencies": { 40 | "stylelint": ">= 11 < 17" 41 | }, 42 | "eslintConfig": { 43 | "extends": "dev" 44 | }, 45 | "keywords": [ 46 | "stylelint", 47 | "stylelint-plugin", 48 | "css", 49 | "logical", 50 | "properties", 51 | "property", 52 | "flow", 53 | "relative", 54 | "values", 55 | "value", 56 | "ltr", 57 | "rtl", 58 | "directional", 59 | "dir", 60 | "inline", 61 | "block", 62 | "start", 63 | "end", 64 | "align", 65 | "border", 66 | "clear", 67 | "float", 68 | "margin", 69 | "padding", 70 | "size", 71 | "text" 72 | ] 73 | } 74 | -------------------------------------------------------------------------------- /.eslintcache: -------------------------------------------------------------------------------- 1 | [{"/Users/romainmenke/projects/stylelint-use-logical/index.js":"1","/Users/romainmenke/projects/stylelint-use-logical/lib/maps.js":"2","/Users/romainmenke/projects/stylelint-use-logical/lib/messages.js":"3","/Users/romainmenke/projects/stylelint-use-logical/lib/rule-name.js":"4","/Users/romainmenke/projects/stylelint-use-logical/lib/validate.js":"5","/Users/romainmenke/projects/stylelint-use-logical/lib/walk.js":"6"},{"size":5861,"mtime":1709461857333,"results":"7","hashOfConfig":"8"},{"size":3248,"mtime":1709460306105,"results":"9","hashOfConfig":"8"},{"size":429,"mtime":1709460306106,"results":"10","hashOfConfig":"8"},{"size":39,"mtime":1709460306106,"results":"11","hashOfConfig":"8"},{"size":462,"mtime":1709460306106,"results":"12","hashOfConfig":"8"},{"size":471,"mtime":1709460306106,"results":"13","hashOfConfig":"8"},{"filePath":"14","messages":"15","suppressedMessages":"16","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"gd8gf4",{"filePath":"17","messages":"18","suppressedMessages":"19","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"20","messages":"21","suppressedMessages":"22","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"23","messages":"24","suppressedMessages":"25","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"26","messages":"27","suppressedMessages":"28","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"29","messages":"30","suppressedMessages":"31","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"/Users/romainmenke/projects/stylelint-use-logical/index.js",[],[],"/Users/romainmenke/projects/stylelint-use-logical/lib/maps.js",[],[],"/Users/romainmenke/projects/stylelint-use-logical/lib/messages.js",[],[],"/Users/romainmenke/projects/stylelint-use-logical/lib/rule-name.js",[],[],"/Users/romainmenke/projects/stylelint-use-logical/lib/validate.js",[],[],"/Users/romainmenke/projects/stylelint-use-logical/lib/walk.js",[],[]] -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Property Use Logical 2 | 3 | You want to help? You rock! Now, take a moment to be sure your contributions 4 | make sense to everyone else. 5 | 6 | ## Reporting Issues 7 | 8 | Found a problem? Want a new feature? 9 | 10 | - See if your issue or idea has [already been reported]. 11 | - Provide a [reduced test case] or a [live example]. 12 | 13 | Remember, a bug is a _demonstrable problem_ caused by _our_ code. 14 | 15 | ## Submitting Pull Requests 16 | 17 | Pull requests are the greatest contributions, so be sure they are focused in 18 | scope and avoid unrelated commits. 19 | 20 | 1. To begin; [fork this project], clone your fork, and add our upstream. 21 | ```bash 22 | # Clone your fork of the repo into the current directory 23 | git clone git@github.com:YOUR_USER/stylelint-use-logical.git 24 | 25 | # Navigate to the newly cloned directory 26 | cd stylelint-use-logical 27 | 28 | # Assign the original repo to a remote called "upstream" 29 | git remote add upstream git@github.com:csstools/stylelint-use-logical.git 30 | 31 | # Install the tools necessary for testing 32 | npm install 33 | ``` 34 | 35 | 2. Create a branch for your feature or fix: 36 | ```bash 37 | # Move into a new branch for your feature 38 | git checkout -b feature/thing 39 | ``` 40 | ```bash 41 | # Move into a new branch for your fix 42 | git checkout -b fix/something 43 | ``` 44 | 45 | 3. If your code follows our practices, then push your feature branch: 46 | ```bash 47 | # Test current code 48 | npm test 49 | ``` 50 | ```bash 51 | # Push the branch for your new feature 52 | git push origin feature/thing 53 | ``` 54 | ```bash 55 | # Or, push the branch for your update 56 | git push origin update/something 57 | ``` 58 | 59 | That’s it! Now [open a pull request] with a clear title and description. 60 | 61 | [already been reported]: issues 62 | [fork this project]: fork 63 | [live example]: https://codepen.io/pen 64 | [open a pull request]: https://help.github.com/articles/using-pull-requests/ 65 | [reduced test case]: https://css-tricks.com/reduced-test-cases/ 66 | -------------------------------------------------------------------------------- /lib/maps.js: -------------------------------------------------------------------------------- 1 | const inline = { 2 | start: { ltr: 'left', rtl: 'right' }, 3 | end: { ltr: 'right', rtl: 'left' } 4 | } 5 | 6 | export const physical4Prop = [ 7 | [ [ 'top', 'left', 'bottom', 'right' ], 'inset' ], 8 | [ [ 'margin-top', 'margin-left', 'margin-bottom', 'margin-right' ], 'margin' ], 9 | [ [ 'padding-top', 'padding-left', 'padding-bottom', 'padding-right' ], 'padding' ] 10 | ]; 11 | 12 | export const physical2Prop = () => [ 13 | [ [ 'top', 'bottom' ], 'inset-block' ], 14 | [ [ 'left', 'right' ], 'inset-inline' ], 15 | 16 | [ [ 'margin-top', 'margin-bottom' ], 'margin-block' ], 17 | [ [ 'margin-left', 'margin-right' ], 'margin-inline' ], 18 | 19 | [ [ 'padding-top', 'padding-bottom' ], 'padding-block' ], 20 | [ [ 'padding-left', 'padding-right' ], 'padding-inline' ], 21 | ]; 22 | 23 | export const physicalProp = dir => [ 24 | [ [ 'top' ], 'inset-block-start' ], 25 | [ [ 'bottom' ], 'inset-block-end' ], 26 | [ [ inline.start[dir] ], 'inset-inline-start' ], 27 | [ [ inline.end[dir] ], 'inset-inline-end' ], 28 | 29 | [ [ 'margin-top' ], 'margin-block-start' ], 30 | [ [ 'margin-bottom' ], 'margin-block-end' ], 31 | [ [ `margin-${inline.start[dir]}` ], 'margin-inline-start' ], 32 | [ [ `margin-${inline.end[dir]}` ], 'margin-inline-end' ], 33 | 34 | [ [ 'padding-top' ], 'padding-block-start' ], 35 | [ [ 'padding-bottom' ], 'padding-block-end' ], 36 | [ [ `padding-${inline.start[dir]}` ], 'padding-inline-start' ], 37 | [ [ `padding-${inline.end[dir]}` ], 'padding-inline-end' ], 38 | 39 | // width, height 40 | [ [ 'width' ], 'inline-size' ], 41 | [ [ 'min-width' ], 'min-inline-size' ], 42 | [ [ 'max-width' ], 'max-inline-size' ], 43 | [ [ 'height' ], 'block-size' ], 44 | [ [ 'min-height' ], 'min-block-size' ], 45 | [ [ 'max-height' ], 'max-block-size' ], 46 | 47 | // border 48 | [ [ 'border-top' ], 'border-block-start' ], 49 | [ [ 'border-bottom' ], 'border-block-end' ], 50 | [ [ `border-${inline.start[dir]}` ], 'border-inline-start' ], 51 | [ [ `border-${inline.end[dir]}` ], 'border-inline-end' ], 52 | 53 | [ [ 'border-top-color' ], 'border-block-start-color' ], 54 | [ [ 'border-top-style' ], 'border-block-start-style' ], 55 | [ [ 'border-top-width' ], 'border-block-start-width' ], 56 | [ [ 'border-bottom-color' ], 'border-block-end-color' ], 57 | [ [ 'border-bottom-style' ], 'border-block-end-style' ], 58 | [ [ 'border-bottom-width' ], 'border-block-end-width' ], 59 | 60 | 61 | [ [ `border-${inline.start[dir]}-color` ], 'border-inline-start-color' ], 62 | [ [ `border-${inline.start[dir]}-style` ], 'border-inline-start-style' ], 63 | [ [ `border-${inline.start[dir]}-width` ], 'border-inline-start-width' ], 64 | [ [ `border-${inline.end[dir]}-color` ], 'border-inline-end-color' ], 65 | [ [ `border-${inline.end[dir]}-style` ], 'border-inline-end-style' ], 66 | [ [ `border-${inline.end[dir]}-width` ], 'border-inline-end-width' ], 67 | 68 | 69 | 70 | [ [ `border-top-${inline.start[dir]}-radius` ], 'border-start-start-radius' ], 71 | [ [ `border-bottom-${inline.start[dir]}-radius` ], 'border-end-start-radius' ], 72 | [ [ `border-top-${inline.end[dir]}-radius` ], 'border-start-end-radius' ], 73 | [ [ `border-bottom-${inline.end[dir]}-radius` ], 'border-end-end-radius' ], 74 | 75 | ]; 76 | 77 | export const physicalValue = dir => [ 78 | [ /^clear$/i, { 79 | [inline.start[dir]]: 'inline-start', 80 | [inline.end[dir]]: 'inline-end' 81 | }], 82 | [ /^float$/i, { 83 | [inline.start[dir]]: 'inline-start', 84 | [inline.end[dir]]: 'inline-end' 85 | }], 86 | [ /^text-align$/i, { 87 | [inline.start[dir]]: 'start', 88 | [inline.end[dir]]: 'end' 89 | }] 90 | ]; 91 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import stylelint from 'stylelint'; 2 | import { physicalProp, physical2Prop, physical4Prop, physicalValue } from './lib/maps'; 3 | import { validateRuleWithProps } from './lib/validate'; 4 | import ruleName from './lib/rule-name'; 5 | import messages from './lib/messages'; 6 | import walk from './lib/walk'; 7 | 8 | const reportedDecls = new WeakMap(); 9 | 10 | function ruleFunc(method, opts, context) { 11 | const propExceptions = [].concat(Object(opts).except || []); 12 | const isAutofix = isContextAutofixing(context); 13 | const dir = /^rtl$/i.test(Object(opts).direction) ? 'rtl' : 'ltr'; 14 | 15 | return (root, result) => { 16 | // validate the method 17 | const isMethodValid = stylelint.utils.validateOptions(result, ruleName, { 18 | actual: method, 19 | possible() { 20 | return isMethodIndifferent(method) || 21 | isMethodAlways(method) 22 | } 23 | }); 24 | 25 | const reportUnexpectedProperty = (decl, logicalProperty) => stylelint.utils.report({ 26 | message: messages.unexpectedProp(decl.prop, logicalProperty), 27 | node: decl, 28 | result, 29 | ruleName 30 | }); 31 | 32 | const reportUnexpectedValue = (node, value) => stylelint.utils.report({ 33 | message: messages.unexpectedValue(node.prop, node.value, value), 34 | node, 35 | result, 36 | ruleName 37 | }); 38 | 39 | if (isMethodValid && isMethodAlways(method)) { 40 | walk(root, node => { 41 | // validate or autofix 4 physical properties as logical shorthands 42 | physical4Prop.forEach(([ props, prop ]) => { 43 | validateRuleWithProps(node, props, (blockStartDecl, blockStartIndex, inlineStartDecl, inlineStartIndex, blockEndDecl, blockEndIndex, inlineEndDecl, inlineEndIndex) => { // eslint-disable-line 44 | if ( 45 | isDeclAnException(blockStartDecl, propExceptions) || 46 | isDeclAnException(inlineStartDecl, propExceptions) || 47 | isDeclAnException(blockEndDecl, propExceptions) || 48 | isDeclAnException(inlineEndDecl, propExceptions) 49 | ) { 50 | return; 51 | } 52 | 53 | const firstInlineDecl = blockStartDecl; 54 | 55 | if (isAutofix) { 56 | const values = [ blockStartDecl.value, inlineStartDecl.value, blockEndDecl.value, inlineEndDecl.value ]; 57 | 58 | if (values[1] === values[3]) { 59 | values.pop(); 60 | 61 | if (values[2] === values[1]) { 62 | values.pop(); 63 | 64 | if (values[1] === values[0]) { 65 | values.pop(); 66 | } 67 | } 68 | } 69 | 70 | firstInlineDecl.cloneBefore({ 71 | prop, 72 | value: values.length <= 2 ? values.join(' ') : `logical ${values.join(' ')}` 73 | }); 74 | 75 | blockStartDecl.remove(); 76 | inlineStartDecl.remove(); 77 | blockEndDecl.remove(); 78 | inlineEndDecl.remove(); 79 | } else if (!isDeclReported(blockStartDecl) && !isDeclReported(inlineStartDecl) && !isDeclReported(blockEndDecl) && !isDeclReported(inlineEndDecl)) { 80 | reportUnexpectedProperty(firstInlineDecl, prop); 81 | 82 | reportedDecls.set(blockStartDecl); 83 | reportedDecls.set(inlineStartDecl); 84 | reportedDecls.set(blockEndDecl); 85 | reportedDecls.set(inlineEndDecl); 86 | } 87 | }); 88 | }); 89 | 90 | // validate or autofix 2 physical properties as logical shorthands 91 | physical2Prop().forEach(([ props, prop ]) => { 92 | validateRuleWithProps(node, props, (blockStartDecl, blockStartIndex, inlineStartDecl, inlineStartIndex) => { // eslint-disable-line 93 | if ( 94 | isDeclAnException(blockStartDecl, propExceptions) || 95 | isDeclAnException(inlineStartDecl, propExceptions) 96 | ) { 97 | return; 98 | } 99 | 100 | const firstInlineDecl = blockStartIndex < inlineStartIndex 101 | ? blockStartDecl 102 | : inlineStartDecl; 103 | 104 | if (isAutofix) { 105 | firstInlineDecl.cloneBefore({ 106 | prop, 107 | value: blockStartDecl.value === inlineStartDecl.value 108 | ? blockStartDecl.value 109 | : [ blockStartDecl.value, inlineStartDecl.value ].join(' ') 110 | }); 111 | 112 | blockStartDecl.remove(); 113 | inlineStartDecl.remove(); 114 | } else if (!isDeclReported(blockStartDecl) && !isDeclReported(inlineStartDecl)) { 115 | reportUnexpectedProperty(firstInlineDecl, prop); 116 | 117 | reportedDecls.set(blockStartDecl); 118 | reportedDecls.set(inlineStartDecl); 119 | } 120 | }); 121 | }); 122 | 123 | // validate or autofix physical properties as logical 124 | physicalProp(dir).forEach(([ props, prop ]) => { 125 | validateRuleWithProps(node, props, physicalDecl => { 126 | if (isDeclAnException(physicalDecl, propExceptions)) { 127 | return; 128 | } 129 | 130 | if (isAutofix) { 131 | physicalDecl.prop = prop; 132 | } else if (!isDeclReported(physicalDecl)) { 133 | reportUnexpectedProperty(physicalDecl, prop); 134 | 135 | reportedDecls.set(physicalDecl); 136 | } 137 | }); 138 | }); 139 | 140 | // validate or autofix physical values as logical 141 | physicalValue(dir).forEach(([ regexp, props ]) => { 142 | if (!isNodeMatchingDecl(node, regexp)) { 143 | return; 144 | } 145 | 146 | if (isDeclAnException(node, propExceptions)) { 147 | return; 148 | } 149 | 150 | const valuekey = node.value.toLowerCase(); 151 | 152 | if (valuekey in props) { 153 | const value = props[valuekey]; 154 | 155 | if (isAutofix) { 156 | node.value = value; 157 | } else { 158 | reportUnexpectedValue(node, value); 159 | 160 | reportedDecls.set(node); 161 | } 162 | } 163 | }); 164 | }); 165 | } 166 | }; 167 | }; 168 | ruleFunc.ruleName = ruleName; 169 | 170 | export default stylelint.createPlugin(ruleName, ruleFunc); 171 | 172 | const isMethodIndifferent = method => method === 'ignore' || method === false || method === null; 173 | const isMethodAlways = method => method === 'always' || method === true; 174 | const isContextAutofixing = context => Boolean(Object(context).fix); 175 | const isNodeMatchingDecl = (decl, regexp) => decl.type === 'decl' && regexp.test(decl.prop); 176 | 177 | const isDeclAnException = (decl, propExceptions) => { 178 | if (!decl || decl.type !== 'decl') { 179 | return false; 180 | } 181 | 182 | return propExceptions.some((match) => { 183 | if (match instanceof RegExp) { 184 | return match.test(decl.prop); 185 | } 186 | 187 | return String(match || '').toLowerCase() === String(decl.prop || '').toLowerCase(); 188 | }); 189 | } 190 | 191 | const isDeclReported = decl => reportedDecls.has(decl); 192 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Property Use Logical [stylelint][stylelint] 2 | 3 | [![NPM Version][npm-img]][npm-url] 4 | [![Build Status][cli-img]][cli-url] 5 | [![Support Chat][git-img]][git-url] 6 | 7 | [Property Use Logical] is a [stylelint] rule to enforce the usage of 8 | [Logical Properties and Values] in CSS. 9 | 10 | Physical dimensions and directions are described _left_ to _right_ and _top_ to 11 | _bottom_, while their logical counterparts are described _start_ to _end_ and 12 | _inline_ or _block_. 13 | 14 | --- 15 | 16 | For example, to add spacing before the start of a paragraph, we might use the 17 | physical `padding-left` property. 18 | 19 | ```css 20 | p { 21 | padding-left: 2em; 22 | } 23 | ``` 24 | 25 | Were the content Hebrew or Arabic — flowing _right to left_ — then we might 26 | use alternating `padding-left` and `padding-right` properties. 27 | 28 | ```css 29 | p:dir(ltr) { 30 | padding-left: 2em; 31 | } 32 | 33 | p:dir(rtl) { 34 | padding-right: 2em; 35 | } 36 | ``` 37 | 38 | Selector weight aside, we can instead use the logical `padding-inline-start` 39 | property. 40 | 41 | ```css 42 | p { 43 | padding-inline-start: 2em; 44 | } 45 | ``` 46 | 47 | Similarly, physical _horizontal_ and _vertical_ dimensions are described 48 | more succinctly using their logical counterparts. 49 | 50 | ```css 51 | h1, h2, h3 { 52 | margin-top: 1em; 53 | margin-bottom: 1em; 54 | } 55 | 56 | blockquote { 57 | margin-left: 1em; 58 | margin-right: 1em; 59 | } 60 | 61 | /* becomes */ 62 | 63 | h1, h2, h3 { 64 | margin-block: 1em; 65 | } 66 | 67 | blockquote { 68 | margin-inline: 1em; 69 | } 70 | ``` 71 | 72 | ## Usage 73 | 74 | Add [stylelint] and [Property Use Logical] to your project. 75 | 76 | ```bash 77 | npm install stylelint stylelint-use-logical --save-dev 78 | ``` 79 | 80 | Add [Property Use Logical] to your [stylelint configuration]. 81 | 82 | ```js 83 | { 84 | "plugins": [ 85 | "stylelint-use-logical" 86 | ], 87 | "rules": { 88 | "csstools/use-logical": ("always" || true) || ("ignore" || false || null) 89 | } 90 | } 91 | ``` 92 | 93 | ## Options 94 | 95 | ### always 96 | 97 | The `"always"` option (alternatively `true`) requires logical properties and 98 | values to be used, and the following patterns are _not_ considered violations: 99 | 100 | ```pcss 101 | .inset { 102 | inset: 0; 103 | } 104 | 105 | .margin { 106 | margin-inline-start: 0; 107 | } 108 | 109 | .padding { 110 | padding-inline: 0; 111 | } 112 | 113 | .float { 114 | float: inline-start; 115 | } 116 | 117 | .text-align { 118 | text-align: start; 119 | } 120 | 121 | .text-align-ignored:dir(ltr) { 122 | text-align: left; 123 | } 124 | ``` 125 | 126 | While the following patterns _are_ considered violations: 127 | 128 | ```pcss 129 | .inset { 130 | top: 0; 131 | right: 0; 132 | bottom: 0; 133 | left: 0; 134 | } 135 | 136 | .margin { 137 | margin-left: 0; 138 | } 139 | 140 | .padding { 141 | padding-left: 0; 142 | padding-right: 0; 143 | } 144 | 145 | .float { 146 | float: left; 147 | } 148 | 149 | .text-align { 150 | text-align: left; 151 | } 152 | ``` 153 | 154 | ### ignore 155 | 156 | The `"ignore"` option (alternatively `false` or `null`) disables the rule. 157 | 158 | ## Secondary Options 159 | 160 | ### except 161 | 162 | The `except` option ignores reporting or autofixing properties and values 163 | matching a case-insensitive string or regular expression. 164 | 165 | ```js 166 | { 167 | "rules": { 168 | "csstools/use-logical": ["always", { "except": ['float', /^margin/i] }] 169 | } 170 | } 171 | ``` 172 | 173 | ### direction 174 | 175 | The `direction` option controls whether _left to right_ or _right to left_ 176 | properties and values should be reported or autofixed. 177 | 178 | ```js 179 | { 180 | "rules": { 181 | "csstools/use-logical": ["always", { "direction": "ltr" || "rtl" }] 182 | } 183 | } 184 | ``` 185 | 186 | ## Property and Value Mapping 187 | 188 | Assuming _left to right_ directionality: 189 | 190 | | Physical Property | Logical Property | 191 | | ----------------- | ---------------------- | 192 | | `top` | `inset-block-start` | 193 | | `right` | `inset-inline-end` | 194 | | `bottom` | `inset-block-end` | 195 | | `left` | `inset-inline-start` | 196 | 197 | | Physical Property | Logical Property | 198 | | ----------------- | ---------------------- | 199 | | `margin-top` | `margin-block-start` | 200 | | `margin-right` | `margin-inline-end` | 201 | | `margin-bottom` | `margin-block-end` | 202 | | `margin-left` | `margin-inline-start` | 203 | 204 | | Physical Property | Logical Property | 205 | | ----------------- | ---------------------- | 206 | | `padding-top` | `padding-block-start` | 207 | | `padding-right` | `padding-inline-end` | 208 | | `padding-bottom` | `padding-block-end` | 209 | | `padding-left` | `padding-inline-start` | 210 | 211 | | Physical Property | Logical Property | 212 | | ----------------- | ---------------------- | 213 | | `width` | `inline-size` | 214 | | `min-width` | `min-inline-size` | 215 | | `max-width` | `max-inline-size` | 216 | | `height` | `block-size` | 217 | | `min-height` | `min-block-size` | 218 | | `max-height` | `max-block-size` | 219 | 220 | | Physical Property | Logical Property | 221 | | --------------------------- | --------------------------- | 222 | | `border-top-left-radius` | `border-start-start-radius` | 223 | | `border-top-right-radius` | `border-start-end-radius` | 224 | | `border-bottom-left-radius` | `border-end-start-radius` | 225 | | `border-bottom-right-radius`| `border-end-end-radius` | 226 | 227 | | Physical Value | Logical Value | 228 | | -------------------- | --------------------- | 229 | | `text-align: left;` | `text-align: start;` | 230 | | `text-align: right;` | `text-align: end;` | 231 | 232 | [cli-img]: https://img.shields.io/travis/csstools/stylelint-use-logical.svg 233 | [cli-url]: https://travis-ci.org/csstools/stylelint-use-logical 234 | [git-img]: https://img.shields.io/badge/support-chat-blue.svg 235 | [git-url]: https://gitter.im/stylelint/stylelint 236 | [npm-img]: https://img.shields.io/npm/v/stylelint-use-logical.svg 237 | [npm-url]: https://www.npmjs.com/package/stylelint-use-logical 238 | 239 | [Logical Properties and Values]: https://www.w3.org/TR/css-logical-1/ 240 | [stylelint]: https://github.com/stylelint/stylelint 241 | [stylelint configuration]: https://github.com/stylelint/stylelint/blob/master/docs/user-guide/configuration.md#readme 242 | [Property Use Logical]: https://github.com/csstools/stylelint-use-logical 243 | -------------------------------------------------------------------------------- /.tape.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 'csstools/use-logical': [{ 3 | source: 'body { left: 0 }', 4 | args: 'always', 5 | warnings: 1, 6 | }, { 7 | source: 'body { left: 0 }', 8 | args: [ 'always', { except: 'left' }], 9 | warnings: 0, 10 | }, { 11 | source: 'body { top: -4px; left: 0; }', 12 | args: 'always', 13 | warnings: 2, 14 | }, { 15 | source: 'body { top: -4px; left: 0; }', 16 | args: ['always', { except: 'top' }], 17 | warnings: 1, 18 | }, { 19 | source: 'body { top: -4px; left: 0; }', 20 | args: ['always', { except: 'left' }], 21 | warnings: 1, 22 | }, { 23 | source: 'body { top: -4px; left: 0; }', 24 | args: ['always', { except: ['top', 'left'] }], 25 | warnings: 0, 26 | }, { 27 | source: 'body { margin-top: 0.5rem; margin-bottom: 0.5rem; }', 28 | args: ['always', { except: ['margin-top'] }], 29 | warnings: 1, 30 | }, { 31 | source: 'body { margin-top: 0.5rem; margin-bottom: 0.5rem; }', 32 | args: ['always', { except: ['margin-top', 'margin-bottom'] }], 33 | warnings: 0, 34 | }, { 35 | source: 'body { top: 0; left: 0 }', 36 | args: 'always', 37 | warnings: 2 38 | }, { 39 | source: 'body { border-left: 0; left: 0 }', 40 | args: 'always', 41 | warnings: 2 42 | }, { 43 | source: 'body { top: 0; margin-left: 0 }', 44 | args: 'always', 45 | warnings: 2 46 | }, { 47 | source: 'body { top: 0; margin-left: 0 }', 48 | args: [ 'always', { except: [ 'top', /^margin/ ] }], 49 | warnings: 0 50 | }, { 51 | source: 'body { padding-left: 0; margin-right: 0 }', 52 | args: 'always', 53 | warnings: 2, 54 | }, { 55 | source: 'body { clear: left }', 56 | args: 'always', 57 | warnings: 1, 58 | }, { 59 | source: 'body { float: left }', 60 | args: 'always', 61 | warnings: 1, 62 | }, { 63 | source: 'body { text-align: left }', 64 | args: 'always', 65 | warnings: 1, 66 | }, { 67 | source: 'body:dir(ltr) { top: 0; margin-left: 0; float: left }', 68 | args: 'always', 69 | warnings: 0 70 | }, { 71 | source: 'body { left: 0 }', 72 | expect: 'body { inset-inline-start: 0 }', 73 | args: 'always' 74 | }, { 75 | source: 'body { left: 0; right: 0 }', 76 | expect: 'body { inset-inline: 0 }', 77 | args: 'always' 78 | }, { 79 | source: 'body { top: 0; right: 0; bottom: 0; left: 0 }', 80 | expect: 'body { inset: 0 }', 81 | args: 'always' 82 | }, { 83 | source: 'body { margin-top: 0; margin-right: 0; margin-left: 0 }', 84 | expect: 'body { margin-block-start: 0; margin-inline: 0 }', 85 | args: 'always' 86 | }, { 87 | source: 'body { margin-left: 0; }', 88 | expect: 'body { margin-inline-start: 0; }', 89 | args: 'always' 90 | }, { 91 | source: 'body { clear: left }', 92 | expect: 'body { clear: inline-start }', 93 | args: 'always' 94 | }, { 95 | source: 'body { float: right }', 96 | expect: 'body { float: inline-end }', 97 | args: 'always' 98 | }, { 99 | source: 'body { text-align: left }', 100 | expect: 'body { text-align: start }', 101 | args: 'always' 102 | }, { 103 | source: 'body:dir(ltr) { text-align: left }', 104 | expect: 'body:dir(ltr) { text-align: left }', 105 | args: [ 'always' ] 106 | }, { 107 | source: 'body { float: left; text-align: left }', 108 | expect: 'body { float: left; text-align: start }', 109 | args: [ 'always', { 110 | except: [ /^float$/i ] 111 | }] 112 | }, { 113 | source: 'body { width: 0; }', 114 | expect: 'body { inline-size: 0; }', 115 | args: 'always' 116 | }, { 117 | source: 'body { min-width: 0; }', 118 | expect: 'body { min-inline-size: 0; }', 119 | args: 'always' 120 | }, { 121 | source: 'body { max-width: 0; }', 122 | expect: 'body { max-inline-size: 0; }', 123 | args: 'always' 124 | }, { 125 | source: 'body { height: 0; }', 126 | expect: 'body { block-size: 0; }', 127 | args: 'always' 128 | }, { 129 | source: 'body { min-height: 0; }', 130 | expect: 'body { min-block-size: 0; }', 131 | args: 'always' 132 | }, { 133 | source: 'body { max-height: 0; }', 134 | expect: 'body { max-block-size: 0; }', 135 | args: 'always' 136 | }, { 137 | source: 'body { border-left: 0; }', 138 | expect: 'body { border-inline-start: 0; }', 139 | args: 'always' 140 | }, { 141 | source: 'body { border-right: 0; }', 142 | expect: 'body { border-inline-end: 0; }', 143 | args: 'always' 144 | }, { 145 | source: 'body { border-top: 0; }', 146 | expect: 'body { border-block-start: 0; }', 147 | args: 'always' 148 | }, { 149 | source: 'body { border-bottom: 0; }', 150 | expect: 'body { border-block-end: 0; }', 151 | args: 'always' 152 | }, { 153 | source: 'body { border-left-color: 0; }', 154 | expect: 'body { border-inline-start-color: 0; }', 155 | args: 'always' 156 | }, { 157 | source: 'body { border-right-color: 0; }', 158 | expect: 'body { border-inline-end-color: 0; }', 159 | args: 'always' 160 | }, { 161 | source: 'body { border-top-color: 0; }', 162 | expect: 'body { border-block-start-color: 0; }', 163 | args: 'always' 164 | }, { 165 | source: 'body { border-bottom-color: 0; }', 166 | expect: 'body { border-block-end-color: 0; }', 167 | args: 'always' 168 | }, { 169 | source: 'body { border-left-style: 0; }', 170 | expect: 'body { border-inline-start-style: 0; }', 171 | args: 'always' 172 | }, { 173 | source: 'body { border-right-style: 0; }', 174 | expect: 'body { border-inline-end-style: 0; }', 175 | args: 'always' 176 | }, { 177 | source: 'body { border-top-style: 0; }', 178 | expect: 'body { border-block-start-style: 0; }', 179 | args: 'always' 180 | }, { 181 | source: 'body { border-bottom-style: 0; }', 182 | expect: 'body { border-block-end-style: 0; }', 183 | args: 'always' 184 | }, { 185 | source: 'body { border-left-width: 0; }', 186 | expect: 'body { border-inline-start-width: 0; }', 187 | args: 'always' 188 | }, { 189 | source: 'body { border-right-width: 0; }', 190 | expect: 'body { border-inline-end-width: 0; }', 191 | args: 'always' 192 | }, { 193 | source: 'body { border-top-width: 0; }', 194 | expect: 'body { border-block-start-width: 0; }', 195 | args: 'always' 196 | }, { 197 | source: 'body { border-bottom-width: 0; }', 198 | expect: 'body { border-block-end-width: 0; }', 199 | args: 'always' 200 | }, { 201 | source: 'body { border-top-left-radius: 0; }', 202 | expect: 'body { border-start-start-radius: 0; }', 203 | args: 'always' 204 | }, { 205 | source: 'body { border-top-right-radius: 0; }', 206 | expect: 'body { border-start-end-radius: 0; }', 207 | args: 'always' 208 | }, { 209 | source: 'body { border-bottom-left-radius: 0; }', 210 | expect: 'body { border-end-start-radius: 0; }', 211 | args: 'always' 212 | }, { 213 | source: 'body { border-bottom-right-radius: 0; }', 214 | expect: 'body { border-end-end-radius: 0; }', 215 | args: 'always' 216 | } 217 | ] 218 | }; 219 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # CC0 1.0 Universal 2 | 3 | ## Statement of Purpose 4 | 5 | The laws of most jurisdictions throughout the world automatically confer 6 | exclusive Copyright and Related Rights (defined below) upon the creator and 7 | subsequent owner(s) (each and all, an “owner”) of an original work of 8 | authorship and/or a database (each, a “Work”). 9 | 10 | Certain owners wish to permanently relinquish those rights to a Work for the 11 | purpose of contributing to a commons of creative, cultural and scientific works 12 | (“Commons”) that the public can reliably and without fear of later claims of 13 | infringement build upon, modify, incorporate in other works, reuse and 14 | redistribute as freely as possible in any form whatsoever and for any purposes, 15 | including without limitation commercial purposes. These owners may contribute 16 | to the Commons to promote the ideal of a free culture and the further 17 | production of creative, cultural and scientific works, or to gain reputation or 18 | greater distribution for their Work in part through the use and efforts of 19 | others. 20 | 21 | For these and/or other purposes and motivations, and without any expectation of 22 | additional consideration or compensation, the person associating CC0 with a 23 | Work (the “Affirmer”), to the extent that he or she is an owner of Copyright 24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and 25 | publicly distribute the Work under its terms, with knowledge of his or her 26 | Copyright and Related Rights in the Work and the meaning and intended legal 27 | effect of CC0 on those rights. 28 | 29 | 1. Copyright and Related Rights. A Work made available under CC0 may be 30 | protected by copyright and related or neighboring rights (“Copyright and 31 | Related Rights”). Copyright and Related Rights include, but are not limited 32 | to, the following: 33 | 1. the right to reproduce, adapt, distribute, perform, display, communicate, 34 | and translate a Work; 35 | 2. moral rights retained by the original author(s) and/or performer(s); 36 | 3. publicity and privacy rights pertaining to a person’s image or likeness 37 | depicted in a Work; 38 | 4. rights protecting against unfair competition in regards to a Work, 39 | subject to the limitations in paragraph 4(i), below; 40 | 5. rights protecting the extraction, dissemination, use and reuse of data in 41 | a Work; 42 | 6. database rights (such as those arising under Directive 96/9/EC of the 43 | European Parliament and of the Council of 11 March 1996 on the legal 44 | protection of databases, and under any national implementation thereof, 45 | including any amended or successor version of such directive); and 46 | 7. other similar, equivalent or corresponding rights throughout the world 47 | based on applicable law or treaty, and any national implementations 48 | thereof. 49 | 50 | 2. Waiver. To the greatest extent permitted by, but not in contravention of, 51 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and 52 | unconditionally waives, abandons, and surrenders all of Affirmer’s Copyright 53 | and Related Rights and associated claims and causes of action, whether now 54 | known or unknown (including existing as well as future claims and causes of 55 | action), in the Work (i) in all territories worldwide, (ii) for the maximum 56 | duration provided by applicable law or treaty (including future time 57 | extensions), (iii) in any current or future medium and for any number of 58 | copies, and (iv) for any purpose whatsoever, including without limitation 59 | commercial, advertising or promotional purposes (the “Waiver”). Affirmer 60 | makes the Waiver for the benefit of each member of the public at large and 61 | to the detriment of Affirmer’s heirs and successors, fully intending that 62 | such Waiver shall not be subject to revocation, rescission, cancellation, 63 | termination, or any other legal or equitable action to disrupt the quiet 64 | enjoyment of the Work by the public as contemplated by Affirmer’s express 65 | Statement of Purpose. 66 | 67 | 3. Public License Fallback. Should any part of the Waiver for any reason be 68 | judged legally invalid or ineffective under applicable law, then the Waiver 69 | shall be preserved to the maximum extent permitted taking into account 70 | Affirmer’s express Statement of Purpose. In addition, to the extent the 71 | Waiver is so judged Affirmer hereby grants to each affected person a 72 | royalty-free, non transferable, non sublicensable, non exclusive, 73 | irrevocable and unconditional license to exercise Affirmer’s Copyright and 74 | Related Rights in the Work (i) in all territories worldwide, (ii) for the 75 | maximum duration provided by applicable law or treaty (including future time 76 | extensions), (iii) in any current or future medium and for any number of 77 | copies, and (iv) for any purpose whatsoever, including without limitation 78 | commercial, advertising or promotional purposes (the “License”). The License 79 | shall be deemed effective as of the date CC0 was applied by Affirmer to the 80 | Work. Should any part of the License for any reason be judged legally 81 | invalid or ineffective under applicable law, such partial invalidity or 82 | ineffectiveness shall not invalidate the remainder of the License, and in 83 | such case Affirmer hereby affirms that he or she will not (i) exercise any 84 | of his or her remaining Copyright and Related Rights in the Work or (ii) 85 | assert any associated claims and causes of action with respect to the Work, 86 | in either case contrary to Affirmer’s express Statement of Purpose. 87 | 88 | 4. Limitations and Disclaimers. 89 | 1. No trademark or patent rights held by Affirmer are waived, abandoned, 90 | surrendered, licensed or otherwise affected by this document. 91 | 2. Affirmer offers the Work as-is and makes no representations or warranties 92 | of any kind concerning the Work, express, implied, statutory or 93 | otherwise, including without limitation warranties of title, 94 | merchantability, fitness for a particular purpose, non infringement, or 95 | the absence of latent or other defects, accuracy, or the present or 96 | absence of errors, whether or not discoverable, all to the greatest 97 | extent permissible under applicable law. 98 | 3. Affirmer disclaims responsibility for clearing rights of other persons 99 | that may apply to the Work or any use thereof, including without 100 | limitation any person’s Copyright and Related Rights in the Work. 101 | Further, Affirmer disclaims responsibility for obtaining any necessary 102 | consents, permissions or other rights required for any use of the Work. 103 | 4. Affirmer understands and acknowledges that Creative Commons is not a 104 | party to this document and has no duty or obligation with respect to this 105 | CC0 or use of the Work. 106 | 107 | For more information, please see 108 | http://creativecommons.org/publicdomain/zero/1.0/. 109 | -------------------------------------------------------------------------------- /index.mjs: -------------------------------------------------------------------------------- 1 | import stylelint from 'stylelint'; 2 | 3 | const inline = { 4 | start: { ltr: 'left', rtl: 'right' }, 5 | end: { ltr: 'right', rtl: 'left' } 6 | }; 7 | 8 | const physical4Prop = [ 9 | [ [ 'top', 'left', 'bottom', 'right' ], 'inset' ], 10 | [ [ 'margin-top', 'margin-left', 'margin-bottom', 'margin-right' ], 'margin' ], 11 | [ [ 'padding-top', 'padding-left', 'padding-bottom', 'padding-right' ], 'padding' ] 12 | ]; 13 | 14 | const physical2Prop = () => [ 15 | [ [ 'top', 'bottom' ], 'inset-block' ], 16 | [ [ 'left', 'right' ], 'inset-inline' ], 17 | 18 | [ [ 'margin-top', 'margin-bottom' ], 'margin-block' ], 19 | [ [ 'margin-left', 'margin-right' ], 'margin-inline' ], 20 | 21 | [ [ 'padding-top', 'padding-bottom' ], 'padding-block' ], 22 | [ [ 'padding-left', 'padding-right' ], 'padding-inline' ], 23 | ]; 24 | 25 | const physicalProp = dir => [ 26 | [ [ 'top' ], 'inset-block-start' ], 27 | [ [ 'bottom' ], 'inset-block-end' ], 28 | [ [ inline.start[dir] ], 'inset-inline-start' ], 29 | [ [ inline.end[dir] ], 'inset-inline-end' ], 30 | 31 | [ [ 'margin-top' ], 'margin-block-start' ], 32 | [ [ 'margin-bottom' ], 'margin-block-end' ], 33 | [ [ `margin-${inline.start[dir]}` ], 'margin-inline-start' ], 34 | [ [ `margin-${inline.end[dir]}` ], 'margin-inline-end' ], 35 | 36 | [ [ 'padding-top' ], 'padding-block-start' ], 37 | [ [ 'padding-bottom' ], 'padding-block-end' ], 38 | [ [ `padding-${inline.start[dir]}` ], 'padding-inline-start' ], 39 | [ [ `padding-${inline.end[dir]}` ], 'padding-inline-end' ], 40 | 41 | // width, height 42 | [ [ 'width' ], 'inline-size' ], 43 | [ [ 'min-width' ], 'min-inline-size' ], 44 | [ [ 'max-width' ], 'max-inline-size' ], 45 | [ [ 'height' ], 'block-size' ], 46 | [ [ 'min-height' ], 'min-block-size' ], 47 | [ [ 'max-height' ], 'max-block-size' ], 48 | 49 | // border 50 | [ [ 'border-top' ], 'border-block-start' ], 51 | [ [ 'border-bottom' ], 'border-block-end' ], 52 | [ [ `border-${inline.start[dir]}` ], 'border-inline-start' ], 53 | [ [ `border-${inline.end[dir]}` ], 'border-inline-end' ], 54 | 55 | [ [ 'border-top-color' ], 'border-block-start-color' ], 56 | [ [ 'border-top-style' ], 'border-block-start-style' ], 57 | [ [ 'border-top-width' ], 'border-block-start-width' ], 58 | [ [ 'border-bottom-color' ], 'border-block-end-color' ], 59 | [ [ 'border-bottom-style' ], 'border-block-end-style' ], 60 | [ [ 'border-bottom-width' ], 'border-block-end-width' ], 61 | 62 | 63 | [ [ `border-${inline.start[dir]}-color` ], 'border-inline-start-color' ], 64 | [ [ `border-${inline.start[dir]}-style` ], 'border-inline-start-style' ], 65 | [ [ `border-${inline.start[dir]}-width` ], 'border-inline-start-width' ], 66 | [ [ `border-${inline.end[dir]}-color` ], 'border-inline-end-color' ], 67 | [ [ `border-${inline.end[dir]}-style` ], 'border-inline-end-style' ], 68 | [ [ `border-${inline.end[dir]}-width` ], 'border-inline-end-width' ], 69 | 70 | 71 | 72 | [ [ `border-top-${inline.start[dir]}-radius` ], 'border-start-start-radius' ], 73 | [ [ `border-bottom-${inline.start[dir]}-radius` ], 'border-end-start-radius' ], 74 | [ [ `border-top-${inline.end[dir]}-radius` ], 'border-start-end-radius' ], 75 | [ [ `border-bottom-${inline.end[dir]}-radius` ], 'border-end-end-radius' ], 76 | 77 | ]; 78 | 79 | const physicalValue = dir => [ 80 | [ /^clear$/i, { 81 | [inline.start[dir]]: 'inline-start', 82 | [inline.end[dir]]: 'inline-end' 83 | }], 84 | [ /^float$/i, { 85 | [inline.start[dir]]: 'inline-start', 86 | [inline.end[dir]]: 'inline-end' 87 | }], 88 | [ /^text-align$/i, { 89 | [inline.start[dir]]: 'start', 90 | [inline.end[dir]]: 'end' 91 | }] 92 | ]; 93 | 94 | const validateRuleWithProps = (root, props, fn) => { 95 | // conditionally walk nodes with children 96 | if (root.nodes && root.nodes.length) { 97 | const args = []; 98 | 99 | const hasProps = props.every(prop => { 100 | const declIndex = root.nodes.findIndex(child => child.type === 'decl' && child.prop === prop); 101 | const decl = root.nodes[declIndex]; 102 | 103 | if (decl) { 104 | args.push(decl, declIndex); 105 | } 106 | 107 | return decl; 108 | }); 109 | 110 | if (hasProps) { 111 | fn(...args); 112 | } 113 | } 114 | }; 115 | 116 | var ruleName = 'csstools/use-logical'; 117 | 118 | var messages = stylelint.utils.ruleMessages(ruleName, { 119 | unexpectedProp(physicalProperty, logicalProperty) { 120 | return `Unexpected "${physicalProperty}" property. Use "${logicalProperty}".`; 121 | }, 122 | unexpectedValue(property, physicalValue, logicalValue) { 123 | return `Unexpected "${physicalValue}" value in "${property}" property. Use "${logicalValue}".`; 124 | } 125 | }); 126 | 127 | // walk all container nodes 128 | function walk(node, fn) { 129 | if (node.nodes && node.nodes.length) { 130 | const nodes = node.nodes.slice(); 131 | const length = nodes.length; 132 | let index = -1; 133 | 134 | while (++index < length) { 135 | const child = nodes[index]; 136 | 137 | if (!isDirRule(child)) { 138 | fn(child); 139 | 140 | walk(child, fn); 141 | } 142 | } 143 | } 144 | } 145 | 146 | const dirSelectorRegExp = /:dir\(ltr|rtl\)/i; 147 | const isDirRule = node => node.type === 'rule' && dirSelectorRegExp.test(node.selector); 148 | 149 | const reportedDecls = new WeakMap(); 150 | 151 | function ruleFunc(method, opts, context) { 152 | const propExceptions = [].concat(Object(opts).except || []); 153 | const isAutofix = isContextAutofixing(context); 154 | const dir = /^rtl$/i.test(Object(opts).direction) ? 'rtl' : 'ltr'; 155 | 156 | return (root, result) => { 157 | // validate the method 158 | const isMethodValid = stylelint.utils.validateOptions(result, ruleName, { 159 | actual: method, 160 | possible() { 161 | return isMethodIndifferent(method) || 162 | isMethodAlways(method) 163 | } 164 | }); 165 | 166 | const reportUnexpectedProperty = (decl, logicalProperty) => stylelint.utils.report({ 167 | message: messages.unexpectedProp(decl.prop, logicalProperty), 168 | node: decl, 169 | result, 170 | ruleName 171 | }); 172 | 173 | const reportUnexpectedValue = (node, value) => stylelint.utils.report({ 174 | message: messages.unexpectedValue(node.prop, node.value, value), 175 | node, 176 | result, 177 | ruleName 178 | }); 179 | 180 | if (isMethodValid && isMethodAlways(method)) { 181 | walk(root, node => { 182 | // validate or autofix 4 physical properties as logical shorthands 183 | physical4Prop.forEach(([ props, prop ]) => { 184 | validateRuleWithProps(node, props, (blockStartDecl, blockStartIndex, inlineStartDecl, inlineStartIndex, blockEndDecl, blockEndIndex, inlineEndDecl, inlineEndIndex) => { // eslint-disable-line 185 | if ( 186 | isDeclAnException(blockStartDecl, propExceptions) || 187 | isDeclAnException(inlineStartDecl, propExceptions) || 188 | isDeclAnException(blockEndDecl, propExceptions) || 189 | isDeclAnException(inlineEndDecl, propExceptions) 190 | ) { 191 | return; 192 | } 193 | 194 | const firstInlineDecl = blockStartDecl; 195 | 196 | if (isAutofix) { 197 | const values = [ blockStartDecl.value, inlineStartDecl.value, blockEndDecl.value, inlineEndDecl.value ]; 198 | 199 | if (values[1] === values[3]) { 200 | values.pop(); 201 | 202 | if (values[2] === values[1]) { 203 | values.pop(); 204 | 205 | if (values[1] === values[0]) { 206 | values.pop(); 207 | } 208 | } 209 | } 210 | 211 | firstInlineDecl.cloneBefore({ 212 | prop, 213 | value: values.length <= 2 ? values.join(' ') : `logical ${values.join(' ')}` 214 | }); 215 | 216 | blockStartDecl.remove(); 217 | inlineStartDecl.remove(); 218 | blockEndDecl.remove(); 219 | inlineEndDecl.remove(); 220 | } else if (!isDeclReported(blockStartDecl) && !isDeclReported(inlineStartDecl) && !isDeclReported(blockEndDecl) && !isDeclReported(inlineEndDecl)) { 221 | reportUnexpectedProperty(firstInlineDecl, prop); 222 | 223 | reportedDecls.set(blockStartDecl); 224 | reportedDecls.set(inlineStartDecl); 225 | reportedDecls.set(blockEndDecl); 226 | reportedDecls.set(inlineEndDecl); 227 | } 228 | }); 229 | }); 230 | 231 | // validate or autofix 2 physical properties as logical shorthands 232 | physical2Prop().forEach(([ props, prop ]) => { 233 | validateRuleWithProps(node, props, (blockStartDecl, blockStartIndex, inlineStartDecl, inlineStartIndex) => { // eslint-disable-line 234 | if ( 235 | isDeclAnException(blockStartDecl, propExceptions) || 236 | isDeclAnException(inlineStartDecl, propExceptions) 237 | ) { 238 | return; 239 | } 240 | 241 | const firstInlineDecl = blockStartIndex < inlineStartIndex 242 | ? blockStartDecl 243 | : inlineStartDecl; 244 | 245 | if (isAutofix) { 246 | firstInlineDecl.cloneBefore({ 247 | prop, 248 | value: blockStartDecl.value === inlineStartDecl.value 249 | ? blockStartDecl.value 250 | : [ blockStartDecl.value, inlineStartDecl.value ].join(' ') 251 | }); 252 | 253 | blockStartDecl.remove(); 254 | inlineStartDecl.remove(); 255 | } else if (!isDeclReported(blockStartDecl) && !isDeclReported(inlineStartDecl)) { 256 | reportUnexpectedProperty(firstInlineDecl, prop); 257 | 258 | reportedDecls.set(blockStartDecl); 259 | reportedDecls.set(inlineStartDecl); 260 | } 261 | }); 262 | }); 263 | 264 | // validate or autofix physical properties as logical 265 | physicalProp(dir).forEach(([ props, prop ]) => { 266 | validateRuleWithProps(node, props, physicalDecl => { 267 | if (isDeclAnException(physicalDecl, propExceptions)) { 268 | return; 269 | } 270 | 271 | if (isAutofix) { 272 | physicalDecl.prop = prop; 273 | } else if (!isDeclReported(physicalDecl)) { 274 | reportUnexpectedProperty(physicalDecl, prop); 275 | 276 | reportedDecls.set(physicalDecl); 277 | } 278 | }); 279 | }); 280 | 281 | // validate or autofix physical values as logical 282 | physicalValue(dir).forEach(([ regexp, props ]) => { 283 | if (!isNodeMatchingDecl(node, regexp)) { 284 | return; 285 | } 286 | 287 | if (isDeclAnException(node, propExceptions)) { 288 | return; 289 | } 290 | 291 | const valuekey = node.value.toLowerCase(); 292 | 293 | if (valuekey in props) { 294 | const value = props[valuekey]; 295 | 296 | if (isAutofix) { 297 | node.value = value; 298 | } else { 299 | reportUnexpectedValue(node, value); 300 | 301 | reportedDecls.set(node); 302 | } 303 | } 304 | }); 305 | }); 306 | } 307 | }; 308 | }ruleFunc.ruleName = ruleName; 309 | 310 | var index = stylelint.createPlugin(ruleName, ruleFunc); 311 | 312 | const isMethodIndifferent = method => method === 'ignore' || method === false || method === null; 313 | const isMethodAlways = method => method === 'always' || method === true; 314 | const isContextAutofixing = context => Boolean(Object(context).fix); 315 | const isNodeMatchingDecl = (decl, regexp) => decl.type === 'decl' && regexp.test(decl.prop); 316 | 317 | const isDeclAnException = (decl, propExceptions) => { 318 | if (!decl || decl.type !== 'decl') { 319 | return false; 320 | } 321 | 322 | return propExceptions.some((match) => { 323 | if (match instanceof RegExp) { 324 | return match.test(decl.prop); 325 | } 326 | 327 | return String(match || '').toLowerCase() === String(decl.prop || '').toLowerCase(); 328 | }); 329 | }; 330 | 331 | const isDeclReported = decl => reportedDecls.has(decl); 332 | 333 | export { index as default }; 334 | //# sourceMappingURL=index.mjs.map 335 | -------------------------------------------------------------------------------- /index.cjs: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var stylelint = require('stylelint'); 4 | 5 | const inline = { 6 | start: { ltr: 'left', rtl: 'right' }, 7 | end: { ltr: 'right', rtl: 'left' } 8 | }; 9 | 10 | const physical4Prop = [ 11 | [ [ 'top', 'left', 'bottom', 'right' ], 'inset' ], 12 | [ [ 'margin-top', 'margin-left', 'margin-bottom', 'margin-right' ], 'margin' ], 13 | [ [ 'padding-top', 'padding-left', 'padding-bottom', 'padding-right' ], 'padding' ] 14 | ]; 15 | 16 | const physical2Prop = () => [ 17 | [ [ 'top', 'bottom' ], 'inset-block' ], 18 | [ [ 'left', 'right' ], 'inset-inline' ], 19 | 20 | [ [ 'margin-top', 'margin-bottom' ], 'margin-block' ], 21 | [ [ 'margin-left', 'margin-right' ], 'margin-inline' ], 22 | 23 | [ [ 'padding-top', 'padding-bottom' ], 'padding-block' ], 24 | [ [ 'padding-left', 'padding-right' ], 'padding-inline' ], 25 | ]; 26 | 27 | const physicalProp = dir => [ 28 | [ [ 'top' ], 'inset-block-start' ], 29 | [ [ 'bottom' ], 'inset-block-end' ], 30 | [ [ inline.start[dir] ], 'inset-inline-start' ], 31 | [ [ inline.end[dir] ], 'inset-inline-end' ], 32 | 33 | [ [ 'margin-top' ], 'margin-block-start' ], 34 | [ [ 'margin-bottom' ], 'margin-block-end' ], 35 | [ [ `margin-${inline.start[dir]}` ], 'margin-inline-start' ], 36 | [ [ `margin-${inline.end[dir]}` ], 'margin-inline-end' ], 37 | 38 | [ [ 'padding-top' ], 'padding-block-start' ], 39 | [ [ 'padding-bottom' ], 'padding-block-end' ], 40 | [ [ `padding-${inline.start[dir]}` ], 'padding-inline-start' ], 41 | [ [ `padding-${inline.end[dir]}` ], 'padding-inline-end' ], 42 | 43 | // width, height 44 | [ [ 'width' ], 'inline-size' ], 45 | [ [ 'min-width' ], 'min-inline-size' ], 46 | [ [ 'max-width' ], 'max-inline-size' ], 47 | [ [ 'height' ], 'block-size' ], 48 | [ [ 'min-height' ], 'min-block-size' ], 49 | [ [ 'max-height' ], 'max-block-size' ], 50 | 51 | // border 52 | [ [ 'border-top' ], 'border-block-start' ], 53 | [ [ 'border-bottom' ], 'border-block-end' ], 54 | [ [ `border-${inline.start[dir]}` ], 'border-inline-start' ], 55 | [ [ `border-${inline.end[dir]}` ], 'border-inline-end' ], 56 | 57 | [ [ 'border-top-color' ], 'border-block-start-color' ], 58 | [ [ 'border-top-style' ], 'border-block-start-style' ], 59 | [ [ 'border-top-width' ], 'border-block-start-width' ], 60 | [ [ 'border-bottom-color' ], 'border-block-end-color' ], 61 | [ [ 'border-bottom-style' ], 'border-block-end-style' ], 62 | [ [ 'border-bottom-width' ], 'border-block-end-width' ], 63 | 64 | 65 | [ [ `border-${inline.start[dir]}-color` ], 'border-inline-start-color' ], 66 | [ [ `border-${inline.start[dir]}-style` ], 'border-inline-start-style' ], 67 | [ [ `border-${inline.start[dir]}-width` ], 'border-inline-start-width' ], 68 | [ [ `border-${inline.end[dir]}-color` ], 'border-inline-end-color' ], 69 | [ [ `border-${inline.end[dir]}-style` ], 'border-inline-end-style' ], 70 | [ [ `border-${inline.end[dir]}-width` ], 'border-inline-end-width' ], 71 | 72 | 73 | 74 | [ [ `border-top-${inline.start[dir]}-radius` ], 'border-start-start-radius' ], 75 | [ [ `border-bottom-${inline.start[dir]}-radius` ], 'border-end-start-radius' ], 76 | [ [ `border-top-${inline.end[dir]}-radius` ], 'border-start-end-radius' ], 77 | [ [ `border-bottom-${inline.end[dir]}-radius` ], 'border-end-end-radius' ], 78 | 79 | ]; 80 | 81 | const physicalValue = dir => [ 82 | [ /^clear$/i, { 83 | [inline.start[dir]]: 'inline-start', 84 | [inline.end[dir]]: 'inline-end' 85 | }], 86 | [ /^float$/i, { 87 | [inline.start[dir]]: 'inline-start', 88 | [inline.end[dir]]: 'inline-end' 89 | }], 90 | [ /^text-align$/i, { 91 | [inline.start[dir]]: 'start', 92 | [inline.end[dir]]: 'end' 93 | }] 94 | ]; 95 | 96 | const validateRuleWithProps = (root, props, fn) => { 97 | // conditionally walk nodes with children 98 | if (root.nodes && root.nodes.length) { 99 | const args = []; 100 | 101 | const hasProps = props.every(prop => { 102 | const declIndex = root.nodes.findIndex(child => child.type === 'decl' && child.prop === prop); 103 | const decl = root.nodes[declIndex]; 104 | 105 | if (decl) { 106 | args.push(decl, declIndex); 107 | } 108 | 109 | return decl; 110 | }); 111 | 112 | if (hasProps) { 113 | fn(...args); 114 | } 115 | } 116 | }; 117 | 118 | var ruleName = 'csstools/use-logical'; 119 | 120 | var messages = stylelint.utils.ruleMessages(ruleName, { 121 | unexpectedProp(physicalProperty, logicalProperty) { 122 | return `Unexpected "${physicalProperty}" property. Use "${logicalProperty}".`; 123 | }, 124 | unexpectedValue(property, physicalValue, logicalValue) { 125 | return `Unexpected "${physicalValue}" value in "${property}" property. Use "${logicalValue}".`; 126 | } 127 | }); 128 | 129 | // walk all container nodes 130 | function walk(node, fn) { 131 | if (node.nodes && node.nodes.length) { 132 | const nodes = node.nodes.slice(); 133 | const length = nodes.length; 134 | let index = -1; 135 | 136 | while (++index < length) { 137 | const child = nodes[index]; 138 | 139 | if (!isDirRule(child)) { 140 | fn(child); 141 | 142 | walk(child, fn); 143 | } 144 | } 145 | } 146 | } 147 | 148 | const dirSelectorRegExp = /:dir\(ltr|rtl\)/i; 149 | const isDirRule = node => node.type === 'rule' && dirSelectorRegExp.test(node.selector); 150 | 151 | const reportedDecls = new WeakMap(); 152 | 153 | function ruleFunc(method, opts, context) { 154 | const propExceptions = [].concat(Object(opts).except || []); 155 | const isAutofix = isContextAutofixing(context); 156 | const dir = /^rtl$/i.test(Object(opts).direction) ? 'rtl' : 'ltr'; 157 | 158 | return (root, result) => { 159 | // validate the method 160 | const isMethodValid = stylelint.utils.validateOptions(result, ruleName, { 161 | actual: method, 162 | possible() { 163 | return isMethodIndifferent(method) || 164 | isMethodAlways(method) 165 | } 166 | }); 167 | 168 | const reportUnexpectedProperty = (decl, logicalProperty) => stylelint.utils.report({ 169 | message: messages.unexpectedProp(decl.prop, logicalProperty), 170 | node: decl, 171 | result, 172 | ruleName 173 | }); 174 | 175 | const reportUnexpectedValue = (node, value) => stylelint.utils.report({ 176 | message: messages.unexpectedValue(node.prop, node.value, value), 177 | node, 178 | result, 179 | ruleName 180 | }); 181 | 182 | if (isMethodValid && isMethodAlways(method)) { 183 | walk(root, node => { 184 | // validate or autofix 4 physical properties as logical shorthands 185 | physical4Prop.forEach(([ props, prop ]) => { 186 | validateRuleWithProps(node, props, (blockStartDecl, blockStartIndex, inlineStartDecl, inlineStartIndex, blockEndDecl, blockEndIndex, inlineEndDecl, inlineEndIndex) => { // eslint-disable-line 187 | if ( 188 | isDeclAnException(blockStartDecl, propExceptions) || 189 | isDeclAnException(inlineStartDecl, propExceptions) || 190 | isDeclAnException(blockEndDecl, propExceptions) || 191 | isDeclAnException(inlineEndDecl, propExceptions) 192 | ) { 193 | return; 194 | } 195 | 196 | const firstInlineDecl = blockStartDecl; 197 | 198 | if (isAutofix) { 199 | const values = [ blockStartDecl.value, inlineStartDecl.value, blockEndDecl.value, inlineEndDecl.value ]; 200 | 201 | if (values[1] === values[3]) { 202 | values.pop(); 203 | 204 | if (values[2] === values[1]) { 205 | values.pop(); 206 | 207 | if (values[1] === values[0]) { 208 | values.pop(); 209 | } 210 | } 211 | } 212 | 213 | firstInlineDecl.cloneBefore({ 214 | prop, 215 | value: values.length <= 2 ? values.join(' ') : `logical ${values.join(' ')}` 216 | }); 217 | 218 | blockStartDecl.remove(); 219 | inlineStartDecl.remove(); 220 | blockEndDecl.remove(); 221 | inlineEndDecl.remove(); 222 | } else if (!isDeclReported(blockStartDecl) && !isDeclReported(inlineStartDecl) && !isDeclReported(blockEndDecl) && !isDeclReported(inlineEndDecl)) { 223 | reportUnexpectedProperty(firstInlineDecl, prop); 224 | 225 | reportedDecls.set(blockStartDecl); 226 | reportedDecls.set(inlineStartDecl); 227 | reportedDecls.set(blockEndDecl); 228 | reportedDecls.set(inlineEndDecl); 229 | } 230 | }); 231 | }); 232 | 233 | // validate or autofix 2 physical properties as logical shorthands 234 | physical2Prop().forEach(([ props, prop ]) => { 235 | validateRuleWithProps(node, props, (blockStartDecl, blockStartIndex, inlineStartDecl, inlineStartIndex) => { // eslint-disable-line 236 | if ( 237 | isDeclAnException(blockStartDecl, propExceptions) || 238 | isDeclAnException(inlineStartDecl, propExceptions) 239 | ) { 240 | return; 241 | } 242 | 243 | const firstInlineDecl = blockStartIndex < inlineStartIndex 244 | ? blockStartDecl 245 | : inlineStartDecl; 246 | 247 | if (isAutofix) { 248 | firstInlineDecl.cloneBefore({ 249 | prop, 250 | value: blockStartDecl.value === inlineStartDecl.value 251 | ? blockStartDecl.value 252 | : [ blockStartDecl.value, inlineStartDecl.value ].join(' ') 253 | }); 254 | 255 | blockStartDecl.remove(); 256 | inlineStartDecl.remove(); 257 | } else if (!isDeclReported(blockStartDecl) && !isDeclReported(inlineStartDecl)) { 258 | reportUnexpectedProperty(firstInlineDecl, prop); 259 | 260 | reportedDecls.set(blockStartDecl); 261 | reportedDecls.set(inlineStartDecl); 262 | } 263 | }); 264 | }); 265 | 266 | // validate or autofix physical properties as logical 267 | physicalProp(dir).forEach(([ props, prop ]) => { 268 | validateRuleWithProps(node, props, physicalDecl => { 269 | if (isDeclAnException(physicalDecl, propExceptions)) { 270 | return; 271 | } 272 | 273 | if (isAutofix) { 274 | physicalDecl.prop = prop; 275 | } else if (!isDeclReported(physicalDecl)) { 276 | reportUnexpectedProperty(physicalDecl, prop); 277 | 278 | reportedDecls.set(physicalDecl); 279 | } 280 | }); 281 | }); 282 | 283 | // validate or autofix physical values as logical 284 | physicalValue(dir).forEach(([ regexp, props ]) => { 285 | if (!isNodeMatchingDecl(node, regexp)) { 286 | return; 287 | } 288 | 289 | if (isDeclAnException(node, propExceptions)) { 290 | return; 291 | } 292 | 293 | const valuekey = node.value.toLowerCase(); 294 | 295 | if (valuekey in props) { 296 | const value = props[valuekey]; 297 | 298 | if (isAutofix) { 299 | node.value = value; 300 | } else { 301 | reportUnexpectedValue(node, value); 302 | 303 | reportedDecls.set(node); 304 | } 305 | } 306 | }); 307 | }); 308 | } 309 | }; 310 | }ruleFunc.ruleName = ruleName; 311 | 312 | var index = stylelint.createPlugin(ruleName, ruleFunc); 313 | 314 | const isMethodIndifferent = method => method === 'ignore' || method === false || method === null; 315 | const isMethodAlways = method => method === 'always' || method === true; 316 | const isContextAutofixing = context => Boolean(Object(context).fix); 317 | const isNodeMatchingDecl = (decl, regexp) => decl.type === 'decl' && regexp.test(decl.prop); 318 | 319 | const isDeclAnException = (decl, propExceptions) => { 320 | if (!decl || decl.type !== 'decl') { 321 | return false; 322 | } 323 | 324 | return propExceptions.some((match) => { 325 | if (match instanceof RegExp) { 326 | return match.test(decl.prop); 327 | } 328 | 329 | return String(match || '').toLowerCase() === String(decl.prop || '').toLowerCase(); 330 | }); 331 | }; 332 | 333 | const isDeclReported = decl => reportedDecls.has(decl); 334 | 335 | module.exports = index; 336 | //# sourceMappingURL=index.cjs.map 337 | -------------------------------------------------------------------------------- /index.mjs.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.mjs","sources":["lib/maps.js","lib/validate.js","lib/rule-name.js","lib/messages.js","lib/walk.js","index.js"],"sourcesContent":["const inline = {\n\tstart: { ltr: 'left', rtl: 'right' },\n\tend: { ltr: 'right', rtl: 'left' }\n}\n\nexport const physical4Prop = [\n\t[ [ 'top', 'left', 'bottom', 'right' ], 'inset' ],\n\t[ [ 'margin-top', 'margin-left', 'margin-bottom', 'margin-right' ], 'margin' ],\n\t[ [ 'padding-top', 'padding-left', 'padding-bottom', 'padding-right' ], 'padding' ]\n];\n\nexport const physical2Prop = () => [\n\t[ [ 'top', 'bottom' ], 'inset-block' ],\n\t[ [ 'left', 'right' ], 'inset-inline' ],\n\n\t[ [ 'margin-top', 'margin-bottom' ], 'margin-block' ],\n\t[ [ 'margin-left', 'margin-right' ], 'margin-inline' ],\n\n\t[ [ 'padding-top', 'padding-bottom' ], 'padding-block' ],\n\t[ [ 'padding-left', 'padding-right' ], 'padding-inline' ],\n];\n\nexport const physicalProp = dir => [\n\t[ [ 'top' ], 'inset-block-start' ],\n\t[ [ 'bottom' ], 'inset-block-end' ],\n\t[ [ inline.start[dir] ], 'inset-inline-start' ],\n\t[ [ inline.end[dir] ], 'inset-inline-end' ],\n\n\t[ [ 'margin-top' ], 'margin-block-start' ],\n\t[ [ 'margin-bottom' ], 'margin-block-end' ],\n\t[ [ `margin-${inline.start[dir]}` ], 'margin-inline-start' ],\n\t[ [ `margin-${inline.end[dir]}` ], 'margin-inline-end' ],\n\n\t[ [ 'padding-top' ], 'padding-block-start' ],\n\t[ [ 'padding-bottom' ], 'padding-block-end' ],\n\t[ [ `padding-${inline.start[dir]}` ], 'padding-inline-start' ],\n\t[ [ `padding-${inline.end[dir]}` ], 'padding-inline-end' ],\n\n\t// width, height\n\t[ [ 'width' ], 'inline-size' ],\n\t[ [ 'min-width' ], 'min-inline-size' ],\n\t[ [ 'max-width' ], 'max-inline-size' ],\n\t[ [ 'height' ], 'block-size' ],\n\t[ [ 'min-height' ], 'min-block-size' ],\n\t[ [ 'max-height' ], 'max-block-size' ],\n\n\t// border\n\t[ [ 'border-top' ], 'border-block-start' ],\n\t[ [ 'border-bottom' ], 'border-block-end' ],\n\t[ [ `border-${inline.start[dir]}` ], 'border-inline-start' ],\n\t[ [ `border-${inline.end[dir]}` ], 'border-inline-end' ],\n\n\t[ [ 'border-top-color' ], 'border-block-start-color' ],\n\t[ [ 'border-top-style' ], 'border-block-start-style' ],\n\t[ [ 'border-top-width' ], 'border-block-start-width' ],\n\t[ [ 'border-bottom-color' ], 'border-block-end-color' ],\n\t[ [ 'border-bottom-style' ], 'border-block-end-style' ],\n\t[ [ 'border-bottom-width' ], 'border-block-end-width' ],\n\n\n\t[ [ `border-${inline.start[dir]}-color` ], 'border-inline-start-color' ],\n\t[ [ `border-${inline.start[dir]}-style` ], 'border-inline-start-style' ],\n\t[ [ `border-${inline.start[dir]}-width` ], 'border-inline-start-width' ],\n\t[ [ `border-${inline.end[dir]}-color` ], 'border-inline-end-color' ],\n\t[ [ `border-${inline.end[dir]}-style` ], 'border-inline-end-style' ],\n\t[ [ `border-${inline.end[dir]}-width` ], 'border-inline-end-width' ],\n\n\n\n\t[ [ `border-top-${inline.start[dir]}-radius` ], 'border-start-start-radius' ],\n\t[ [ `border-bottom-${inline.start[dir]}-radius` ], 'border-end-start-radius' ],\n\t[ [ `border-top-${inline.end[dir]}-radius` ], 'border-start-end-radius' ],\n\t[ [ `border-bottom-${inline.end[dir]}-radius` ], 'border-end-end-radius' ],\n\n];\n\nexport const physicalValue = dir => [\n\t[ /^clear$/i, {\n\t\t[inline.start[dir]]: 'inline-start',\n\t\t[inline.end[dir]]: 'inline-end'\n\t}],\n\t[ /^float$/i, {\n\t\t[inline.start[dir]]: 'inline-start',\n\t\t[inline.end[dir]]: 'inline-end'\n\t}],\n\t[ /^text-align$/i, {\n\t\t[inline.start[dir]]: 'start',\n\t\t[inline.end[dir]]: 'end'\n\t}]\n];\n","export const validateRuleWithProps = (root, props, fn) => {\n\t// conditionally walk nodes with children\n\tif (root.nodes && root.nodes.length) {\n\t\tconst args = [];\n\n\t\tconst hasProps = props.every(prop => {\n\t\t\tconst declIndex = root.nodes.findIndex(child => child.type === 'decl' && child.prop === prop);\n\t\t\tconst decl = root.nodes[declIndex];\n\n\t\t\tif (decl) {\n\t\t\t\targs.push(decl, declIndex);\n\t\t\t}\n\n\t\t\treturn decl;\n\t\t});\n\n\t\tif (hasProps) {\n\t\t\tfn(...args);\n\t\t}\n\t}\n};\n","export default 'csstools/use-logical';\n","import stylelint from 'stylelint';\nimport ruleName from './rule-name';\n\nexport default stylelint.utils.ruleMessages(ruleName, {\n\tunexpectedProp(physicalProperty, logicalProperty) {\n\t\treturn `Unexpected \"${physicalProperty}\" property. Use \"${logicalProperty}\".`;\n\t},\n\tunexpectedValue(property, physicalValue, logicalValue) {\n\t\treturn `Unexpected \"${physicalValue}\" value in \"${property}\" property. Use \"${logicalValue}\".`;\n\t}\n});\n","// walk all container nodes\nexport default function walk(node, fn) {\n\tif (node.nodes && node.nodes.length) {\n\t\tconst nodes = node.nodes.slice();\n\t\tconst length = nodes.length;\n\t\tlet index = -1;\n\n\t\twhile (++index < length) {\n\t\t\tconst child = nodes[index];\n\n\t\t\tif (!isDirRule(child)) {\n\t\t\t\tfn(child);\n\n\t\t\t\twalk(child, fn);\n\t\t\t}\n\t\t}\n\t}\n}\n\nconst dirSelectorRegExp = /:dir\\(ltr|rtl\\)/i;\nconst isDirRule = node => node.type === 'rule' && dirSelectorRegExp.test(node.selector);\n","import stylelint from 'stylelint';\nimport { physicalProp, physical2Prop, physical4Prop, physicalValue } from './lib/maps';\nimport { validateRuleWithProps } from './lib/validate';\nimport ruleName from './lib/rule-name';\nimport messages from './lib/messages';\nimport walk from './lib/walk';\n\nconst reportedDecls = new WeakMap();\n\nfunction ruleFunc(method, opts, context) {\n\tconst propExceptions = [].concat(Object(opts).except || []);\n\tconst isAutofix = isContextAutofixing(context);\n\tconst dir = /^rtl$/i.test(Object(opts).direction) ? 'rtl' : 'ltr';\n\n\treturn (root, result) => {\n\t\t// validate the method\n\t\tconst isMethodValid = stylelint.utils.validateOptions(result, ruleName, {\n\t\t\tactual: method,\n\t\t\tpossible() {\n\t\t\t\treturn isMethodIndifferent(method) ||\n\t\t\t\t\tisMethodAlways(method)\n\t\t\t}\n\t\t});\n\n\t\tconst reportUnexpectedProperty = (decl, logicalProperty) => stylelint.utils.report({\n\t\t\tmessage: messages.unexpectedProp(decl.prop, logicalProperty),\n\t\t\tnode: decl,\n\t\t\tresult,\n\t\t\truleName\n\t\t});\n\n\t\tconst reportUnexpectedValue = (node, value) => stylelint.utils.report({\n\t\t\tmessage: messages.unexpectedValue(node.prop, node.value, value),\n\t\t\tnode,\n\t\t\tresult,\n\t\t\truleName\n\t\t});\n\n\t\tif (isMethodValid && isMethodAlways(method)) {\n\t\t\twalk(root, node => {\n\t\t\t\t// validate or autofix 4 physical properties as logical shorthands\n\t\t\t\tphysical4Prop.forEach(([ props, prop ]) => {\n\t\t\t\t\tvalidateRuleWithProps(node, props, (blockStartDecl, blockStartIndex, inlineStartDecl, inlineStartIndex, blockEndDecl, blockEndIndex, inlineEndDecl, inlineEndIndex) => { // eslint-disable-line\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tisDeclAnException(blockStartDecl, propExceptions) ||\n\t\t\t\t\t\t\tisDeclAnException(inlineStartDecl, propExceptions) ||\n\t\t\t\t\t\t\tisDeclAnException(blockEndDecl, propExceptions) ||\n\t\t\t\t\t\t\tisDeclAnException(inlineEndDecl, propExceptions)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst firstInlineDecl = blockStartDecl;\n\n\t\t\t\t\t\tif (isAutofix) {\n\t\t\t\t\t\t\tconst values = [ blockStartDecl.value, inlineStartDecl.value, blockEndDecl.value, inlineEndDecl.value ];\n\n\t\t\t\t\t\t\tif (values[1] === values[3]) {\n\t\t\t\t\t\t\t\tvalues.pop();\n\n\t\t\t\t\t\t\t\tif (values[2] === values[1]) {\n\t\t\t\t\t\t\t\t\tvalues.pop();\n\n\t\t\t\t\t\t\t\t\tif (values[1] === values[0]) {\n\t\t\t\t\t\t\t\t\t\tvalues.pop();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tfirstInlineDecl.cloneBefore({\n\t\t\t\t\t\t\t\tprop,\n\t\t\t\t\t\t\t\tvalue: values.length <= 2 ? values.join(' ') : `logical ${values.join(' ')}`\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tblockStartDecl.remove();\n\t\t\t\t\t\t\tinlineStartDecl.remove();\n\t\t\t\t\t\t\tblockEndDecl.remove();\n\t\t\t\t\t\t\tinlineEndDecl.remove();\n\t\t\t\t\t\t} else if (!isDeclReported(blockStartDecl) && !isDeclReported(inlineStartDecl) && !isDeclReported(blockEndDecl) && !isDeclReported(inlineEndDecl)) {\n\t\t\t\t\t\t\treportUnexpectedProperty(firstInlineDecl, prop);\n\n\t\t\t\t\t\t\treportedDecls.set(blockStartDecl);\n\t\t\t\t\t\t\treportedDecls.set(inlineStartDecl);\n\t\t\t\t\t\t\treportedDecls.set(blockEndDecl);\n\t\t\t\t\t\t\treportedDecls.set(inlineEndDecl);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\t// validate or autofix 2 physical properties as logical shorthands\n\t\t\t\tphysical2Prop().forEach(([ props, prop ]) => {\n\t\t\t\t\tvalidateRuleWithProps(node, props, (blockStartDecl, blockStartIndex, inlineStartDecl, inlineStartIndex) => { // eslint-disable-line\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tisDeclAnException(blockStartDecl, propExceptions) ||\n\t\t\t\t\t\t\tisDeclAnException(inlineStartDecl, propExceptions)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst firstInlineDecl = blockStartIndex < inlineStartIndex\n\t\t\t\t\t\t\t? blockStartDecl\n\t\t\t\t\t\t: inlineStartDecl;\n\n\t\t\t\t\t\tif (isAutofix) {\n\t\t\t\t\t\t\tfirstInlineDecl.cloneBefore({\n\t\t\t\t\t\t\t\tprop,\n\t\t\t\t\t\t\t\tvalue: blockStartDecl.value === inlineStartDecl.value\n\t\t\t\t\t\t\t\t\t? blockStartDecl.value\n\t\t\t\t\t\t\t\t: [ blockStartDecl.value, inlineStartDecl.value ].join(' ')\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tblockStartDecl.remove();\n\t\t\t\t\t\t\tinlineStartDecl.remove();\n\t\t\t\t\t\t} else if (!isDeclReported(blockStartDecl) && !isDeclReported(inlineStartDecl)) {\n\t\t\t\t\t\t\treportUnexpectedProperty(firstInlineDecl, prop);\n\n\t\t\t\t\t\t\treportedDecls.set(blockStartDecl);\n\t\t\t\t\t\t\treportedDecls.set(inlineStartDecl);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\t// validate or autofix physical properties as logical\n\t\t\t\tphysicalProp(dir).forEach(([ props, prop ]) => {\n\t\t\t\t\tvalidateRuleWithProps(node, props, physicalDecl => {\n\t\t\t\t\t\tif (isDeclAnException(physicalDecl, propExceptions)) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (isAutofix) {\n\t\t\t\t\t\t\tphysicalDecl.prop = prop;\n\t\t\t\t\t\t} else if (!isDeclReported(physicalDecl)) {\n\t\t\t\t\t\t\treportUnexpectedProperty(physicalDecl, prop);\n\n\t\t\t\t\t\t\treportedDecls.set(physicalDecl);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\t// validate or autofix physical values as logical\n\t\t\t\tphysicalValue(dir).forEach(([ regexp, props ]) => {\n\t\t\t\t\tif (!isNodeMatchingDecl(node, regexp)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (isDeclAnException(node, propExceptions)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst valuekey = node.value.toLowerCase();\n\n\t\t\t\t\tif (valuekey in props) {\n\t\t\t\t\t\tconst value = props[valuekey];\n\n\t\t\t\t\t\tif (isAutofix) {\n\t\t\t\t\t\t\tnode.value = value;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treportUnexpectedValue(node, value);\n\n\t\t\t\t\t\t\treportedDecls.set(node);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t};\n};\nruleFunc.ruleName = ruleName;\n\nexport default stylelint.createPlugin(ruleName, ruleFunc);\n\nconst isMethodIndifferent = method => method === 'ignore' || method === false || method === null;\nconst isMethodAlways = method => method === 'always' || method === true;\nconst isContextAutofixing = context => Boolean(Object(context).fix);\nconst isNodeMatchingDecl = (decl, regexp) => decl.type === 'decl' && regexp.test(decl.prop);\n\nconst isDeclAnException = (decl, propExceptions) => {\n\tif (!decl || decl.type !== 'decl') {\n\t\treturn false;\n\t}\n\n\treturn propExceptions.some((match) => {\n\t\tif (match instanceof RegExp) {\n\t\t\treturn match.test(decl.prop);\n\t\t}\n\n\t\treturn String(match || '').toLowerCase() === String(decl.prop || '').toLowerCase();\n\t});\n}\n\nconst isDeclReported = decl => reportedDecls.has(decl);\n"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /index.cjs.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.cjs","sources":["lib/maps.js","lib/validate.js","lib/rule-name.js","lib/messages.js","lib/walk.js","index.js"],"sourcesContent":["const inline = {\n\tstart: { ltr: 'left', rtl: 'right' },\n\tend: { ltr: 'right', rtl: 'left' }\n}\n\nexport const physical4Prop = [\n\t[ [ 'top', 'left', 'bottom', 'right' ], 'inset' ],\n\t[ [ 'margin-top', 'margin-left', 'margin-bottom', 'margin-right' ], 'margin' ],\n\t[ [ 'padding-top', 'padding-left', 'padding-bottom', 'padding-right' ], 'padding' ]\n];\n\nexport const physical2Prop = () => [\n\t[ [ 'top', 'bottom' ], 'inset-block' ],\n\t[ [ 'left', 'right' ], 'inset-inline' ],\n\n\t[ [ 'margin-top', 'margin-bottom' ], 'margin-block' ],\n\t[ [ 'margin-left', 'margin-right' ], 'margin-inline' ],\n\n\t[ [ 'padding-top', 'padding-bottom' ], 'padding-block' ],\n\t[ [ 'padding-left', 'padding-right' ], 'padding-inline' ],\n];\n\nexport const physicalProp = dir => [\n\t[ [ 'top' ], 'inset-block-start' ],\n\t[ [ 'bottom' ], 'inset-block-end' ],\n\t[ [ inline.start[dir] ], 'inset-inline-start' ],\n\t[ [ inline.end[dir] ], 'inset-inline-end' ],\n\n\t[ [ 'margin-top' ], 'margin-block-start' ],\n\t[ [ 'margin-bottom' ], 'margin-block-end' ],\n\t[ [ `margin-${inline.start[dir]}` ], 'margin-inline-start' ],\n\t[ [ `margin-${inline.end[dir]}` ], 'margin-inline-end' ],\n\n\t[ [ 'padding-top' ], 'padding-block-start' ],\n\t[ [ 'padding-bottom' ], 'padding-block-end' ],\n\t[ [ `padding-${inline.start[dir]}` ], 'padding-inline-start' ],\n\t[ [ `padding-${inline.end[dir]}` ], 'padding-inline-end' ],\n\n\t// width, height\n\t[ [ 'width' ], 'inline-size' ],\n\t[ [ 'min-width' ], 'min-inline-size' ],\n\t[ [ 'max-width' ], 'max-inline-size' ],\n\t[ [ 'height' ], 'block-size' ],\n\t[ [ 'min-height' ], 'min-block-size' ],\n\t[ [ 'max-height' ], 'max-block-size' ],\n\n\t// border\n\t[ [ 'border-top' ], 'border-block-start' ],\n\t[ [ 'border-bottom' ], 'border-block-end' ],\n\t[ [ `border-${inline.start[dir]}` ], 'border-inline-start' ],\n\t[ [ `border-${inline.end[dir]}` ], 'border-inline-end' ],\n\n\t[ [ 'border-top-color' ], 'border-block-start-color' ],\n\t[ [ 'border-top-style' ], 'border-block-start-style' ],\n\t[ [ 'border-top-width' ], 'border-block-start-width' ],\n\t[ [ 'border-bottom-color' ], 'border-block-end-color' ],\n\t[ [ 'border-bottom-style' ], 'border-block-end-style' ],\n\t[ [ 'border-bottom-width' ], 'border-block-end-width' ],\n\n\n\t[ [ `border-${inline.start[dir]}-color` ], 'border-inline-start-color' ],\n\t[ [ `border-${inline.start[dir]}-style` ], 'border-inline-start-style' ],\n\t[ [ `border-${inline.start[dir]}-width` ], 'border-inline-start-width' ],\n\t[ [ `border-${inline.end[dir]}-color` ], 'border-inline-end-color' ],\n\t[ [ `border-${inline.end[dir]}-style` ], 'border-inline-end-style' ],\n\t[ [ `border-${inline.end[dir]}-width` ], 'border-inline-end-width' ],\n\n\n\n\t[ [ `border-top-${inline.start[dir]}-radius` ], 'border-start-start-radius' ],\n\t[ [ `border-bottom-${inline.start[dir]}-radius` ], 'border-end-start-radius' ],\n\t[ [ `border-top-${inline.end[dir]}-radius` ], 'border-start-end-radius' ],\n\t[ [ `border-bottom-${inline.end[dir]}-radius` ], 'border-end-end-radius' ],\n\n];\n\nexport const physicalValue = dir => [\n\t[ /^clear$/i, {\n\t\t[inline.start[dir]]: 'inline-start',\n\t\t[inline.end[dir]]: 'inline-end'\n\t}],\n\t[ /^float$/i, {\n\t\t[inline.start[dir]]: 'inline-start',\n\t\t[inline.end[dir]]: 'inline-end'\n\t}],\n\t[ /^text-align$/i, {\n\t\t[inline.start[dir]]: 'start',\n\t\t[inline.end[dir]]: 'end'\n\t}]\n];\n","export const validateRuleWithProps = (root, props, fn) => {\n\t// conditionally walk nodes with children\n\tif (root.nodes && root.nodes.length) {\n\t\tconst args = [];\n\n\t\tconst hasProps = props.every(prop => {\n\t\t\tconst declIndex = root.nodes.findIndex(child => child.type === 'decl' && child.prop === prop);\n\t\t\tconst decl = root.nodes[declIndex];\n\n\t\t\tif (decl) {\n\t\t\t\targs.push(decl, declIndex);\n\t\t\t}\n\n\t\t\treturn decl;\n\t\t});\n\n\t\tif (hasProps) {\n\t\t\tfn(...args);\n\t\t}\n\t}\n};\n","export default 'csstools/use-logical';\n","import stylelint from 'stylelint';\nimport ruleName from './rule-name';\n\nexport default stylelint.utils.ruleMessages(ruleName, {\n\tunexpectedProp(physicalProperty, logicalProperty) {\n\t\treturn `Unexpected \"${physicalProperty}\" property. Use \"${logicalProperty}\".`;\n\t},\n\tunexpectedValue(property, physicalValue, logicalValue) {\n\t\treturn `Unexpected \"${physicalValue}\" value in \"${property}\" property. Use \"${logicalValue}\".`;\n\t}\n});\n","// walk all container nodes\nexport default function walk(node, fn) {\n\tif (node.nodes && node.nodes.length) {\n\t\tconst nodes = node.nodes.slice();\n\t\tconst length = nodes.length;\n\t\tlet index = -1;\n\n\t\twhile (++index < length) {\n\t\t\tconst child = nodes[index];\n\n\t\t\tif (!isDirRule(child)) {\n\t\t\t\tfn(child);\n\n\t\t\t\twalk(child, fn);\n\t\t\t}\n\t\t}\n\t}\n}\n\nconst dirSelectorRegExp = /:dir\\(ltr|rtl\\)/i;\nconst isDirRule = node => node.type === 'rule' && dirSelectorRegExp.test(node.selector);\n","import stylelint from 'stylelint';\nimport { physicalProp, physical2Prop, physical4Prop, physicalValue } from './lib/maps';\nimport { validateRuleWithProps } from './lib/validate';\nimport ruleName from './lib/rule-name';\nimport messages from './lib/messages';\nimport walk from './lib/walk';\n\nconst reportedDecls = new WeakMap();\n\nfunction ruleFunc(method, opts, context) {\n\tconst propExceptions = [].concat(Object(opts).except || []);\n\tconst isAutofix = isContextAutofixing(context);\n\tconst dir = /^rtl$/i.test(Object(opts).direction) ? 'rtl' : 'ltr';\n\n\treturn (root, result) => {\n\t\t// validate the method\n\t\tconst isMethodValid = stylelint.utils.validateOptions(result, ruleName, {\n\t\t\tactual: method,\n\t\t\tpossible() {\n\t\t\t\treturn isMethodIndifferent(method) ||\n\t\t\t\t\tisMethodAlways(method)\n\t\t\t}\n\t\t});\n\n\t\tconst reportUnexpectedProperty = (decl, logicalProperty) => stylelint.utils.report({\n\t\t\tmessage: messages.unexpectedProp(decl.prop, logicalProperty),\n\t\t\tnode: decl,\n\t\t\tresult,\n\t\t\truleName\n\t\t});\n\n\t\tconst reportUnexpectedValue = (node, value) => stylelint.utils.report({\n\t\t\tmessage: messages.unexpectedValue(node.prop, node.value, value),\n\t\t\tnode,\n\t\t\tresult,\n\t\t\truleName\n\t\t});\n\n\t\tif (isMethodValid && isMethodAlways(method)) {\n\t\t\twalk(root, node => {\n\t\t\t\t// validate or autofix 4 physical properties as logical shorthands\n\t\t\t\tphysical4Prop.forEach(([ props, prop ]) => {\n\t\t\t\t\tvalidateRuleWithProps(node, props, (blockStartDecl, blockStartIndex, inlineStartDecl, inlineStartIndex, blockEndDecl, blockEndIndex, inlineEndDecl, inlineEndIndex) => { // eslint-disable-line\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tisDeclAnException(blockStartDecl, propExceptions) ||\n\t\t\t\t\t\t\tisDeclAnException(inlineStartDecl, propExceptions) ||\n\t\t\t\t\t\t\tisDeclAnException(blockEndDecl, propExceptions) ||\n\t\t\t\t\t\t\tisDeclAnException(inlineEndDecl, propExceptions)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst firstInlineDecl = blockStartDecl;\n\n\t\t\t\t\t\tif (isAutofix) {\n\t\t\t\t\t\t\tconst values = [ blockStartDecl.value, inlineStartDecl.value, blockEndDecl.value, inlineEndDecl.value ];\n\n\t\t\t\t\t\t\tif (values[1] === values[3]) {\n\t\t\t\t\t\t\t\tvalues.pop();\n\n\t\t\t\t\t\t\t\tif (values[2] === values[1]) {\n\t\t\t\t\t\t\t\t\tvalues.pop();\n\n\t\t\t\t\t\t\t\t\tif (values[1] === values[0]) {\n\t\t\t\t\t\t\t\t\t\tvalues.pop();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tfirstInlineDecl.cloneBefore({\n\t\t\t\t\t\t\t\tprop,\n\t\t\t\t\t\t\t\tvalue: values.length <= 2 ? values.join(' ') : `logical ${values.join(' ')}`\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tblockStartDecl.remove();\n\t\t\t\t\t\t\tinlineStartDecl.remove();\n\t\t\t\t\t\t\tblockEndDecl.remove();\n\t\t\t\t\t\t\tinlineEndDecl.remove();\n\t\t\t\t\t\t} else if (!isDeclReported(blockStartDecl) && !isDeclReported(inlineStartDecl) && !isDeclReported(blockEndDecl) && !isDeclReported(inlineEndDecl)) {\n\t\t\t\t\t\t\treportUnexpectedProperty(firstInlineDecl, prop);\n\n\t\t\t\t\t\t\treportedDecls.set(blockStartDecl);\n\t\t\t\t\t\t\treportedDecls.set(inlineStartDecl);\n\t\t\t\t\t\t\treportedDecls.set(blockEndDecl);\n\t\t\t\t\t\t\treportedDecls.set(inlineEndDecl);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\t// validate or autofix 2 physical properties as logical shorthands\n\t\t\t\tphysical2Prop().forEach(([ props, prop ]) => {\n\t\t\t\t\tvalidateRuleWithProps(node, props, (blockStartDecl, blockStartIndex, inlineStartDecl, inlineStartIndex) => { // eslint-disable-line\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tisDeclAnException(blockStartDecl, propExceptions) ||\n\t\t\t\t\t\t\tisDeclAnException(inlineStartDecl, propExceptions)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst firstInlineDecl = blockStartIndex < inlineStartIndex\n\t\t\t\t\t\t\t? blockStartDecl\n\t\t\t\t\t\t: inlineStartDecl;\n\n\t\t\t\t\t\tif (isAutofix) {\n\t\t\t\t\t\t\tfirstInlineDecl.cloneBefore({\n\t\t\t\t\t\t\t\tprop,\n\t\t\t\t\t\t\t\tvalue: blockStartDecl.value === inlineStartDecl.value\n\t\t\t\t\t\t\t\t\t? blockStartDecl.value\n\t\t\t\t\t\t\t\t: [ blockStartDecl.value, inlineStartDecl.value ].join(' ')\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tblockStartDecl.remove();\n\t\t\t\t\t\t\tinlineStartDecl.remove();\n\t\t\t\t\t\t} else if (!isDeclReported(blockStartDecl) && !isDeclReported(inlineStartDecl)) {\n\t\t\t\t\t\t\treportUnexpectedProperty(firstInlineDecl, prop);\n\n\t\t\t\t\t\t\treportedDecls.set(blockStartDecl);\n\t\t\t\t\t\t\treportedDecls.set(inlineStartDecl);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\t// validate or autofix physical properties as logical\n\t\t\t\tphysicalProp(dir).forEach(([ props, prop ]) => {\n\t\t\t\t\tvalidateRuleWithProps(node, props, physicalDecl => {\n\t\t\t\t\t\tif (isDeclAnException(physicalDecl, propExceptions)) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (isAutofix) {\n\t\t\t\t\t\t\tphysicalDecl.prop = prop;\n\t\t\t\t\t\t} else if (!isDeclReported(physicalDecl)) {\n\t\t\t\t\t\t\treportUnexpectedProperty(physicalDecl, prop);\n\n\t\t\t\t\t\t\treportedDecls.set(physicalDecl);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\t// validate or autofix physical values as logical\n\t\t\t\tphysicalValue(dir).forEach(([ regexp, props ]) => {\n\t\t\t\t\tif (!isNodeMatchingDecl(node, regexp)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (isDeclAnException(node, propExceptions)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst valuekey = node.value.toLowerCase();\n\n\t\t\t\t\tif (valuekey in props) {\n\t\t\t\t\t\tconst value = props[valuekey];\n\n\t\t\t\t\t\tif (isAutofix) {\n\t\t\t\t\t\t\tnode.value = value;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treportUnexpectedValue(node, value);\n\n\t\t\t\t\t\t\treportedDecls.set(node);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t};\n};\nruleFunc.ruleName = ruleName;\n\nexport default stylelint.createPlugin(ruleName, ruleFunc);\n\nconst isMethodIndifferent = method => method === 'ignore' || method === false || method === null;\nconst isMethodAlways = method => method === 'always' || method === true;\nconst isContextAutofixing = context => Boolean(Object(context).fix);\nconst isNodeMatchingDecl = (decl, regexp) => decl.type === 'decl' && regexp.test(decl.prop);\n\nconst isDeclAnException = (decl, propExceptions) => {\n\tif (!decl || decl.type !== 'decl') {\n\t\treturn false;\n\t}\n\n\treturn propExceptions.some((match) => {\n\t\tif (match instanceof RegExp) {\n\t\t\treturn match.test(decl.prop);\n\t\t}\n\n\t\treturn String(match || '').toLowerCase() === String(decl.prop || '').toLowerCase();\n\t});\n}\n\nconst isDeclReported = decl => reportedDecls.has(decl);\n"],"names":[],"mappings":"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"} --------------------------------------------------------------------------------