linter-bundle 5.1.0 → 6.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.linter-bundle.js +2 -0
- package/CHANGELOG.md +83 -9
- package/README.md +5 -3
- package/TODO.md +5 -0
- package/eslint/index.cjs +10 -4
- package/eslint/overrides-javascript.cjs +7 -1
- package/eslint/overrides-jest.cjs +1 -0
- package/eslint/overrides-jsdoc.cjs +1 -0
- package/eslint/rules/no-global-undefined-check.js +5 -3
- package/eslint/rules/no-unnecessary-typeof.js +26 -24
- package/eslint/rules/restricted-filenames.js +3 -1
- package/helper/ensure-type.cjs +2 -2
- package/helper/get-git-files.js +1 -1
- package/helper/get-outdated-dependencies.js +1 -1
- package/helper/get-outdated-overrides.js +1 -1
- package/helper/get-stylelint-path.js +1 -1
- package/helper/is-npm-or-yarn.js +1 -1
- package/helper/linter-bundle-config.js +22 -7
- package/helper/run-process.js +3 -3
- package/lint.js +31 -35
- package/package.json +27 -26
- package/stylelint/index.cjs +90 -5
- package/stylelint/plugins/stylelint-15.11.0-stylistic/LICENSE +20 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/html-tags/LICENSE +9 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/html-tags/index.cjs +122 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/reference/selectors.cjs +327 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/at-rule-name-case/README.md +110 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/at-rule-name-case/index.cjs +66 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/at-rule-name-space-after/README.md +117 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/at-rule-name-space-after/index.cjs +55 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/at-rule-semicolon-newline-after/README.md +63 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/at-rule-semicolon-newline-after/index.cjs +87 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/at-rule-semicolon-space-before/README.md +50 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/at-rule-semicolon-space-before/index.cjs +70 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/atRuleNameSpaceChecker.cjs +56 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/block-closing-brace-empty-line-before/README.md +238 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/block-closing-brace-empty-line-before/index.cjs +130 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/block-closing-brace-newline-after/README.md +196 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/block-closing-brace-newline-after/index.cjs +154 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/block-closing-brace-newline-before/README.md +93 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/block-closing-brace-newline-before/index.cjs +133 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/block-closing-brace-space-before/README.md +174 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/block-closing-brace-space-before/index.cjs +111 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/block-opening-brace-newline-after/README.md +138 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/block-opening-brace-newline-after/index.cjs +184 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/block-opening-brace-space-after/README.md +191 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/block-opening-brace-space-after/index.cjs +118 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/block-opening-brace-space-before/README.md +218 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/block-opening-brace-space-before/index.cjs +141 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/color-hex-case/README.md +58 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/color-hex-case/index.cjs +95 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-bang-space-after/README.md +72 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-bang-space-after/index.cjs +95 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-bang-space-before/README.md +67 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-bang-space-before/index.cjs +96 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-block-semicolon-newline-after/README.md +141 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-block-semicolon-newline-after/index.cjs +109 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-block-semicolon-newline-before/README.md +120 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-block-semicolon-newline-before/index.cjs +75 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-block-semicolon-space-after/README.md +147 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-block-semicolon-space-after/index.cjs +97 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-block-semicolon-space-before/README.md +130 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-block-semicolon-space-before/index.cjs +106 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-block-trailing-semicolon/README.md +108 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-block-trailing-semicolon/index.cjs +147 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-colon-newline-after/README.md +78 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-colon-newline-after/index.cjs +99 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-colon-space-after/README.md +111 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-colon-space-after/index.cjs +75 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-colon-space-before/README.md +72 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-colon-space-before/index.cjs +74 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declarationBangSpaceChecker.cjs +63 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declarationColonSpaceChecker.cjs +58 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/findMediaOperator.cjs +32 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-comma-newline-after/README.md +113 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-comma-newline-after/index.cjs +61 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-comma-newline-before/README.md +129 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-comma-newline-before/index.cjs +61 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-comma-space-after/README.md +144 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-comma-space-after/index.cjs +62 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-comma-space-before/README.md +144 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-comma-space-before/index.cjs +62 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-max-empty-lines/README.md +78 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-max-empty-lines/index.cjs +115 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-parentheses-newline-inside/README.md +144 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-parentheses-newline-inside/index.cjs +282 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-parentheses-space-inside/README.md +140 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-parentheses-space-inside/index.cjs +182 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-whitespace-after/README.md +80 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-whitespace-after/index.cjs +198 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/functionCommaSpaceChecker.cjs +125 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/functionCommaSpaceFix.cjs +51 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/indentation/README.md +339 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/indentation/index.cjs +743 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/linebreaks/README.md +21 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/linebreaks/index.cjs +132 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/max-empty-lines/README.md +116 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/max-empty-lines/index.cjs +225 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/max-line-length/README.md +151 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/max-line-length/index.cjs +200 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-feature-colon-space-after/README.md +72 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-feature-colon-space-after/index.cjs +91 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-feature-colon-space-before/README.md +72 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-feature-colon-space-before/index.cjs +91 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-feature-name-case/README.md +108 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-feature-name-case/index.cjs +93 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-feature-parentheses-space-inside/README.md +62 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-feature-parentheses-space-inside/index.cjs +112 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-feature-range-operator-space-after/README.md +72 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-feature-range-operator-space-after/index.cjs +109 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-feature-range-operator-space-before/README.md +72 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-feature-range-operator-space-before/index.cjs +109 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-query-list-comma-newline-after/README.md +113 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-query-list-comma-newline-after/index.cjs +97 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-query-list-comma-newline-before/README.md +111 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-query-list-comma-newline-before/index.cjs +49 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-query-list-comma-space-after/README.md +136 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-query-list-comma-space-after/index.cjs +93 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-query-list-comma-space-before/README.md +136 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-query-list-comma-space-before/index.cjs +93 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/mediaFeatureColonSpaceChecker.cjs +54 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/mediaQueryListCommaWhitespaceChecker.cjs +73 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/no-empty-first-line/README.md +34 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/no-empty-first-line/index.cjs +63 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/no-eol-whitespace/README.md +79 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/no-eol-whitespace/index.cjs +302 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/no-extra-semicolons/README.md +78 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/no-extra-semicolons/index.cjs +246 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/no-missing-end-of-source-newline/README.md +34 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/no-missing-end-of-source-newline/index.cjs +62 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/number-leading-zero/README.md +74 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/number-leading-zero/index.cjs +197 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/number-no-trailing-zeros/README.md +40 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/number-no-trailing-zeros/index.cjs +139 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/property-case/README.md +192 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/property-case/index.cjs +95 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-attribute-brackets-space-inside/README.md +112 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-attribute-brackets-space-inside/index.cjs +214 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-attribute-operator-space-after/README.md +162 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-attribute-operator-space-after/index.cjs +109 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-attribute-operator-space-before/README.md +162 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-attribute-operator-space-before/index.cjs +88 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-combinator-space-after/README.md +78 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-combinator-space-after/index.cjs +67 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-combinator-space-before/README.md +78 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-combinator-space-before/index.cjs +67 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-descendant-combinator-no-non-space/README.md +40 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-descendant-combinator-no-non-space/index.cjs +95 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-list-comma-newline-after/README.md +120 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-list-comma-newline-after/index.cjs +126 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-list-comma-newline-before/README.md +112 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-list-comma-newline-before/index.cjs +101 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-list-comma-space-after/README.md +110 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-list-comma-space-after/index.cjs +92 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-list-comma-space-before/README.md +110 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-list-comma-space-before/index.cjs +92 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-max-empty-lines/README.md +103 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-max-empty-lines/index.cjs +74 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-pseudo-class-case/README.md +108 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-pseudo-class-case/index.cjs +104 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-pseudo-class-parentheses-space-inside/README.md +62 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-pseudo-class-parentheses-space-inside/index.cjs +162 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-pseudo-element-case/README.md +128 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-pseudo-element-case/index.cjs +90 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selectorAttributeOperatorSpaceChecker.cjs +95 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selectorCombinatorSpaceChecker.cjs +113 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selectorListCommaWhitespaceChecker.cjs +64 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/string-quotes/README.md +130 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/string-quotes/index.cjs +256 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/unicode-bom/README.md +41 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/unicode-bom/index.cjs +67 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/unit-case/README.md +126 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/unit-case/index.cjs +133 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/value-list-comma-newline-after/README.md +102 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/value-list-comma-newline-after/index.cjs +107 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/value-list-comma-newline-before/README.md +100 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/value-list-comma-newline-before/index.cjs +49 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/value-list-comma-space-after/README.md +136 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/value-list-comma-space-after/index.cjs +94 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/value-list-comma-space-before/README.md +136 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/value-list-comma-space-before/index.cjs +94 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/value-list-max-empty-lines/README.md +121 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/value-list-max-empty-lines/index.cjs +68 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/valueListCommaWhitespaceChecker.cjs +74 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/style-search/LICENSE +13 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/style-search/index.cjs +216 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/utils/addEmptyLineAfter.cjs +30 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/utils/hasEmptyBlock.cjs +14 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/utils/nextNonCommentNode.cjs +21 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/utils/removeEmptyLinesAfter.cjs +16 -0
- package/stylelint/plugins/stylelint-15.11.0-stylistic/utils/whitespaceChecker.cjs +361 -0
- package/stylelint/plugins/stylelint-selector-no-empty.js +8 -8
- package/stylelint/plugins/stylelint-selector-tag-no-without-class.js +4 -4
- package/stylelint/plugins/stylelint-high-performance-animation.js +0 -276
- package/stylelint/plugins/stylelint-stylistic.js +0 -188
|
@@ -0,0 +1,743 @@
|
|
|
1
|
+
/* eslint-disable -- We want to keep as much of the original code as possible */
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
|
|
4
|
+
const stylelint = require('stylelint');
|
|
5
|
+
const beforeBlockString = require('stylelint/lib/utils/beforeBlockString.cjs');
|
|
6
|
+
const hasBlock = require('stylelint/lib/utils/hasBlock.cjs');
|
|
7
|
+
const optionsMatches = require('stylelint/lib/utils/optionsMatches.cjs');
|
|
8
|
+
const report = require('stylelint/lib/utils/report.cjs');
|
|
9
|
+
const ruleMessages = require('stylelint/lib/utils/ruleMessages.cjs');
|
|
10
|
+
const { isAtRule, isDeclaration, isRoot, isRule } = require('stylelint/lib/utils/typeGuards.cjs');
|
|
11
|
+
const validateOptions = require('stylelint/lib/utils/validateOptions.cjs');
|
|
12
|
+
const { isBoolean, isNumber, isString, assertString } = require('stylelint/lib/utils/validateTypes.cjs');
|
|
13
|
+
|
|
14
|
+
const styleSearch = require('../../style-search/index.cjs');
|
|
15
|
+
|
|
16
|
+
const ruleName = 'plugin/indentation';
|
|
17
|
+
const messages = ruleMessages(ruleName, {
|
|
18
|
+
expected: (x) => `Expected indentation of ${x}`
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const meta = {
|
|
22
|
+
url: 'https://github.com/jens-duttke/linter-bundle/blob/main/stylelint/plugins/stylelint-15.11.0-stylistic/rules/indentation/README.md',
|
|
23
|
+
fixable: true
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/** @type {import('stylelint').Rule} */
|
|
27
|
+
const rule = (primary, secondaryOptions = {}, context) => (root, result) => {
|
|
28
|
+
const validOptions = validateOptions(
|
|
29
|
+
result,
|
|
30
|
+
ruleName,
|
|
31
|
+
{
|
|
32
|
+
actual: primary,
|
|
33
|
+
possible: [isNumber, 'tab']
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
actual: secondaryOptions,
|
|
37
|
+
possible: {
|
|
38
|
+
baseIndentLevel: [isNumber, 'auto'],
|
|
39
|
+
except: ['block', 'value', 'param'],
|
|
40
|
+
ignore: ['value', 'param', 'inside-parens'],
|
|
41
|
+
indentInsideParens: ['twice', 'once-at-root-twice-in-block'],
|
|
42
|
+
indentClosingBrace: [isBoolean]
|
|
43
|
+
},
|
|
44
|
+
optional: true
|
|
45
|
+
}
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
if (!validOptions) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const spaceCount = isNumber(primary) ? primary : null;
|
|
53
|
+
const indentChar = spaceCount == null ? '\t' : ' '.repeat(spaceCount);
|
|
54
|
+
const warningWord = primary === 'tab' ? 'tab' : 'space';
|
|
55
|
+
|
|
56
|
+
/** @type {number | 'auto'} */
|
|
57
|
+
const baseIndentLevel = secondaryOptions.baseIndentLevel;
|
|
58
|
+
/** @type {boolean} */
|
|
59
|
+
const indentClosingBrace = secondaryOptions.indentClosingBrace;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @param {number} level
|
|
63
|
+
*/
|
|
64
|
+
const legibleExpectation = (level) => {
|
|
65
|
+
const count = spaceCount == null ? level : level * spaceCount;
|
|
66
|
+
const quantifiedWarningWord = count === 1 ? warningWord : `${warningWord}s`;
|
|
67
|
+
|
|
68
|
+
return `${count} ${quantifiedWarningWord}`;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// Cycle through all nodes using walk.
|
|
72
|
+
root.walk((node) => {
|
|
73
|
+
if (isRoot(node)) {
|
|
74
|
+
// Ignore nested template literals root in css-in-js lang
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const nodeLevel = indentationLevel(node);
|
|
79
|
+
|
|
80
|
+
// Cut out any * and _ hacks from `before`
|
|
81
|
+
const before = (node.raws.before || '').replace(/[*_]$/, '');
|
|
82
|
+
const after = typeof node.raws.after === 'string' ? node.raws.after : '';
|
|
83
|
+
const parent = node.parent;
|
|
84
|
+
|
|
85
|
+
if (!parent) { throw new Error('A parent node must be present'); }
|
|
86
|
+
|
|
87
|
+
const expectedOpeningBraceIndentation = indentChar.repeat(nodeLevel);
|
|
88
|
+
|
|
89
|
+
// Only inspect the spaces before the node
|
|
90
|
+
// if this is the first node in root
|
|
91
|
+
// or there is a newline in the `before` string.
|
|
92
|
+
// (If there is no newline before a node,
|
|
93
|
+
// there is no "indentation" to check.)
|
|
94
|
+
const isFirstChild = parent.type === 'root' && parent.first === node;
|
|
95
|
+
const lastIndexOfNewline = before.lastIndexOf('\n');
|
|
96
|
+
|
|
97
|
+
// Inspect whitespace in the `before` string that is
|
|
98
|
+
// *after* the *last* newline character,
|
|
99
|
+
// because anything besides that is not indentation for this node:
|
|
100
|
+
// it is some other kind of separation, checked by some separate rule
|
|
101
|
+
if (
|
|
102
|
+
(lastIndexOfNewline !== -1 ||
|
|
103
|
+
(isFirstChild &&
|
|
104
|
+
(!getDocument(parent) ||
|
|
105
|
+
(parent.raws.codeBefore?.endsWith('\n'))))) &&
|
|
106
|
+
before.slice(lastIndexOfNewline + 1) !== expectedOpeningBraceIndentation
|
|
107
|
+
) {
|
|
108
|
+
if (context.fix) {
|
|
109
|
+
if (isFirstChild && isString(node.raws.before)) {
|
|
110
|
+
node.raws.before = node.raws.before.replace(
|
|
111
|
+
/^[\t ]*(?=\S|$)/,
|
|
112
|
+
expectedOpeningBraceIndentation
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
node.raws.before = fixIndentation(node.raws.before, expectedOpeningBraceIndentation);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
report({
|
|
120
|
+
message: messages.expected(legibleExpectation(nodeLevel)),
|
|
121
|
+
node,
|
|
122
|
+
result,
|
|
123
|
+
ruleName
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Only blocks have the `after` string to check.
|
|
129
|
+
// Only inspect `after` strings that start with a newline;
|
|
130
|
+
// otherwise there's no indentation involved.
|
|
131
|
+
// And check `indentClosingBrace` to see if it should be indented an extra level.
|
|
132
|
+
const closingBraceLevel = indentClosingBrace ? nodeLevel + 1 : nodeLevel;
|
|
133
|
+
const expectedClosingBraceIndentation = indentChar.repeat(closingBraceLevel);
|
|
134
|
+
|
|
135
|
+
if (
|
|
136
|
+
(isRule(node) || isAtRule(node)) &&
|
|
137
|
+
hasBlock(node) &&
|
|
138
|
+
after &&
|
|
139
|
+
after.includes('\n') &&
|
|
140
|
+
after.slice(after.lastIndexOf('\n') + 1) !== expectedClosingBraceIndentation
|
|
141
|
+
) {
|
|
142
|
+
if (context.fix) {
|
|
143
|
+
node.raws.after = fixIndentation(node.raws.after, expectedClosingBraceIndentation);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
report({
|
|
147
|
+
message: messages.expected(legibleExpectation(closingBraceLevel)),
|
|
148
|
+
node,
|
|
149
|
+
index: node.toString().length - 1,
|
|
150
|
+
result,
|
|
151
|
+
ruleName
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// If this is a declaration, check the value
|
|
157
|
+
if (isDeclaration(node)) {
|
|
158
|
+
checkValue(node, nodeLevel);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// If this is a rule, check the selector
|
|
162
|
+
if (isRule(node)) {
|
|
163
|
+
checkSelector(node, nodeLevel);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// If this is an at rule, check the params
|
|
167
|
+
if (isAtRule(node)) {
|
|
168
|
+
checkAtRuleParameters(node, nodeLevel);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* @param {import('postcss').Node} node
|
|
174
|
+
* @param {number} level
|
|
175
|
+
* @returns {number}
|
|
176
|
+
*/
|
|
177
|
+
function indentationLevel (node, level = 0) {
|
|
178
|
+
if (!node.parent) { throw new Error('A parent node must be present'); }
|
|
179
|
+
|
|
180
|
+
if (isRoot(node.parent)) {
|
|
181
|
+
return level + getRootBaseIndentLevel(node.parent, baseIndentLevel, primary);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
let calculatedLevel;
|
|
185
|
+
|
|
186
|
+
// Indentation level equals the ancestor nodes
|
|
187
|
+
// separating this node from root; so recursively
|
|
188
|
+
// run this operation
|
|
189
|
+
calculatedLevel = indentationLevel(node.parent, level + 1);
|
|
190
|
+
|
|
191
|
+
// If `secondaryOptions.except` includes "block",
|
|
192
|
+
// blocks are taken down one from their calculated level
|
|
193
|
+
// (all blocks are the same level as their parents)
|
|
194
|
+
if (
|
|
195
|
+
optionsMatches(secondaryOptions, 'except', 'block') &&
|
|
196
|
+
(isRule(node) || isAtRule(node)) &&
|
|
197
|
+
hasBlock(node)
|
|
198
|
+
) {
|
|
199
|
+
calculatedLevel--;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return calculatedLevel;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* @param {import('postcss').Declaration} decl
|
|
207
|
+
* @param {number} declLevel
|
|
208
|
+
*/
|
|
209
|
+
function checkValue (decl, declLevel) {
|
|
210
|
+
if (!decl.value.includes('\n')) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (optionsMatches(secondaryOptions, 'ignore', 'value')) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const declString = decl.toString();
|
|
219
|
+
const valueLevel = optionsMatches(secondaryOptions, 'except', 'value') ?
|
|
220
|
+
declLevel
|
|
221
|
+
: declLevel + 1;
|
|
222
|
+
|
|
223
|
+
checkMultilineBit(declString, valueLevel, decl);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* @param {import('postcss').Rule} ruleNode
|
|
228
|
+
* @param {number} ruleLevel
|
|
229
|
+
*/
|
|
230
|
+
function checkSelector (ruleNode, ruleLevel) {
|
|
231
|
+
const selector = ruleNode.selector;
|
|
232
|
+
|
|
233
|
+
// Less mixins have params, and they should be indented extra
|
|
234
|
+
// @ts-expect-error -- TS2339: Property 'params' does not exist on type 'Rule'.
|
|
235
|
+
if (ruleNode.params) {
|
|
236
|
+
ruleLevel += 1;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
checkMultilineBit(selector, ruleLevel, ruleNode);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* @param {import('postcss').AtRule} atRule
|
|
244
|
+
* @param {number} ruleLevel
|
|
245
|
+
*/
|
|
246
|
+
function checkAtRuleParameters (atRule, ruleLevel) {
|
|
247
|
+
if (optionsMatches(secondaryOptions, 'ignore', 'param')) {
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// @nest and SCSS's @at-root rules should be treated like regular rules, not expected
|
|
252
|
+
// to have their params (selectors) indented
|
|
253
|
+
const parameterLevel =
|
|
254
|
+
optionsMatches(secondaryOptions, 'except', 'param') ||
|
|
255
|
+
atRule.name === 'nest' ||
|
|
256
|
+
atRule.name === 'at-root' ?
|
|
257
|
+
ruleLevel
|
|
258
|
+
: ruleLevel + 1;
|
|
259
|
+
|
|
260
|
+
checkMultilineBit(beforeBlockString(atRule).trim(), parameterLevel, atRule);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* @param {string} source
|
|
265
|
+
* @param {number} newlineIndentLevel
|
|
266
|
+
* @param {import('postcss').Node} node
|
|
267
|
+
*/
|
|
268
|
+
function checkMultilineBit (source, newlineIndentLevel, node) {
|
|
269
|
+
if (!source.includes('\n')) {
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Data for current node fixing
|
|
274
|
+
/** @type {Array<{ expectedIndentation: string, currentIndentation: string, startIndex: number }>} */
|
|
275
|
+
const fixPositions = [];
|
|
276
|
+
|
|
277
|
+
// `outsideParens` because function arguments and also non-standard parenthesized stuff like
|
|
278
|
+
// Sass maps are ignored to allow for arbitrary indentation
|
|
279
|
+
let parentheticalDepth = 0;
|
|
280
|
+
|
|
281
|
+
const ignoreInsideParans = optionsMatches(secondaryOptions, 'ignore', 'inside-parens');
|
|
282
|
+
|
|
283
|
+
styleSearch(
|
|
284
|
+
{
|
|
285
|
+
source,
|
|
286
|
+
target: '\n',
|
|
287
|
+
// @ts-expect-error -- The `outsideParens` option is unsupported. Why?
|
|
288
|
+
outsideParens: ignoreInsideParans
|
|
289
|
+
},
|
|
290
|
+
(match, matchCount) => {
|
|
291
|
+
const precedesClosingParenthesis = (/^[\t ]*\)/).test(source.slice(match.startIndex + 1));
|
|
292
|
+
|
|
293
|
+
if (ignoreInsideParans && (precedesClosingParenthesis || match.insideParens)) {
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
let expectedIndentLevel = newlineIndentLevel;
|
|
298
|
+
|
|
299
|
+
// Modififications for parenthetical content
|
|
300
|
+
if (!ignoreInsideParans && match.insideParens) {
|
|
301
|
+
// If the first match in is within parentheses, reduce the parenthesis penalty
|
|
302
|
+
if (matchCount === 1) { parentheticalDepth -= 1; }
|
|
303
|
+
|
|
304
|
+
// Account for windows line endings
|
|
305
|
+
let newlineIndex = match.startIndex;
|
|
306
|
+
|
|
307
|
+
if (source[match.startIndex - 1] === '\r') {
|
|
308
|
+
newlineIndex--;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
const followsOpeningParenthesis = (/\([\t ]*$/).test(source.slice(0, newlineIndex));
|
|
312
|
+
|
|
313
|
+
if (followsOpeningParenthesis) {
|
|
314
|
+
parentheticalDepth += 1;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const followsOpeningBrace = (/{[\t ]*$/).test(source.slice(0, newlineIndex));
|
|
318
|
+
|
|
319
|
+
if (followsOpeningBrace) {
|
|
320
|
+
parentheticalDepth += 1;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
const startingClosingBrace = (/^[\t ]*}/).test(source.slice(match.startIndex + 1));
|
|
324
|
+
|
|
325
|
+
if (startingClosingBrace) {
|
|
326
|
+
parentheticalDepth -= 1;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
expectedIndentLevel += parentheticalDepth;
|
|
330
|
+
|
|
331
|
+
// Past this point, adjustments to parentheticalDepth affect next line
|
|
332
|
+
|
|
333
|
+
if (precedesClosingParenthesis) {
|
|
334
|
+
parentheticalDepth -= 1;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
switch (secondaryOptions.indentInsideParens) {
|
|
338
|
+
case 'twice':
|
|
339
|
+
if (!precedesClosingParenthesis || indentClosingBrace) {
|
|
340
|
+
expectedIndentLevel += 1;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
break;
|
|
344
|
+
case 'once-at-root-twice-in-block':
|
|
345
|
+
if (node.parent === node.root()) {
|
|
346
|
+
if (precedesClosingParenthesis && !indentClosingBrace) {
|
|
347
|
+
expectedIndentLevel -= 1;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
break;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
if (!precedesClosingParenthesis || indentClosingBrace) {
|
|
354
|
+
expectedIndentLevel += 1;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
break;
|
|
358
|
+
default:
|
|
359
|
+
if (precedesClosingParenthesis && !indentClosingBrace) {
|
|
360
|
+
expectedIndentLevel -= 1;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Starting at the index after the newline, we want to
|
|
366
|
+
// check that the whitespace characters (excluding newlines) before the first
|
|
367
|
+
// non-whitespace character equal the expected indentation
|
|
368
|
+
const afterNewlineSpaceMatches = (/^([\t ]*)\S/).exec(source.slice(match.startIndex + 1));
|
|
369
|
+
|
|
370
|
+
if (!afterNewlineSpaceMatches) {
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
const afterNewlineSpace = afterNewlineSpaceMatches[1] || '';
|
|
375
|
+
const expectedIndentation = indentChar.repeat(
|
|
376
|
+
expectedIndentLevel > 0 ? expectedIndentLevel : 0
|
|
377
|
+
);
|
|
378
|
+
|
|
379
|
+
if (afterNewlineSpace !== expectedIndentation) {
|
|
380
|
+
if (context.fix) {
|
|
381
|
+
// Adding fixes position in reverse order, because if we change indent in the beginning of the string it will break all following fixes for that string
|
|
382
|
+
fixPositions.unshift({
|
|
383
|
+
expectedIndentation,
|
|
384
|
+
currentIndentation: afterNewlineSpace,
|
|
385
|
+
startIndex: match.startIndex
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
else {
|
|
389
|
+
report({
|
|
390
|
+
message: messages.expected(legibleExpectation(expectedIndentLevel)),
|
|
391
|
+
node,
|
|
392
|
+
index: match.startIndex + afterNewlineSpace.length + 1,
|
|
393
|
+
result,
|
|
394
|
+
ruleName
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
);
|
|
400
|
+
|
|
401
|
+
if (fixPositions.length > 0) {
|
|
402
|
+
if (isRule(node)) {
|
|
403
|
+
for (const fixPosition of fixPositions) {
|
|
404
|
+
node.selector = replaceIndentation(
|
|
405
|
+
node.selector,
|
|
406
|
+
fixPosition.currentIndentation,
|
|
407
|
+
fixPosition.expectedIndentation,
|
|
408
|
+
fixPosition.startIndex
|
|
409
|
+
);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
if (isDeclaration(node)) {
|
|
414
|
+
const declProperty = node.prop;
|
|
415
|
+
const declBetween = node.raws.between;
|
|
416
|
+
|
|
417
|
+
if (!isString(declBetween)) {
|
|
418
|
+
throw new TypeError('The `between` property must be a string');
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
for (const fixPosition of fixPositions) {
|
|
422
|
+
if (fixPosition.startIndex < declProperty.length + declBetween.length) {
|
|
423
|
+
node.raws.between = replaceIndentation(
|
|
424
|
+
declBetween,
|
|
425
|
+
fixPosition.currentIndentation,
|
|
426
|
+
fixPosition.expectedIndentation,
|
|
427
|
+
fixPosition.startIndex - declProperty.length
|
|
428
|
+
);
|
|
429
|
+
}
|
|
430
|
+
else {
|
|
431
|
+
node.value = replaceIndentation(
|
|
432
|
+
node.value,
|
|
433
|
+
fixPosition.currentIndentation,
|
|
434
|
+
fixPosition.expectedIndentation,
|
|
435
|
+
fixPosition.startIndex - declProperty.length - declBetween.length
|
|
436
|
+
);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
if (isAtRule(node)) {
|
|
442
|
+
const atRuleName = node.name;
|
|
443
|
+
const atRuleAfterName = node.raws.afterName;
|
|
444
|
+
const atRuleParameters = node.params;
|
|
445
|
+
|
|
446
|
+
if (!isString(atRuleAfterName)) {
|
|
447
|
+
throw new TypeError('The `afterName` property must be a string');
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
for (const fixPosition of fixPositions) {
|
|
451
|
+
// 1 — it's a @ length
|
|
452
|
+
if (fixPosition.startIndex < 1 + atRuleName.length + atRuleAfterName.length) {
|
|
453
|
+
node.raws.afterName = replaceIndentation(
|
|
454
|
+
atRuleAfterName,
|
|
455
|
+
fixPosition.currentIndentation,
|
|
456
|
+
fixPosition.expectedIndentation,
|
|
457
|
+
fixPosition.startIndex - atRuleName.length - 1
|
|
458
|
+
);
|
|
459
|
+
}
|
|
460
|
+
else {
|
|
461
|
+
node.params = replaceIndentation(
|
|
462
|
+
atRuleParameters,
|
|
463
|
+
fixPosition.currentIndentation,
|
|
464
|
+
fixPosition.expectedIndentation,
|
|
465
|
+
fixPosition.startIndex - atRuleName.length - atRuleAfterName.length - 1
|
|
466
|
+
);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
};
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* @param {import('postcss').Root} root
|
|
476
|
+
* @param {number | 'auto'} baseIndentLevel
|
|
477
|
+
* @param {string} space
|
|
478
|
+
* @returns {number}
|
|
479
|
+
*/
|
|
480
|
+
function getRootBaseIndentLevel (root, baseIndentLevel, space) {
|
|
481
|
+
const document = getDocument(root);
|
|
482
|
+
|
|
483
|
+
if (!document) {
|
|
484
|
+
return 0;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
if (!root.source) {
|
|
488
|
+
throw new Error('The root node must have a source');
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/** @type {import('postcss').Source & { baseIndentLevel?: number }} */
|
|
492
|
+
const source = root.source;
|
|
493
|
+
|
|
494
|
+
const indentLevel = source.baseIndentLevel;
|
|
495
|
+
|
|
496
|
+
if (isNumber(indentLevel) && Number.isSafeInteger(indentLevel)) {
|
|
497
|
+
return indentLevel;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
const newIndentLevel = inferRootIndentLevel(root, baseIndentLevel, () => inferDocIndentSize(document, space));
|
|
501
|
+
|
|
502
|
+
source.baseIndentLevel = newIndentLevel;
|
|
503
|
+
|
|
504
|
+
return newIndentLevel;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* @param {import('postcss').Node} node
|
|
509
|
+
*/
|
|
510
|
+
function getDocument (node) {
|
|
511
|
+
// @ts-expect-error -- TS2339: Property 'document' does not exist on type 'Node'.
|
|
512
|
+
const document = node.document;
|
|
513
|
+
|
|
514
|
+
if (document) {
|
|
515
|
+
return document;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
const root = node.root();
|
|
519
|
+
|
|
520
|
+
// @ts-expect-error -- TS2339: Property 'document' does not exist on type 'Node'.
|
|
521
|
+
return root.document;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* @param {import('postcss').Document} document
|
|
526
|
+
* @param {string} space- -
|
|
527
|
+
* returns {number}
|
|
528
|
+
* @param space
|
|
529
|
+
*/
|
|
530
|
+
function inferDocIndentSize (document, space) {
|
|
531
|
+
if (!document.source) { throw new Error('The document node must have a source'); }
|
|
532
|
+
|
|
533
|
+
/** @type {import('postcss').Source & { indentSize?: number }} */
|
|
534
|
+
const documentSource = document.source;
|
|
535
|
+
|
|
536
|
+
let indentSize = documentSource.indentSize;
|
|
537
|
+
|
|
538
|
+
if (isNumber(indentSize) && Number.isSafeInteger(indentSize)) {
|
|
539
|
+
return indentSize;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
const source = document.source.input.css;
|
|
543
|
+
const indents = source.match(/^ *(?=\S)/gm);
|
|
544
|
+
|
|
545
|
+
if (indents) {
|
|
546
|
+
/** @type {Map<number, number>} */
|
|
547
|
+
const scores = new Map();
|
|
548
|
+
let lastIndentSize = 0;
|
|
549
|
+
let lastLeadingSpacesLength = 0;
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* @param {number} leadingSpacesLength
|
|
553
|
+
*/
|
|
554
|
+
const vote = (leadingSpacesLength) => {
|
|
555
|
+
if (leadingSpacesLength) {
|
|
556
|
+
lastIndentSize = Math.abs(leadingSpacesLength - lastLeadingSpacesLength) || lastIndentSize;
|
|
557
|
+
|
|
558
|
+
if (lastIndentSize > 1) {
|
|
559
|
+
const score = scores.get(lastIndentSize);
|
|
560
|
+
|
|
561
|
+
if (score) {
|
|
562
|
+
scores.set(lastIndentSize, score + 1);
|
|
563
|
+
}
|
|
564
|
+
else {
|
|
565
|
+
scores.set(lastIndentSize, 1);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
else {
|
|
570
|
+
lastIndentSize = 0;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
lastLeadingSpacesLength = leadingSpacesLength;
|
|
574
|
+
};
|
|
575
|
+
|
|
576
|
+
for (const leadingSpaces of indents) {
|
|
577
|
+
vote(leadingSpaces.length);
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
let bestScore = 0;
|
|
581
|
+
|
|
582
|
+
for (const [indentSizeDate, score] of scores.entries()) {
|
|
583
|
+
if (score > bestScore) {
|
|
584
|
+
bestScore = score;
|
|
585
|
+
indentSize = indentSizeDate;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
indentSize =
|
|
591
|
+
Number(indentSize) || (indents && indents[0] && indents[0].length) || Number(space) || 2;
|
|
592
|
+
documentSource.indentSize = indentSize;
|
|
593
|
+
|
|
594
|
+
return indentSize;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/**
|
|
598
|
+
* @param {import('postcss').Root} root
|
|
599
|
+
* @param {number | 'auto'} baseIndentLevel
|
|
600
|
+
* @param {() => number} indentSize
|
|
601
|
+
* @returns {number}
|
|
602
|
+
*/
|
|
603
|
+
function inferRootIndentLevel (root, baseIndentLevel, indentSize) {
|
|
604
|
+
/**
|
|
605
|
+
* @param {string} indent
|
|
606
|
+
*/
|
|
607
|
+
function getIndentLevel (indent) {
|
|
608
|
+
const tabMatch = indent.match(/\t/g);
|
|
609
|
+
const tabCount = tabMatch ? tabMatch.length : 0;
|
|
610
|
+
|
|
611
|
+
const spaceMatch = indent.match(/ /g);
|
|
612
|
+
const spaceCount = spaceMatch ? Math.round(spaceMatch.length / indentSize()) : 0;
|
|
613
|
+
|
|
614
|
+
return tabCount + spaceCount;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
let newBaseIndentLevel = 0;
|
|
618
|
+
|
|
619
|
+
if (!isNumber(baseIndentLevel) || !Number.isSafeInteger(baseIndentLevel)) {
|
|
620
|
+
if (!root.source) { throw new Error('The root node must have a source'); }
|
|
621
|
+
|
|
622
|
+
let source = root.source.input.css;
|
|
623
|
+
|
|
624
|
+
source = source.replace(/^[^\n\r]+/, (firstLine) => {
|
|
625
|
+
const match = root.raws.codeBefore && (/(?:^|\n)([\t ]*)$/).exec(root.raws.codeBefore);
|
|
626
|
+
|
|
627
|
+
if (match) {
|
|
628
|
+
return match[1] + firstLine;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
return '';
|
|
632
|
+
});
|
|
633
|
+
|
|
634
|
+
const indents = source.match(/^[\t ]*(?=\S)/gm);
|
|
635
|
+
|
|
636
|
+
if (indents) {
|
|
637
|
+
return Math.min(...indents.map((indent) => getIndentLevel(indent)));
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
newBaseIndentLevel = 1;
|
|
641
|
+
}
|
|
642
|
+
else {
|
|
643
|
+
newBaseIndentLevel = baseIndentLevel;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
const indents = [];
|
|
647
|
+
const foundIndents = root.raws.codeBefore && (/(?:^|\n)([\t ]*)\S/m).exec(root.raws.codeBefore);
|
|
648
|
+
|
|
649
|
+
// The indent level of the CSS code block in non-CSS-like files is determined by the shortest indent of non-empty line.
|
|
650
|
+
if (foundIndents) {
|
|
651
|
+
let shortest = Number.MAX_SAFE_INTEGER;
|
|
652
|
+
let i = 0;
|
|
653
|
+
|
|
654
|
+
while (++i < foundIndents.length) {
|
|
655
|
+
const foundIndent = foundIndents[i];
|
|
656
|
+
|
|
657
|
+
assertString(foundIndent);
|
|
658
|
+
const current = getIndentLevel(foundIndent);
|
|
659
|
+
|
|
660
|
+
if (current < shortest) {
|
|
661
|
+
shortest = current;
|
|
662
|
+
|
|
663
|
+
if (shortest === 0) {
|
|
664
|
+
break;
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
if (shortest !== Number.MAX_SAFE_INTEGER) {
|
|
670
|
+
indents.push(new Array(shortest).fill(' ').join(''));
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
const after = root.raws.after;
|
|
675
|
+
|
|
676
|
+
if (after) {
|
|
677
|
+
let afterEnd;
|
|
678
|
+
|
|
679
|
+
if (after.endsWith('\n')) {
|
|
680
|
+
// @ts-expect-error -- TS2339: Property 'document' does not exist on type 'Root'.
|
|
681
|
+
const document = root.document;
|
|
682
|
+
|
|
683
|
+
if (document) {
|
|
684
|
+
const nextRoot = document.nodes[document.nodes.indexOf(root) + 1];
|
|
685
|
+
|
|
686
|
+
afterEnd = nextRoot ? nextRoot.raws.codeBefore : document.raws.codeAfter;
|
|
687
|
+
}
|
|
688
|
+
else {
|
|
689
|
+
// Nested root node in css-in-js lang
|
|
690
|
+
const parent = root.parent;
|
|
691
|
+
|
|
692
|
+
if (!parent) { throw new Error('The root node must have a parent'); }
|
|
693
|
+
|
|
694
|
+
const nextRoot = parent.nodes[parent.nodes.indexOf(root) + 1];
|
|
695
|
+
|
|
696
|
+
afterEnd = nextRoot ? nextRoot.raws.codeBefore : root.raws.codeAfter;
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
else {
|
|
700
|
+
afterEnd = after;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
if (afterEnd) { indents.push(afterEnd.match(/^[\t ]*/)[0]); }
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
if (indents.length > 0) {
|
|
707
|
+
return Math.max(...indents.map((indent) => getIndentLevel(indent))) + newBaseIndentLevel;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
return newBaseIndentLevel;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
/**
|
|
714
|
+
* @param {string | undefined} str
|
|
715
|
+
* @param string_
|
|
716
|
+
* @param {string} whitespace
|
|
717
|
+
*/
|
|
718
|
+
function fixIndentation (string_, whitespace) {
|
|
719
|
+
if (!isString(string_)) {
|
|
720
|
+
return string_;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
return string_.replace(/\n[\t ]*(?=\S|$)/g, `\n${whitespace}`);
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
/**
|
|
727
|
+
* @param {string} input
|
|
728
|
+
* @param {string} searchString
|
|
729
|
+
* @param {string} replaceString
|
|
730
|
+
* @param {number} startIndex
|
|
731
|
+
*/
|
|
732
|
+
function replaceIndentation (input, searchString, replaceString, startIndex) {
|
|
733
|
+
const offset = startIndex + 1;
|
|
734
|
+
const stringStart = input.slice(0, offset);
|
|
735
|
+
const stringEnd = input.slice(offset + searchString.length);
|
|
736
|
+
|
|
737
|
+
return stringStart + replaceString + stringEnd;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
rule.ruleName = ruleName;
|
|
741
|
+
rule.messages = messages;
|
|
742
|
+
rule.meta = meta;
|
|
743
|
+
module.exports = stylelint.createPlugin(ruleName, rule);
|