linter-bundle 7.2.0 → 7.4.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.
Files changed (91) hide show
  1. package/CHANGELOG.md +27 -2
  2. package/README.md +11 -11
  3. package/eslint/react.mjs +2 -1
  4. package/eslint/rules/enforce-logical-expression-parens.mjs +1 -1
  5. package/eslint/rules/enforce-ternary-parens.mjs +1 -1
  6. package/eslint/rules/ensure-lucide-import-consistency.mjs +1 -1
  7. package/eslint/rules/no-extra-spaces-in-generics.mjs +1 -1
  8. package/eslint/rules/no-ternary-return.mjs +1 -1
  9. package/eslint/rules/no-unnecessary-typeof.mjs +1 -1
  10. package/eslint/rules/restricted-filenames.mjs +6 -2
  11. package/package.json +5 -5
  12. package/stylelint/index.mjs +0 -2
  13. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/at-rule-name-case/index.mjs +5 -9
  14. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/at-rule-name-space-after/index.mjs +1 -1
  15. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/at-rule-semicolon-newline-after/index.mjs +12 -14
  16. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/atRuleNameSpaceChecker.mjs +2 -7
  17. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/block-closing-brace-empty-line-before/index.mjs +13 -16
  18. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/block-closing-brace-newline-after/index.mjs +22 -23
  19. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/block-closing-brace-newline-before/index.mjs +29 -30
  20. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/block-closing-brace-space-before/index.mjs +19 -20
  21. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/block-opening-brace-newline-after/index.mjs +40 -43
  22. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/block-opening-brace-space-after/index.mjs +19 -20
  23. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/block-opening-brace-space-before/index.mjs +14 -17
  24. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/color-hex-case/index.mjs +6 -9
  25. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-bang-space-after/index.mjs +1 -1
  26. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-bang-space-before/index.mjs +42 -43
  27. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-block-semicolon-newline-after/index.mjs +19 -20
  28. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-block-semicolon-space-after/index.mjs +15 -16
  29. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-block-semicolon-space-before/index.mjs +27 -28
  30. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-block-trailing-semicolon/index.mjs +6 -8
  31. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-colon-newline-after/index.mjs +17 -18
  32. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-colon-space-after/index.mjs +17 -18
  33. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-colon-space-before/index.mjs +17 -18
  34. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declarationBangSpaceChecker.mjs +2 -5
  35. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declarationColonSpaceChecker.mjs +2 -5
  36. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-comma-newline-after/index.mjs +8 -10
  37. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-comma-newline-before/index.mjs +8 -10
  38. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-comma-space-after/index.mjs +9 -11
  39. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-comma-space-before/index.mjs +9 -11
  40. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-max-empty-lines/index.mjs +23 -25
  41. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-parentheses-newline-inside/index.mjs +72 -57
  42. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-parentheses-space-inside/index.mjs +97 -72
  43. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-whitespace-after/index.mjs +10 -16
  44. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/functionCommaSpaceChecker.mjs +7 -9
  45. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/indentation/index.mjs +43 -49
  46. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/max-empty-lines/index.mjs +13 -8
  47. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/max-line-length/index.mjs +2 -2
  48. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-feature-colon-space-after/index.mjs +9 -11
  49. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-feature-colon-space-before/index.mjs +9 -11
  50. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-feature-name-case/index.mjs +6 -9
  51. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-feature-parentheses-space-inside/index.mjs +68 -27
  52. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-feature-range-operator-space-after/index.mjs +23 -39
  53. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-feature-range-operator-space-before/index.mjs +6 -12
  54. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-query-list-comma-newline-after/index.mjs +8 -10
  55. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-query-list-comma-space-after/index.mjs +9 -11
  56. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-query-list-comma-space-before/index.mjs +9 -11
  57. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/mediaFeatureColonSpaceChecker.mjs +2 -1
  58. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/mediaQueryListCommaWhitespaceChecker.mjs +2 -5
  59. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/no-empty-first-line/index.mjs +14 -17
  60. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/no-eol-whitespace/index.mjs +6 -7
  61. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/no-extra-semicolons/index.mjs +45 -43
  62. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/no-missing-end-of-source-newline/index.mjs +5 -9
  63. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/number-leading-zero/index.mjs +24 -58
  64. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/number-no-trailing-zeros/index.mjs +8 -11
  65. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/property-case/index.mjs +5 -8
  66. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-attribute-brackets-space-inside/index.mjs +49 -45
  67. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-attribute-operator-space-after/index.mjs +52 -54
  68. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-attribute-operator-space-before/index.mjs +37 -39
  69. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-combinator-space-after/index.mjs +12 -14
  70. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-combinator-space-before/index.mjs +12 -14
  71. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-descendant-combinator-no-non-space/index.mjs +11 -14
  72. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-list-comma-newline-after/index.mjs +4 -7
  73. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-list-comma-newline-before/index.mjs +7 -9
  74. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-list-comma-space-after/index.mjs +8 -10
  75. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-list-comma-space-before/index.mjs +8 -10
  76. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-max-empty-lines/index.mjs +17 -17
  77. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-pseudo-class-case/index.mjs +39 -40
  78. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-pseudo-class-parentheses-space-inside/index.mjs +49 -44
  79. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-pseudo-element-case/index.mjs +5 -8
  80. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selectorAttributeOperatorSpaceChecker.mjs +6 -7
  81. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selectorCombinatorSpaceChecker.mjs +6 -7
  82. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selectorListCommaWhitespaceChecker.mjs +2 -5
  83. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/string-quotes/index.mjs +51 -59
  84. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/unit-case/index.mjs +19 -21
  85. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/value-list-comma-newline-after/index.mjs +11 -13
  86. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/value-list-comma-space-after/index.mjs +12 -14
  87. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/value-list-comma-space-before/index.mjs +12 -14
  88. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/value-list-max-empty-lines/index.mjs +12 -12
  89. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/valueListCommaWhitespaceChecker.mjs +2 -1
  90. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/linebreaks/README.md +0 -21
  91. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/linebreaks/index.mjs +0 -133
@@ -24,7 +24,7 @@ const meta = {
24
24
  };
25
25
 
26
26
  /** @type {import('stylelint').Rule} */
27
- const rule = (primary, secondaryOptions = {}, context) => (root, result) => {
27
+ const rule = (primary, secondaryOptions = {}) => (root, result) => {
28
28
  const validOptions = validateOptions(
29
29
  result,
30
30
  ruleName,
@@ -105,24 +105,22 @@ const rule = (primary, secondaryOptions = {}, context) => (root, result) => {
105
105
  (parent.raws.codeBefore?.endsWith('\n'))))) &&
106
106
  before.slice(lastIndexOfNewline + 1) !== expectedOpeningBraceIndentation
107
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
- }
108
+ report({
109
+ message: messages.expected(legibleExpectation(nodeLevel)),
110
+ node,
111
+ result,
112
+ ruleName,
113
+ fix: () => {
114
+ if (isFirstChild && isString(node.raws.before)) {
115
+ node.raws.before = node.raws.before.replace(
116
+ /^[\t ]*(?=\S|$)/,
117
+ expectedOpeningBraceIndentation
118
+ );
119
+ }
115
120
 
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
- }
121
+ node.raws.before = fixIndentation(node.raws.before, expectedOpeningBraceIndentation);
122
+ }
123
+ });
126
124
  }
127
125
 
128
126
  // Only blocks have the `after` string to check.
@@ -139,19 +137,17 @@ const rule = (primary, secondaryOptions = {}, context) => (root, result) => {
139
137
  after.includes('\n') &&
140
138
  after.slice(after.lastIndexOf('\n') + 1) !== expectedClosingBraceIndentation
141
139
  ) {
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
- endIndex: node.toString().length - 1,
151
- result,
152
- ruleName
153
- });
154
- }
140
+ report({
141
+ message: messages.expected(legibleExpectation(closingBraceLevel)),
142
+ node,
143
+ index: node.toString().length - 1,
144
+ endIndex: node.toString().length - 1,
145
+ result,
146
+ ruleName,
147
+ fix: () => {
148
+ node.raws.after = fixIndentation(node.raws.after, expectedClosingBraceIndentation);
149
+ }
150
+ });
155
151
  }
156
152
 
157
153
  // If this is a declaration, check the value
@@ -378,24 +374,22 @@ const rule = (primary, secondaryOptions = {}, context) => (root, result) => {
378
374
  );
379
375
 
380
376
  if (afterNewlineSpace !== expectedIndentation) {
381
- if (context.fix) {
382
- // 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
383
- fixPositions.unshift({
384
- expectedIndentation,
385
- currentIndentation: afterNewlineSpace,
386
- startIndex: match.startIndex
387
- });
388
- }
389
- else {
390
- report({
391
- message: messages.expected(legibleExpectation(expectedIndentLevel)),
392
- node,
393
- index: match.startIndex + afterNewlineSpace.length + 1,
394
- endIndex: match.startIndex + afterNewlineSpace.length + 1,
395
- result,
396
- ruleName
397
- });
398
- }
377
+ report({
378
+ message: messages.expected(legibleExpectation(expectedIndentLevel)),
379
+ node,
380
+ index: match.startIndex + afterNewlineSpace.length + 1,
381
+ endIndex: match.startIndex + afterNewlineSpace.length + 1,
382
+ result,
383
+ ruleName,
384
+ fix: () => {
385
+ // 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
386
+ fixPositions.unshift({
387
+ expectedIndentation,
388
+ currentIndentation: afterNewlineSpace,
389
+ startIndex: match.startIndex
390
+ });
391
+ }
392
+ });
399
393
  }
400
394
  }
401
395
  );
@@ -22,7 +22,7 @@ const meta = {
22
22
  };
23
23
 
24
24
  /** @type {import('stylelint').Rule} */
25
- const rule = (primary, secondaryOptions, context) => {
25
+ const rule = (primary, secondaryOptions) => {
26
26
  let emptyLines = 0;
27
27
  let lastIndex = -1;
28
28
 
@@ -50,11 +50,8 @@ const rule = (primary, secondaryOptions, context) => {
50
50
  const ignoreComments = optionsMatches(secondaryOptions, 'ignore', 'comments');
51
51
  const getChars = replaceEmptyLines.bind(null, primary);
52
52
 
53
- /**
54
- * 1. walk nodes & replace enterchar
55
- * 2. deal with special case.
56
- */
57
- if (context.fix) {
53
+ const fixFn = () => {
54
+ // Erst alle Nodes durchgehen und Zeilenumbrüche ersetzen
58
55
  root.walk((node) => {
59
56
  if (node.type === 'comment' && !ignoreComments) {
60
57
  node.raws.left = getChars(node.raws.left);
@@ -87,9 +84,9 @@ const rule = (primary, secondaryOptions, context) => {
87
84
  // `css in js` or `html`
88
85
  root.raws.after = replaceEmptyLines(primary === 0 ? 1 : primary, rootRawsAfter);
89
86
  }
87
+ };
90
88
 
91
- return;
92
- }
89
+ let problemFound = false;
93
90
 
94
91
  emptyLines = 0;
95
92
  lastIndex = -1;
@@ -106,6 +103,10 @@ const rule = (primary, secondaryOptions, context) => {
106
103
  }
107
104
  );
108
105
 
106
+ if (problemFound) {
107
+ fixFn();
108
+ }
109
+
109
110
  /**
110
111
  * @param {string} source
111
112
  * @param {number} matchStartIndex
@@ -131,6 +132,8 @@ const rule = (primary, secondaryOptions, context) => {
131
132
  if (!eof && !problem) { return; }
132
133
 
133
134
  if (problem) {
135
+ problemFound = true;
136
+
134
137
  report({
135
138
  message: messages.expected(primary),
136
139
  node,
@@ -146,6 +149,8 @@ const rule = (primary, secondaryOptions, context) => {
146
149
  emptyLines++;
147
150
 
148
151
  if (emptyLines > primary && isEofNode(result.root, node)) {
152
+ problemFound = true;
153
+
149
154
  report({
150
155
  message: messages.expected(primary),
151
156
  node,
@@ -21,7 +21,7 @@ const meta = {
21
21
  };
22
22
 
23
23
  /** @type {import('stylelint').Rule} */
24
- const rule = (primary, secondaryOptions, context) => (root, result) => {
24
+ const rule = (primary, secondaryOptions) => (root, result) => {
25
25
  const validOptions = validateOptions(
26
26
  result,
27
27
  ruleName,
@@ -54,7 +54,7 @@ const rule = (primary, secondaryOptions, context) => (root, result) => {
54
54
 
55
55
  const ignoreNonComments = optionsMatches(secondaryOptions, 'ignore', 'non-comments');
56
56
  const ignoreComments = optionsMatches(secondaryOptions, 'ignore', 'comments');
57
- const rootString = context.fix ? root.toString() : root.source.input.css;
57
+ const rootString = root.toString();
58
58
  // Array of skipped sub strings, i.e `url(...)`, `@import "..."`
59
59
  /** @type {Array<[number, number]>} */
60
60
  let skippedSubStrings = [];
@@ -22,7 +22,7 @@ const meta = {
22
22
  };
23
23
 
24
24
  /** @type {import('stylelint').Rule} */
25
- const rule = (primary, _secondaryOptions, context) => {
25
+ const rule = (primary, _secondaryOptions) => {
26
26
  const checker = whitespaceChecker('space', primary, messages);
27
27
 
28
28
  return (root, result) => {
@@ -43,19 +43,17 @@ const rule = (primary, _secondaryOptions, context) => {
43
43
  result,
44
44
  locationChecker: checker.after,
45
45
  checkedRuleName: ruleName,
46
- fix: context.fix ?
47
- (atRule, index) => {
48
- const parameterColonIndex = index - atRuleParamIndex(atRule);
46
+ fix: (atRule, index) => {
47
+ const parameterColonIndex = index - atRuleParamIndex(atRule);
49
48
 
50
- fixData ||= new Map();
51
- const colonIndices = fixData.get(atRule) || [];
49
+ fixData ||= new Map();
50
+ const colonIndices = fixData.get(atRule) || [];
52
51
 
53
- colonIndices.push(parameterColonIndex);
54
- fixData.set(atRule, colonIndices);
52
+ colonIndices.push(parameterColonIndex);
53
+ fixData.set(atRule, colonIndices);
55
54
 
56
- return true;
57
- }
58
- : null
55
+ return true;
56
+ }
59
57
  });
60
58
 
61
59
  if (fixData) {
@@ -22,7 +22,7 @@ const meta = {
22
22
  };
23
23
 
24
24
  /** @type {import('stylelint').Rule} */
25
- const rule = (primary, _secondaryOptions, context) => {
25
+ const rule = (primary, _secondaryOptions) => {
26
26
  const checker = whitespaceChecker('space', primary, messages);
27
27
 
28
28
  return (root, result) => {
@@ -43,19 +43,17 @@ const rule = (primary, _secondaryOptions, context) => {
43
43
  result,
44
44
  locationChecker: checker.before,
45
45
  checkedRuleName: ruleName,
46
- fix: context.fix ?
47
- (atRule, index) => {
48
- const parameterColonIndex = index - atRuleParamIndex(atRule);
46
+ fix: (atRule, index) => {
47
+ const parameterColonIndex = index - atRuleParamIndex(atRule);
49
48
 
50
- fixData ||= new Map();
51
- const colonIndices = fixData.get(atRule) || [];
49
+ fixData ||= new Map();
50
+ const colonIndices = fixData.get(atRule) || [];
52
51
 
53
- colonIndices.push(parameterColonIndex);
54
- fixData.set(atRule, colonIndices);
52
+ colonIndices.push(parameterColonIndex);
53
+ fixData.set(atRule, colonIndices);
55
54
 
56
- return true;
57
- }
58
- : null
55
+ return true;
56
+ }
59
57
  });
60
58
 
61
59
  if (fixData) {
@@ -23,7 +23,7 @@ const meta = {
23
23
  };
24
24
 
25
25
  /** @type {import('stylelint').Rule} */
26
- const rule = (primary, _secondaryOptions, context) => (root, result) => {
26
+ const rule = (primary, _secondaryOptions) => (root, result) => {
27
27
  const validOptions = validateOptions(result, ruleName, {
28
28
  actual: primary,
29
29
  possible: ['lower', 'upper']
@@ -53,13 +53,6 @@ const rule = (primary, _secondaryOptions, context) => (root, result) => {
53
53
  return;
54
54
  }
55
55
 
56
- if (context.fix) {
57
- mutateIdent(mediaFeatureNameToken, expectedFeatureName);
58
- hasFixes = true;
59
-
60
- return;
61
- }
62
-
63
56
  const atRuleIndex = atRuleParamIndex(atRule);
64
57
 
65
58
  report({
@@ -68,7 +61,11 @@ const rule = (primary, _secondaryOptions, context) => (root, result) => {
68
61
  index: atRuleIndex + startIndex,
69
62
  endIndex: atRuleIndex + endIndex + 1,
70
63
  ruleName,
71
- result
64
+ result,
65
+ fix: () => {
66
+ mutateIdent(mediaFeatureNameToken, expectedFeatureName);
67
+ hasFixes = true;
68
+ }
72
69
  });
73
70
  }).stringify();
74
71
 
@@ -23,7 +23,7 @@ const meta = {
23
23
  };
24
24
 
25
25
  /** @type {import('stylelint').Rule} */
26
- const rule = (primary, _secondaryOptions, context) => (root, result) => {
26
+ const rule = (primary, _secondaryOptions) => (root, result) => {
27
27
  const validOptions = validateOptions(result, ruleName, {
28
28
  actual: primary,
29
29
  possible: ['always', 'never']
@@ -38,69 +38,110 @@ const rule = (primary, _secondaryOptions, context) => (root, result) => {
38
38
  // will be at atRule.raws.params.raw
39
39
  const parameters = (atRule.raws.params?.raw) || atRule.params;
40
40
  const indexBoost = atRuleParamIndex(atRule);
41
- /** @type {Array<{ message: string, index: number }>} */
42
- const problems = [];
43
41
 
44
- const parsedParameters = valueParser(parameters).walk((node) => {
42
+ // Parse the parameters once, and create a static copy for reporting
43
+ const originalParsedParams = valueParser(parameters);
44
+ let fixCount = 0;
45
+
46
+ // First pass - only detect problems
47
+ const problems = [];
48
+ originalParsedParams.walk((node) => {
45
49
  if (node.type === 'function') {
46
50
  const length_ = valueParser.stringify(node).length;
47
51
 
48
52
  if (primary === 'never') {
49
53
  if ((/[\t ]/).test(node.before)) {
50
- if (context.fix) { node.before = ''; }
51
-
52
54
  problems.push({
53
55
  message: messages.rejectedOpening,
54
- index: node.sourceIndex + 1 + indexBoost
56
+ index: node.sourceIndex + 1 + indexBoost,
57
+ functionIndex: node.sourceIndex,
58
+ type: 'opening'
55
59
  });
56
60
  }
57
61
 
58
62
  if ((/[\t ]/).test(node.after)) {
59
- if (context.fix) { node.after = ''; }
60
-
61
63
  problems.push({
62
64
  message: messages.rejectedClosing,
63
- index: node.sourceIndex - 2 + length_ + indexBoost
65
+ index: node.sourceIndex - 2 + length_ + indexBoost,
66
+ functionIndex: node.sourceIndex,
67
+ type: 'closing'
64
68
  });
65
69
  }
66
70
  }
67
71
  else if (primary === 'always') {
68
72
  if (node.before === '') {
69
- if (context.fix) { node.before = ' '; }
70
-
71
73
  problems.push({
72
74
  message: messages.expectedOpening,
73
- index: node.sourceIndex + 1 + indexBoost
75
+ index: node.sourceIndex + 1 + indexBoost,
76
+ functionIndex: node.sourceIndex,
77
+ type: 'opening'
74
78
  });
75
79
  }
76
80
 
77
81
  if (node.after === '') {
78
- if (context.fix) { node.after = ' '; }
79
-
80
82
  problems.push({
81
83
  message: messages.expectedClosing,
82
- index: node.sourceIndex - 2 + length_ + indexBoost
84
+ index: node.sourceIndex - 2 + length_ + indexBoost,
85
+ functionIndex: node.sourceIndex,
86
+ type: 'closing'
83
87
  });
84
88
  }
85
89
  }
86
90
  }
87
91
  });
88
92
 
93
+ // Report each problem with a fix function
89
94
  if (problems.length > 0) {
90
- if (context.fix) {
91
- atRule.params = parsedParameters.toString();
92
-
93
- return;
94
- }
95
-
96
- for (const error of problems) {
95
+ for (const problem of problems) {
97
96
  report({
98
- message: error.message,
97
+ message: problem.message,
99
98
  node: atRule,
100
- index: error.index,
101
- endIndex: error.index,
99
+ index: problem.index,
100
+ endIndex: problem.index,
102
101
  result,
103
- ruleName
102
+ ruleName,
103
+ fix: () => {
104
+ // Create a fresh copy for fixing each time to avoid mixing fixes
105
+ const parsedParams = valueParser(parameters);
106
+ let fixed = false;
107
+
108
+ parsedParams.walk((node) => {
109
+ if (node.type === 'function' && node.sourceIndex === problem.functionIndex) {
110
+ if (problem.type === 'opening') {
111
+ if (primary === 'never' && (/[\t ]/).test(node.before)) {
112
+ node.before = '';
113
+ fixed = true;
114
+ }
115
+ else if (primary === 'always' && node.before === '') {
116
+ node.before = ' ';
117
+ fixed = true;
118
+ }
119
+ } else if (problem.type === 'closing') {
120
+ if (primary === 'never' && (/[\t ]/).test(node.after)) {
121
+ node.after = '';
122
+ fixed = true;
123
+ }
124
+ else if (primary === 'always' && node.after === '') {
125
+ node.after = ' ';
126
+ fixed = true;
127
+ }
128
+ }
129
+ }
130
+ });
131
+
132
+ if (fixed) {
133
+ const fixedParams = parsedParams.toString();
134
+
135
+ if (atRule.raws.params?.raw) {
136
+ atRule.raws.params.raw = fixedParams;
137
+ } else {
138
+ atRule.params = fixedParams;
139
+ }
140
+ return true;
141
+ }
142
+
143
+ return false;
144
+ }
104
145
  });
105
146
  }
106
147
  }
@@ -23,7 +23,7 @@ const meta = {
23
23
  };
24
24
 
25
25
  /** @type {import('stylelint').Rule} */
26
- const rule = (primary, _secondaryOptions, context) => {
26
+ const rule = (primary, _secondaryOptions) => {
27
27
  const checker = whitespaceChecker('space', primary, messages);
28
28
 
29
29
  return (root, result) => {
@@ -37,37 +37,9 @@ const rule = (primary, _secondaryOptions, context) => {
37
37
  }
38
38
 
39
39
  root.walkAtRules(/^media$/i, (atRule) => {
40
- /** @type {number[]} */
41
- const fixOperatorIndices = [];
42
- /** @type {((index: number) => void) | null} */
43
- const fix = context.fix ? (index) => fixOperatorIndices.push(index) : null;
44
-
45
40
  findMediaOperator(atRule, (match, parameters, node) => {
46
- checkAfterOperator(match, parameters, node, fix);
41
+ checkAfterOperator(match, parameters, node);
47
42
  });
48
-
49
- if (fixOperatorIndices.length > 0) {
50
- let parameters = atRule.raws.params ? atRule.raws.params.raw : atRule.params;
51
-
52
- for (const index of fixOperatorIndices.sort((a, b) => b - a)) {
53
- const beforeOperator = parameters.slice(0, index + 1);
54
- const afterOperator = parameters.slice(index + 1);
55
-
56
- if (primary === 'always') {
57
- parameters = beforeOperator + afterOperator.replace(/^\s*/, ' ');
58
- }
59
- else if (primary === 'never') {
60
- parameters = beforeOperator + afterOperator.replace(/^\s*/, '');
61
- }
62
- }
63
-
64
- if (atRule.raws.params) {
65
- atRule.raws.params.raw = parameters;
66
- }
67
- else {
68
- atRule.params = parameters;
69
- }
70
- }
71
43
  });
72
44
 
73
45
  /**
@@ -75,28 +47,40 @@ const rule = (primary, _secondaryOptions, context) => {
75
47
  * @param {string} params
76
48
  * @param parameters
77
49
  * @param {import('postcss').AtRule} node
78
- * @param {((index: number) => void) | null} fix
79
50
  */
80
- function checkAfterOperator (match, parameters, node, fix) {
51
+ function checkAfterOperator(match, parameters, node) {
81
52
  const endIndex = match.startIndex + match.target.length - 1;
82
53
 
83
54
  checker.after({
84
55
  source: parameters,
85
56
  index: endIndex,
86
57
  err: (m) => {
87
- if (fix) {
88
- fix(endIndex);
89
-
90
- return;
91
- }
92
-
93
58
  report({
94
59
  message: m,
95
60
  node,
96
61
  index: endIndex + atRuleParamIndex(node) + 1,
97
62
  endIndex: endIndex + atRuleParamIndex(node) + 1,
98
63
  result,
99
- ruleName
64
+ ruleName,
65
+ fix: (fixer) => {
66
+ let parameters = node.raws.params ? node.raws.params.raw : node.params;
67
+ const beforeOperator = parameters.slice(0, endIndex + 1);
68
+ const afterOperator = parameters.slice(endIndex + 1);
69
+
70
+ if (primary === 'always') {
71
+ parameters = beforeOperator + afterOperator.replace(/^\s*/, ' ');
72
+ } else if (primary === 'never') {
73
+ parameters = beforeOperator + afterOperator.replace(/^\s*/, '');
74
+ }
75
+
76
+ if (node.raws.params) {
77
+ node.raws.params.raw = parameters;
78
+ } else {
79
+ node.params = parameters;
80
+ }
81
+
82
+ return fixer;
83
+ }
100
84
  });
101
85
  }
102
86
  });
@@ -23,7 +23,7 @@ const meta = {
23
23
  };
24
24
 
25
25
  /** @type {import('stylelint').Rule} */
26
- const rule = (primary, _secondaryOptions, context) => {
26
+ const rule = (primary, _secondaryOptions) => {
27
27
  const checker = whitespaceChecker('space', primary, messages);
28
28
 
29
29
  return (root, result) => {
@@ -39,11 +39,8 @@ const rule = (primary, _secondaryOptions, context) => {
39
39
  root.walkAtRules(/^media$/i, (atRule) => {
40
40
  /** @type {number[]} */
41
41
  const fixOperatorIndices = [];
42
- /** @type {((index: number) => void) | null} */
43
- const fix = context.fix ? (index) => fixOperatorIndices.push(index) : null;
44
-
45
42
  findMediaOperator(atRule, (match, parameters, node) => {
46
- checkBeforeOperator(match, parameters, node, fix);
43
+ checkBeforeOperator(match, parameters, node, (index) => fixOperatorIndices.push(index));
47
44
  });
48
45
 
49
46
  if (fixOperatorIndices.length > 0) {
@@ -84,19 +81,16 @@ const rule = (primary, _secondaryOptions, context) => {
84
81
  source: parameters,
85
82
  index: match.startIndex,
86
83
  err: (m) => {
87
- if (fix) {
88
- fix(match.startIndex);
89
-
90
- return;
91
- }
92
-
93
84
  report({
94
85
  message: m,
95
86
  node,
96
87
  index: match.startIndex - 1 + atRuleParamIndex(node),
97
88
  endIndex: match.startIndex - 1 + atRuleParamIndex(node),
98
89
  result,
99
- ruleName
90
+ ruleName,
91
+ fix: (fix ? () => {
92
+ fix(match.startIndex);
93
+ }: undefined)
100
94
  });
101
95
  }
102
96
  });
@@ -47,19 +47,17 @@ const rule = (primary, _secondaryOptions, context) => {
47
47
  locationChecker: checker.afterOneOnly,
48
48
  checkedRuleName: ruleName,
49
49
  allowTrailingComments: primary.startsWith('always'),
50
- fix: context.fix ?
51
- (atRule, index) => {
52
- const parameterCommaIndex = index - atRuleParamIndex(atRule);
50
+ fix: (atRule, index) => {
51
+ const parameterCommaIndex = index - atRuleParamIndex(atRule);
53
52
 
54
- fixData ||= new Map();
55
- const commaIndices = fixData.get(atRule) || [];
53
+ fixData ||= new Map();
54
+ const commaIndices = fixData.get(atRule) || [];
56
55
 
57
- commaIndices.push(parameterCommaIndex);
58
- fixData.set(atRule, commaIndices);
56
+ commaIndices.push(parameterCommaIndex);
57
+ fixData.set(atRule, commaIndices);
59
58
 
60
- return true;
61
- }
62
- : null
59
+ return true;
60
+ }
63
61
  });
64
62
 
65
63
  if (fixData) {
@@ -24,7 +24,7 @@ const meta = {
24
24
  };
25
25
 
26
26
  /** @type {import('stylelint').Rule} */
27
- const rule = (primary, _secondaryOptions, context) => {
27
+ const rule = (primary, _secondaryOptions) => {
28
28
  const checker = whitespaceChecker('space', primary, messages);
29
29
 
30
30
  return (root, result) => {
@@ -45,19 +45,17 @@ const rule = (primary, _secondaryOptions, context) => {
45
45
  result,
46
46
  locationChecker: checker.after,
47
47
  checkedRuleName: ruleName,
48
- fix: context.fix ?
49
- (atRule, index) => {
50
- const parameterCommaIndex = index - atRuleParamIndex(atRule);
48
+ fix: (atRule, index) => {
49
+ const parameterCommaIndex = index - atRuleParamIndex(atRule);
51
50
 
52
- fixData ||= new Map();
53
- const commaIndices = fixData.get(atRule) || [];
51
+ fixData ||= new Map();
52
+ const commaIndices = fixData.get(atRule) || [];
54
53
 
55
- commaIndices.push(parameterCommaIndex);
56
- fixData.set(atRule, commaIndices);
54
+ commaIndices.push(parameterCommaIndex);
55
+ fixData.set(atRule, commaIndices);
57
56
 
58
- return true;
59
- }
60
- : null
57
+ return true;
58
+ }
61
59
  });
62
60
 
63
61
  if (fixData) {