Skip to content

Commit 734a574

Browse files
committed
Auto-fix for vue/component-tags-order
1 parent 37a03ed commit 734a574

File tree

2 files changed

+136
-32
lines changed

2 files changed

+136
-32
lines changed

lib/rules/component-tags-order.js

+31-20
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ module.exports = {
2424
categories: ['vue3-recommended', 'recommended'],
2525
url: 'https://eslint.vuejs.org/rules/component-tags-order.html'
2626
},
27-
fixable: null,
27+
fixable: 'code',
2828
schema: [
2929
{
3030
type: 'object',
@@ -87,30 +87,13 @@ module.exports = {
8787
return []
8888
}
8989

90-
/**
91-
* @param {VElement} element
92-
* @param {VElement} firstUnorderedElement
93-
*/
94-
function report(element, firstUnorderedElement) {
95-
context.report({
96-
node: element,
97-
loc: element.loc,
98-
messageId: 'unexpected',
99-
data: {
100-
name: element.name,
101-
firstUnorderedName: firstUnorderedElement.name,
102-
line: firstUnorderedElement.loc.start.line
103-
}
104-
})
105-
}
106-
10790
return {
10891
Program(node) {
10992
if (utils.hasInvalidEOF(node)) {
11093
return
11194
}
11295
const elements = getTopLevelHTMLElements()
113-
96+
const sourceCode = context.getSourceCode()
11497
elements.forEach((element, index) => {
11598
const expectedIndex = getOrderPosition(element.name)
11699
if (expectedIndex < 0) {
@@ -123,7 +106,35 @@ module.exports = {
123106
(e1, e2) => getOrderPosition(e1.name) - getOrderPosition(e2.name)
124107
)[0]
125108
if (firstUnordered) {
126-
report(element, firstUnordered)
109+
context.report({
110+
node: element,
111+
loc: element.loc,
112+
messageId: 'unexpected',
113+
data: {
114+
name: element.name,
115+
firstUnorderedName: firstUnordered.name,
116+
line: firstUnordered.loc.start.line
117+
},
118+
*fix(fixer) {
119+
// insert element before firstUnordered
120+
const fixedElements = elements.flatMap((it) => {
121+
if (it === firstUnordered) {
122+
return [element, it]
123+
} else if (it === element) {
124+
return []
125+
}
126+
return [it]
127+
})
128+
for (let i = elements.length - 1; i >= 0; i--) {
129+
if (elements[i] !== fixedElements[i]) {
130+
yield fixer.replaceTextRange(
131+
elements[i].range,
132+
sourceCode.text.slice(...fixedElements[i].range)
133+
)
134+
}
135+
}
136+
}
137+
})
127138
}
128139
})
129140
}

tests/lib/rules/component-tags-order.js

+105-12
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,25 @@
99

1010
const rule = require('../../../lib/rules/component-tags-order')
1111
const RuleTester = require('eslint').RuleTester
12+
const assert = require('assert')
13+
const { ESLint } = require('../../eslint-compat')
14+
15+
// Initialize linter.
16+
const eslint = new ESLint({
17+
overrideConfig: {
18+
parser: require.resolve('vue-eslint-parser'),
19+
parserOptions: {
20+
ecmaVersion: 2015
21+
},
22+
plugins: ['vue'],
23+
rules: {
24+
'vue/comment-directive': 'error',
25+
'vue/component-tags-order': 'error'
26+
}
27+
},
28+
useEslintrc: false,
29+
plugins: { vue: require('../../../lib/index') }
30+
})
1231

1332
// ------------------------------------------------------------------------------
1433
// Tests
@@ -108,7 +127,8 @@ tester.run('component-tags-order', rule, {
108127
line: 1,
109128
column: 37
110129
}
111-
]
130+
],
131+
output: '<template></template><style></style><script></script>'
112132
},
113133
{
114134
code: '<template></template><script></script><style></style>',
@@ -119,7 +139,8 @@ tester.run('component-tags-order', rule, {
119139
line: 1,
120140
column: 22
121141
}
122-
]
142+
],
143+
output: '<script></script><template></template><style></style>'
123144
},
124145
{
125146
code: `
@@ -133,7 +154,14 @@ tester.run('component-tags-order', rule, {
133154
message: 'The <script> should be above the <style> on line 4.',
134155
line: 6
135156
}
136-
]
157+
],
158+
output:
159+
'\n' +
160+
' <template></template>\n' +
161+
'\n' +
162+
' <script></script>\n' +
163+
'\n' +
164+
' <style></style>'
137165
},
138166
{
139167
code: `
@@ -147,7 +175,13 @@ tester.run('component-tags-order', rule, {
147175
message: 'The <script> should be above the <template> on line 2.',
148176
line: 3
149177
}
150-
]
178+
],
179+
output:
180+
'\n' +
181+
' <script></script>\n' +
182+
' <template></template>\n' +
183+
' <style></style>\n' +
184+
' '
151185
},
152186
{
153187
code: `
@@ -161,7 +195,13 @@ tester.run('component-tags-order', rule, {
161195
message: 'The <template> should be above the <script> on line 2.',
162196
line: 3
163197
}
164-
]
198+
],
199+
output:
200+
'\n' +
201+
' <template></template>\n' +
202+
' <script></script>\n' +
203+
' <style></style>\n' +
204+
' '
165205
},
166206
{
167207
code: `
@@ -176,7 +216,14 @@ tester.run('component-tags-order', rule, {
176216
message: 'The <docs> should be above the <template> on line 2.',
177217
line: 3
178218
}
179-
]
219+
],
220+
output:
221+
'\n' +
222+
' <docs></docs>\n' +
223+
' <template></template>\n' +
224+
' <script></script>\n' +
225+
' <style></style>\n' +
226+
' '
180227
},
181228
{
182229
code: `
@@ -191,7 +238,14 @@ tester.run('component-tags-order', rule, {
191238
message: 'The <script> should be above the <template> on line 2.',
192239
line: 4
193240
}
194-
]
241+
],
242+
output:
243+
'\n' +
244+
' <script></script>\n' +
245+
' <template></template>\n' +
246+
' <docs></docs>\n' +
247+
' <style></style>\n' +
248+
' '
195249
},
196250
{
197251
code: `
@@ -207,7 +261,15 @@ tester.run('component-tags-order', rule, {
207261
message: 'The <script> should be above the <template> on line 2.',
208262
line: 5
209263
}
210-
]
264+
],
265+
output:
266+
'\n' +
267+
' <script></script>\n' +
268+
' <template></template>\n' +
269+
' <docs>\n' +
270+
' </docs>\n' +
271+
' <style></style>\n' +
272+
' '
211273
},
212274
{
213275
code: `
@@ -220,7 +282,9 @@ tester.run('component-tags-order', rule, {
220282
message: 'The <template> should be above the <script> on line 2.',
221283
line: 3
222284
}
223-
]
285+
],
286+
output:
287+
'\n <template></template>\n <script></script>\n '
224288
},
225289
{
226290
code: `
@@ -237,7 +301,13 @@ tester.run('component-tags-order', rule, {
237301
message: 'The <script> should be above the <style> on line 2.',
238302
line: 4
239303
}
240-
]
304+
],
305+
output:
306+
'\n' +
307+
' <template></template>\n' +
308+
' <style></style>\n' +
309+
' <script></script>\n' +
310+
' '
241311
},
242312
{
243313
code: `
@@ -255,7 +325,14 @@ tester.run('component-tags-order', rule, {
255325
message: 'The <script> should be above the <style> on line 2.',
256326
line: 5
257327
}
258-
]
328+
],
329+
output:
330+
'\n' +
331+
' <template></template>\n' +
332+
' <style></style>\n' +
333+
' <docs></docs>\n' +
334+
' <script></script>\n' +
335+
' '
259336
},
260337
// no <template>
261338
{
@@ -268,7 +345,23 @@ tester.run('component-tags-order', rule, {
268345
message: 'The <script> should be above the <style> on line 2.',
269346
line: 3
270347
}
271-
]
348+
],
349+
output: '\n <script></script>\n <style></style>\n '
272350
}
273351
]
274352
})
353+
354+
describe('suppress reporting with eslint-disable-next-line', () => {
355+
it('disable all rules if <!-- eslint-disable-line -->', async () => {
356+
const code = `<style></style><template></template>
357+
<!-- eslint-disable-next-line vue/component-tags-order -->
358+
<script></script>`
359+
const [{ messages }] = await eslint.lintText(code, { filePath: 'test.vue' })
360+
assert.strictEqual(messages.length, 1)
361+
// should not fix <script>
362+
assert.strictEqual(
363+
messages[0].fix.text,
364+
'<template></template><style></style>'
365+
)
366+
})
367+
})

0 commit comments

Comments
 (0)