linter-bundle 7.1.1 → 7.2.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 (76) hide show
  1. package/CHANGELOG.md +29 -1
  2. package/README.md +21 -10
  3. package/eslint/index.mjs +18 -3
  4. package/eslint/jest.mjs +1 -0
  5. package/eslint/react.mjs +3 -0
  6. package/eslint/rules/enforce-logical-expression-parens.mjs +12 -3
  7. package/eslint/rules/enforce-ternary-parens.mjs +12 -3
  8. package/eslint/rules/no-extra-spaces-in-generics.mjs +1 -1
  9. package/lint.js +0 -1
  10. package/package.json +3 -3
  11. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/at-rule-name-case/index.mjs +6 -0
  12. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/at-rule-semicolon-newline-after/index.mjs +13 -8
  13. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/block-closing-brace-empty-line-before/index.mjs +15 -0
  14. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/block-closing-brace-newline-after/index.mjs +23 -0
  15. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/block-closing-brace-newline-before/index.mjs +30 -0
  16. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/block-closing-brace-space-before/index.mjs +18 -0
  17. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/block-opening-brace-newline-after/index.mjs +52 -0
  18. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/block-opening-brace-space-after/index.mjs +18 -0
  19. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/block-opening-brace-space-before/index.mjs +14 -0
  20. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/color-hex-case/index.mjs +7 -0
  21. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-bang-space-before/index.mjs +2 -3
  22. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-block-semicolon-newline-after/index.mjs +19 -0
  23. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-block-semicolon-space-after/index.mjs +14 -0
  24. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-block-semicolon-space-before/index.mjs +26 -0
  25. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-block-trailing-semicolon/index.mjs +19 -0
  26. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-colon-newline-after/index.mjs +17 -0
  27. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-colon-space-after/index.mjs +2 -2
  28. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/declaration-colon-space-before/index.mjs +2 -2
  29. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-comma-newline-after/index.mjs +2 -1
  30. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-comma-newline-before/index.mjs +2 -1
  31. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-comma-space-after/index.mjs +2 -1
  32. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-comma-space-before/index.mjs +2 -1
  33. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-max-empty-lines/index.mjs +31 -10
  34. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-parentheses-newline-inside/index.mjs +42 -6
  35. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-parentheses-space-inside/index.mjs +56 -8
  36. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/function-whitespace-after/index.mjs +18 -3
  37. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/indentation/index.mjs +49 -22
  38. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/linebreaks/index.mjs +39 -9
  39. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/max-empty-lines/index.mjs +41 -0
  40. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/max-line-length/index.mjs +1 -1
  41. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-feature-colon-space-after/index.mjs +2 -1
  42. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-feature-colon-space-before/index.mjs +2 -1
  43. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-feature-name-case/index.mjs +7 -0
  44. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-feature-parentheses-space-inside/index.mjs +14 -0
  45. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-feature-range-operator-space-after/index.mjs +3 -1
  46. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-feature-range-operator-space-before/index.mjs +3 -1
  47. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-query-list-comma-newline-after/index.mjs +2 -1
  48. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-query-list-comma-space-after/index.mjs +2 -1
  49. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-query-list-comma-space-before/index.mjs +2 -1
  50. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/no-empty-first-line/index.mjs +15 -1
  51. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/no-eol-whitespace/index.mjs +5 -1
  52. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/no-extra-semicolons/index.mjs +24 -0
  53. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/no-missing-end-of-source-newline/index.mjs +8 -1
  54. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/number-leading-zero/index.mjs +18 -1
  55. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/number-no-trailing-zeros/index.mjs +9 -0
  56. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/property-case/index.mjs +6 -0
  57. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-attribute-brackets-space-inside/index.mjs +28 -0
  58. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-attribute-operator-space-after/index.mjs +2 -1
  59. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-attribute-operator-space-before/index.mjs +2 -1
  60. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-combinator-space-after/index.mjs +2 -1
  61. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-combinator-space-before/index.mjs +2 -1
  62. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-descendant-combinator-no-non-space/index.mjs +12 -0
  63. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-list-comma-newline-after/index.mjs +6 -0
  64. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-list-comma-newline-before/index.mjs +2 -1
  65. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-list-comma-space-after/index.mjs +2 -1
  66. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-list-comma-space-before/index.mjs +2 -1
  67. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-max-empty-lines/index.mjs +15 -3
  68. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-pseudo-class-case/index.mjs +15 -0
  69. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-pseudo-class-parentheses-space-inside/index.mjs +28 -4
  70. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-pseudo-element-case/index.mjs +6 -0
  71. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/string-quotes/index.mjs +57 -32
  72. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/unit-case/index.mjs +25 -9
  73. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/value-list-comma-newline-after/index.mjs +3 -2
  74. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/value-list-comma-space-after/index.mjs +2 -1
  75. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/value-list-comma-space-before/index.mjs +2 -1
  76. package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/value-list-max-empty-lines/index.mjs +10 -3
@@ -62,6 +62,23 @@ const rule = (primary, _secondaryOptions, context) => {
62
62
  index: indexToCheck,
63
63
  lineCheckStr: decl.value,
64
64
  err: (m) => {
65
+ if (context.fix) {
66
+ const between = decl.raws.between;
67
+
68
+ if (between == null) { throw new Error('`between` must be present'); }
69
+
70
+ const betweenStart = declarationValueIndex(decl) - between.length;
71
+ const sliceIndex = indexToCheck - betweenStart + 1;
72
+ const betweenBefore = between.slice(0, sliceIndex);
73
+ const betweenAfter = between.slice(sliceIndex);
74
+
75
+ decl.raws.between = (/^\s*\n/).test(betweenAfter) ?
76
+ betweenBefore + betweenAfter.replace(/^[^\S\n\r]*/, '')
77
+ : betweenBefore + context.newline + betweenAfter;
78
+
79
+ return;
80
+ }
81
+
65
82
  report({
66
83
  message: m,
67
84
  node: decl,
@@ -42,7 +42,7 @@ const rule = (primary, _secondaryOptions, context) => {
42
42
  locationChecker: checker.after,
43
43
  checkedRuleName: ruleName,
44
44
  fix:
45
- (decl, index) => {
45
+ context.fix ? (decl, index) => {
46
46
  const colonIndex = index - declarationValueIndex(decl);
47
47
  const between = decl.raws.between;
48
48
 
@@ -63,7 +63,7 @@ const rule = (primary, _secondaryOptions, context) => {
63
63
  }
64
64
 
65
65
  return false;
66
- }
66
+ } : null
67
67
  });
68
68
  };
69
69
  };
@@ -40,7 +40,7 @@ const rule = (primary, _secondaryOptions, context) => {
40
40
  result,
41
41
  locationChecker: checker.before,
42
42
  checkedRuleName: ruleName,
43
- fix:
43
+ fix: context.fix ?
44
44
  (decl, index) => {
45
45
  const colonIndex = index - declarationValueIndex(decl);
46
46
  const between = decl.raws.between;
@@ -62,7 +62,7 @@ const rule = (primary, _secondaryOptions, context) => {
62
62
  }
63
63
 
64
64
  return false;
65
- }
65
+ } : null
66
66
  });
67
67
  };
68
68
  };
@@ -41,7 +41,7 @@ const rule = (primary, _secondaryOptions, context) => {
41
41
  result,
42
42
  locationChecker: checker.afterOneOnly,
43
43
  checkedRuleName: ruleName,
44
- fix:
44
+ fix: context.fix ?
45
45
  (div, index, nodes) => fixer({
46
46
  div,
47
47
  index,
@@ -50,6 +50,7 @@ const rule = (primary, _secondaryOptions, context) => {
50
50
  position: 'after',
51
51
  symb: context.newline || ''
52
52
  })
53
+ : null
53
54
  });
54
55
  };
55
56
  };
@@ -41,7 +41,7 @@ const rule = (primary, _secondaryOptions, context) => {
41
41
  result,
42
42
  locationChecker: checker.beforeAllowingIndentation,
43
43
  checkedRuleName: ruleName,
44
- fix:
44
+ fix: context.fix ?
45
45
  (div, index, nodes) => fixer({
46
46
  div,
47
47
  index,
@@ -50,6 +50,7 @@ const rule = (primary, _secondaryOptions, context) => {
50
50
  position: 'before',
51
51
  symb: context.newline || ''
52
52
  })
53
+ : null
53
54
  });
54
55
  };
55
56
  };
@@ -42,7 +42,7 @@ const rule = (primary, _secondaryOptions, context) => {
42
42
  result,
43
43
  locationChecker: checker.after,
44
44
  checkedRuleName: ruleName,
45
- fix:
45
+ fix: context.fix ?
46
46
  (div, index, nodes) => fixer({
47
47
  div,
48
48
  index,
@@ -51,6 +51,7 @@ const rule = (primary, _secondaryOptions, context) => {
51
51
  position: 'after',
52
52
  symb: ' '
53
53
  })
54
+ : null
54
55
  });
55
56
  };
56
57
  };
@@ -42,7 +42,7 @@ const rule = (primary, _secondaryOptions, context) => {
42
42
  result,
43
43
  locationChecker: checker.before,
44
44
  checkedRuleName: ruleName,
45
- fix:
45
+ fix: context.fix ?
46
46
  (div, index, nodes) => fixer({
47
47
  div,
48
48
  index,
@@ -51,6 +51,7 @@ const rule = (primary, _secondaryOptions, context) => {
51
51
  position: 'before',
52
52
  symb: ' '
53
53
  })
54
+ : null
54
55
  });
55
56
  };
56
57
  };
@@ -46,8 +46,8 @@ const rule = (primary, _secondaryOptions, context) => {
46
46
 
47
47
  const violatedCRLFNewLinesRegex = new RegExp(`(?:\r\n){${maxAdjacentNewlines + 1},}`);
48
48
  const violatedLFNewLinesRegex = new RegExp(`\n{${maxAdjacentNewlines + 1},}`);
49
- const allowedLFNewLinesString = '';
50
- const allowedCRLFNewLinesString = '';
49
+ const allowedLFNewLinesString = context.fix ? '\n'.repeat(maxAdjacentNewlines) : '';
50
+ const allowedCRLFNewLinesString = context.fix ? '\r\n'.repeat(maxAdjacentNewlines) : '';
51
51
 
52
52
  root.walkDecls((decl) => {
53
53
  if (!decl.value.includes('(')) {
@@ -76,15 +76,36 @@ const rule = (primary, _secondaryOptions, context) => {
76
76
  return;
77
77
  }
78
78
 
79
- report({
80
- message: messages.expected(primary),
81
- node: decl,
82
- index: placeIndexOnValueStart(decl) + node.sourceIndex,
83
- endIndex: placeIndexOnValueStart(decl) + node.sourceIndex,
84
- result,
85
- ruleName
86
- });
79
+ if (context.fix) {
80
+ const newNodeString = stringifiedNode
81
+ .replace(new RegExp(violatedLFNewLinesRegex, 'gm'), allowedLFNewLinesString)
82
+ .replace(new RegExp(violatedCRLFNewLinesRegex, 'gm'), allowedCRLFNewLinesString);
83
+
84
+ splittedValue.push([
85
+ stringValue.slice(sourceIndexStart, node.sourceIndex),
86
+ newNodeString
87
+ ]);
88
+ sourceIndexStart = node.sourceIndex + stringifiedNode.length;
89
+ }
90
+ else {
91
+ report({
92
+ message: messages.expected(primary),
93
+ node: decl,
94
+ index: placeIndexOnValueStart(decl) + node.sourceIndex,
95
+ endIndex: placeIndexOnValueStart(decl) + node.sourceIndex,
96
+ result,
97
+ ruleName
98
+ });
99
+ }
87
100
  });
101
+
102
+ if (context.fix && splittedValue.length > 0) {
103
+ const updatedValue =
104
+ splittedValue.reduce((accumulator, current) => accumulator + current[0] + current[1], '') +
105
+ stringValue.slice(sourceIndexStart);
106
+
107
+ setDeclarationValue(decl, updatedValue);
108
+ }
88
109
  });
89
110
  };
90
111
  };
@@ -67,15 +67,33 @@ const rule = (primary, _secondaryOptions, context) => (root, result) => {
67
67
  const checkBefore = getCheckBefore(valueNode);
68
68
 
69
69
  if (primary === 'always' && !containsNewline(checkBefore)) {
70
- complain(messages.expectedOpening, openingIndex);
70
+ if (context.fix) {
71
+ hasFixed = true;
72
+ fixBeforeForAlways(valueNode, context.newline || '');
73
+ }
74
+ else {
75
+ complain(messages.expectedOpening, openingIndex);
76
+ }
71
77
  }
72
78
 
73
79
  if (isMultiLine && primary === 'always-multi-line' && !containsNewline(checkBefore)) {
74
- complain(messages.expectedOpeningMultiLine, openingIndex);
80
+ if (context.fix) {
81
+ hasFixed = true;
82
+ fixBeforeForAlways(valueNode, context.newline || '');
83
+ }
84
+ else {
85
+ complain(messages.expectedOpeningMultiLine, openingIndex);
86
+ }
75
87
  }
76
88
 
77
89
  if (isMultiLine && primary === 'never-multi-line' && checkBefore !== '') {
78
- complain(messages.rejectedOpeningMultiLine, openingIndex);
90
+ if (context.fix) {
91
+ hasFixed = true;
92
+ fixBeforeForNever(valueNode);
93
+ }
94
+ else {
95
+ complain(messages.rejectedOpeningMultiLine, openingIndex);
96
+ }
79
97
  }
80
98
 
81
99
  // Check closing ...
@@ -84,15 +102,33 @@ const rule = (primary, _secondaryOptions, context) => (root, result) => {
84
102
  const checkAfter = getCheckAfter(valueNode);
85
103
 
86
104
  if (primary === 'always' && !containsNewline(checkAfter)) {
87
- complain(messages.expectedClosing, closingIndex);
105
+ if (context.fix) {
106
+ hasFixed = true;
107
+ fixAfterForAlways(valueNode, context.newline || '');
108
+ }
109
+ else {
110
+ complain(messages.expectedClosing, closingIndex);
111
+ }
88
112
  }
89
113
 
90
114
  if (isMultiLine && primary === 'always-multi-line' && !containsNewline(checkAfter)) {
91
- complain(messages.expectedClosingMultiLine, closingIndex);
115
+ if (context.fix) {
116
+ hasFixed = true;
117
+ fixAfterForAlways(valueNode, context.newline || '');
118
+ }
119
+ else {
120
+ complain(messages.expectedClosingMultiLine, closingIndex);
121
+ }
92
122
  }
93
123
 
94
124
  if (isMultiLine && primary === 'never-multi-line' && checkAfter !== '') {
95
- complain(messages.rejectedClosingMultiLine, closingIndex);
125
+ if (context.fix) {
126
+ hasFixed = true;
127
+ fixAfterForNever(valueNode);
128
+ }
129
+ else {
130
+ complain(messages.rejectedClosingMultiLine, closingIndex);
131
+ }
96
132
  }
97
133
  });
98
134
 
@@ -72,19 +72,43 @@ const rule = (primary, _secondaryOptions, context) => (root, result) => {
72
72
  const openingIndex = valueNode.sourceIndex + valueNode.value.length + 1;
73
73
 
74
74
  if (primary === 'always' && valueNode.before !== ' ') {
75
- complain(messages.expectedOpening, openingIndex);
75
+ if (context.fix) {
76
+ hasFixed = true;
77
+ valueNode.before = ' ';
78
+ }
79
+ else {
80
+ complain(messages.expectedOpening, openingIndex);
81
+ }
76
82
  }
77
83
 
78
84
  if (primary === 'never' && valueNode.before !== '') {
79
- complain(messages.rejectedOpening, openingIndex);
85
+ if (context.fix) {
86
+ hasFixed = true;
87
+ valueNode.before = '';
88
+ }
89
+ else {
90
+ complain(messages.rejectedOpening, openingIndex);
91
+ }
80
92
  }
81
93
 
82
94
  if (isSingleLine && primary === 'always-single-line' && valueNode.before !== ' ') {
83
- complain(messages.expectedOpeningSingleLine, openingIndex);
95
+ if (context.fix) {
96
+ hasFixed = true;
97
+ valueNode.before = ' ';
98
+ }
99
+ else {
100
+ complain(messages.expectedOpeningSingleLine, openingIndex);
101
+ }
84
102
  }
85
103
 
86
104
  if (isSingleLine && primary === 'never-single-line' && valueNode.before !== '') {
87
- complain(messages.rejectedOpeningSingleLine, openingIndex);
105
+ if (context.fix) {
106
+ hasFixed = true;
107
+ valueNode.before = '';
108
+ }
109
+ else {
110
+ complain(messages.rejectedOpeningSingleLine, openingIndex);
111
+ }
88
112
  }
89
113
 
90
114
  // Check closing ...
@@ -92,19 +116,43 @@ const rule = (primary, _secondaryOptions, context) => (root, result) => {
92
116
  const closingIndex = valueNode.sourceIndex + functionString.length - 2;
93
117
 
94
118
  if (primary === 'always' && valueNode.after !== ' ') {
95
- complain(messages.expectedClosing, closingIndex);
119
+ if (context.fix) {
120
+ hasFixed = true;
121
+ valueNode.after = ' ';
122
+ }
123
+ else {
124
+ complain(messages.expectedClosing, closingIndex);
125
+ }
96
126
  }
97
127
 
98
128
  if (primary === 'never' && valueNode.after !== '') {
99
- complain(messages.rejectedClosing, closingIndex);
129
+ if (context.fix) {
130
+ hasFixed = true;
131
+ valueNode.after = '';
132
+ }
133
+ else {
134
+ complain(messages.rejectedClosing, closingIndex);
135
+ }
100
136
  }
101
137
 
102
138
  if (isSingleLine && primary === 'always-single-line' && valueNode.after !== ' ') {
103
- complain(messages.expectedClosingSingleLine, closingIndex);
139
+ if (context.fix) {
140
+ hasFixed = true;
141
+ valueNode.after = ' ';
142
+ }
143
+ else {
144
+ complain(messages.expectedClosingSingleLine, closingIndex);
145
+ }
104
146
  }
105
147
 
106
148
  if (isSingleLine && primary === 'never-single-line' && valueNode.after !== '') {
107
- complain(messages.rejectedClosingSingleLine, closingIndex);
149
+ if (context.fix) {
150
+ hasFixed = true;
151
+ valueNode.after = '';
152
+ }
153
+ else {
154
+ complain(messages.rejectedClosingSingleLine, closingIndex);
155
+ }
108
156
  }
109
157
  });
110
158
 
@@ -131,7 +131,6 @@ const rule = (primary, _secondaryOptions, context) => (root, result) => {
131
131
 
132
132
  if (primary === 'always') {
133
133
  applyFix = (index) => {
134
-
135
134
  fixed += value.slice(lastIndex, index) + ' ';
136
135
  lastIndex = index;
137
136
  };
@@ -168,12 +167,28 @@ const rule = (primary, _secondaryOptions, context) => (root, result) => {
168
167
 
169
168
  root.walkAtRules(/^import$/i, (atRule) => {
170
169
  const parameter = (atRule.raws.params?.raw) || atRule.params;
170
+ const fixer = context.fix && createFixer(parameter);
171
+
172
+ check(atRule, parameter, atRuleParamIndex(atRule), fixer ? fixer.applyFix : undefined);
171
173
 
172
- check(atRule, parameter, atRuleParamIndex(atRule), undefined);
174
+ if (fixer && fixer.hasFixed) {
175
+ if (atRule.raws.params) {
176
+ atRule.raws.params.raw = fixer.fixed;
177
+ }
178
+ else {
179
+ atRule.params = fixer.fixed;
180
+ }
181
+ }
173
182
  });
174
183
  root.walkDecls((decl) => {
175
184
  const value = getDeclarationValue(decl);
176
- check(decl, value, declarationValueIndex(decl), undefined);
185
+ const fixer = context.fix && createFixer(value);
186
+
187
+ check(decl, value, declarationValueIndex(decl), fixer ? fixer.applyFix : undefined);
188
+
189
+ if (fixer && fixer.hasFixed) {
190
+ setDeclarationValue(decl, fixer.fixed);
191
+ }
177
192
  });
178
193
  };
179
194
 
@@ -105,12 +105,24 @@ const rule = (primary, secondaryOptions = {}, context) => (root, result) => {
105
105
  (parent.raws.codeBefore?.endsWith('\n'))))) &&
106
106
  before.slice(lastIndexOfNewline + 1) !== expectedOpeningBraceIndentation
107
107
  ) {
108
- report({
109
- message: messages.expected(legibleExpectation(nodeLevel)),
110
- node,
111
- result,
112
- ruleName
113
- });
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
+ }
114
126
  }
115
127
 
116
128
  // Only blocks have the `after` string to check.
@@ -127,14 +139,19 @@ const rule = (primary, secondaryOptions = {}, context) => (root, result) => {
127
139
  after.includes('\n') &&
128
140
  after.slice(after.lastIndexOf('\n') + 1) !== expectedClosingBraceIndentation
129
141
  ) {
130
- report({
131
- message: messages.expected(legibleExpectation(closingBraceLevel)),
132
- node,
133
- index: node.toString().length - 1,
134
- endIndex: node.toString().length - 1,
135
- result,
136
- ruleName
137
- });
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
+ }
138
155
  }
139
156
 
140
157
  // If this is a declaration, check the value
@@ -361,14 +378,24 @@ const rule = (primary, secondaryOptions = {}, context) => (root, result) => {
361
378
  );
362
379
 
363
380
  if (afterNewlineSpace !== expectedIndentation) {
364
- report({
365
- message: messages.expected(legibleExpectation(expectedIndentLevel)),
366
- node,
367
- index: match.startIndex + afterNewlineSpace.length + 1,
368
- endIndex: match.startIndex + afterNewlineSpace.length + 1,
369
- result,
370
- ruleName
371
- });
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
+ }
372
399
  }
373
400
  }
374
401
  );
@@ -31,20 +31,50 @@ const rule = (primary, _secondaryOptions, context) => (root, result) => {
31
31
 
32
32
  const shouldHaveCR = primary === 'windows';
33
33
 
34
- if (root.source == null) { throw new Error('The root node must have a source'); }
34
+ if (context.fix) {
35
+ root.walk((node) => {
36
+ if ('selector' in node) {
37
+ node.selector = fixData(node.selector);
38
+ }
39
+
40
+ if ('value' in node) {
41
+ node.value = fixData(node.value);
42
+ }
43
+
44
+ if ('text' in node) {
45
+ node.text = fixData(node.text);
46
+ }
35
47
 
36
- const lines = root.source.input.css.split('\n');
48
+ if (node.raws.before) {
49
+ node.raws.before = fixData(node.raws.before);
50
+ }
51
+
52
+ if (typeof node.raws.after === 'string') {
53
+ node.raws.after = fixData(node.raws.after);
54
+ }
55
+ });
56
+
57
+ if (typeof root.raws.after === 'string') {
58
+ root.raws.after = fixData(root.raws.after);
37
59
 
38
- for (let [i, line] of lines.entries()) {
39
- if (i < lines.length - 1 && !line.includes('\r')) {
40
- line += '\n';
41
60
  }
61
+ }
62
+ else {
63
+ if (root.source == null) { throw new Error('The root node must have a source'); }
42
64
 
43
- if (hasError(line)) {
44
- const lineNum = i + 1;
45
- const colNumber = line.length;
65
+ const lines = root.source.input.css.split('\n');
46
66
 
47
- reportNewlineError(lineNum, colNumber);
67
+ for (let [i, line] of lines.entries()) {
68
+ if (i < lines.length - 1 && !line.includes('\r')) {
69
+ line += '\n';
70
+ }
71
+
72
+ if (hasError(line)) {
73
+ const lineNum = i + 1;
74
+ const colNumber = line.length;
75
+
76
+ reportNewlineError(lineNum, colNumber);
77
+ }
48
78
  }
49
79
  }
50
80
 
@@ -50,6 +50,47 @@ 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) {
58
+ root.walk((node) => {
59
+ if (node.type === 'comment' && !ignoreComments) {
60
+ node.raws.left = getChars(node.raws.left);
61
+ node.raws.right = getChars(node.raws.right);
62
+ }
63
+
64
+ if (node.raws.before) {
65
+ node.raws.before = getChars(node.raws.before);
66
+ }
67
+ });
68
+
69
+ // first node
70
+ const firstNodeRawsBefore = root.first?.raws.before;
71
+ // root raws
72
+ const rootRawsAfter = root.raws.after;
73
+
74
+ // not document node
75
+ // @ts-expect-error -- TS2339: Property 'document' does not exist on type 'Root'.
76
+ if ((root.document?.constructor.name) !== 'Document') {
77
+ if (firstNodeRawsBefore) {
78
+ root.first.raws.before = getChars(firstNodeRawsBefore, true);
79
+ }
80
+
81
+ if (rootRawsAfter) {
82
+ // when max set 0, should be treated as 1 in this situation.
83
+ root.raws.after = replaceEmptyLines(primary === 0 ? 1 : primary, rootRawsAfter, true);
84
+ }
85
+ }
86
+ else if (rootRawsAfter) {
87
+ // `css in js` or `html`
88
+ root.raws.after = replaceEmptyLines(primary === 0 ? 1 : primary, rootRawsAfter);
89
+ }
90
+
91
+ return;
92
+ }
93
+
53
94
  emptyLines = 0;
54
95
  lastIndex = -1;
55
96
  const rootString = root.toString();
@@ -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 = root.source.input.css;
57
+ const rootString = context.fix ? root.toString() : root.source.input.css;
58
58
  // Array of skipped sub strings, i.e `url(...)`, `@import "..."`
59
59
  /** @type {Array<[number, number]>} */
60
60
  let skippedSubStrings = [];
@@ -43,7 +43,7 @@ const rule = (primary, _secondaryOptions, context) => {
43
43
  result,
44
44
  locationChecker: checker.after,
45
45
  checkedRuleName: ruleName,
46
- fix:
46
+ fix: context.fix ?
47
47
  (atRule, index) => {
48
48
  const parameterColonIndex = index - atRuleParamIndex(atRule);
49
49
 
@@ -55,6 +55,7 @@ const rule = (primary, _secondaryOptions, context) => {
55
55
 
56
56
  return true;
57
57
  }
58
+ : null
58
59
  });
59
60
 
60
61
  if (fixData) {
@@ -43,7 +43,7 @@ const rule = (primary, _secondaryOptions, context) => {
43
43
  result,
44
44
  locationChecker: checker.before,
45
45
  checkedRuleName: ruleName,
46
- fix:
46
+ fix: context.fix ?
47
47
  (atRule, index) => {
48
48
  const parameterColonIndex = index - atRuleParamIndex(atRule);
49
49
 
@@ -55,6 +55,7 @@ const rule = (primary, _secondaryOptions, context) => {
55
55
 
56
56
  return true;
57
57
  }
58
+ : null
58
59
  });
59
60
 
60
61
  if (fixData) {
@@ -53,6 +53,13 @@ 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
+
56
63
  const atRuleIndex = atRuleParamIndex(atRule);
57
64
 
58
65
  report({