Skip to content

Commit

Permalink
Auto-fix for vue/component-tags-order
Browse files Browse the repository at this point in the history
  • Loading branch information
lsdsjy committed Mar 2, 2022
1 parent 37a03ed commit 1bba567
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 32 deletions.
51 changes: 31 additions & 20 deletions lib/rules/component-tags-order.js
Expand Up @@ -24,7 +24,7 @@ module.exports = {
categories: ['vue3-recommended', 'recommended'],
url: 'https://eslint.vuejs.org/rules/component-tags-order.html'
},
fixable: null,
fixable: 'code',
schema: [
{
type: 'object',
Expand Down Expand Up @@ -87,30 +87,13 @@ module.exports = {
return []
}

/**
* @param {VElement} element
* @param {VElement} firstUnorderedElement
*/
function report(element, firstUnorderedElement) {
context.report({
node: element,
loc: element.loc,
messageId: 'unexpected',
data: {
name: element.name,
firstUnorderedName: firstUnorderedElement.name,
line: firstUnorderedElement.loc.start.line
}
})
}

return {
Program(node) {
if (utils.hasInvalidEOF(node)) {
return
}
const elements = getTopLevelHTMLElements()

const sourceCode = context.getSourceCode()
elements.forEach((element, index) => {
const expectedIndex = getOrderPosition(element.name)
if (expectedIndex < 0) {
Expand All @@ -123,7 +106,35 @@ module.exports = {
(e1, e2) => getOrderPosition(e1.name) - getOrderPosition(e2.name)
)[0]
if (firstUnordered) {
report(element, firstUnordered)
context.report({
node: element,
loc: element.loc,
messageId: 'unexpected',
data: {
name: element.name,
firstUnorderedName: firstUnordered.name,
line: firstUnordered.loc.start.line
},
*fix(fixer) {
// insert element before firstUnordered
const fixedElements = elements.flatMap((it) => {
if (it === firstUnordered) {
return [element, it]
} else if (it === element) {
return []
}
return [it]
})
for (let i = elements.length - 1; i >= 0; i--) {
if (elements[i] !== fixedElements[i]) {
yield fixer.replaceTextRange(
elements[i].range,
sourceCode.text.slice(...fixedElements[i].range)
)
}
}
}
})
}
})
}
Expand Down
117 changes: 105 additions & 12 deletions tests/lib/rules/component-tags-order.js
Expand Up @@ -9,6 +9,25 @@

const rule = require('../../../lib/rules/component-tags-order')
const RuleTester = require('eslint').RuleTester
const assert = require('assert')
const { ESLint } = require('../../eslint-compat')

// Initialize linter.
const eslint = new ESLint({
overrideConfig: {
parser: require.resolve('vue-eslint-parser'),
parserOptions: {
ecmaVersion: 2015
},
plugins: ['vue'],
rules: {
'vue/comment-directive': 'error',
'vue/component-tags-order': 'error'
}
},
useEslintrc: false,
plugins: { vue: require('../../../lib/index') }
})

// ------------------------------------------------------------------------------
// Tests
Expand Down Expand Up @@ -108,7 +127,8 @@ tester.run('component-tags-order', rule, {
line: 1,
column: 37
}
]
],
output: '<template></template><style></style><script></script>'
},
{
code: '<template></template><script></script><style></style>',
Expand All @@ -119,7 +139,8 @@ tester.run('component-tags-order', rule, {
line: 1,
column: 22
}
]
],
output: '<script></script><template></template><style></style>'
},
{
code: `
Expand All @@ -133,7 +154,14 @@ tester.run('component-tags-order', rule, {
message: 'The <script> should be above the <style> on line 4.',
line: 6
}
]
],
output:
'\n' +
' <template></template>\n' +
'\n' +
' <script></script>\n' +
'\n' +
' <style></style>'
},
{
code: `
Expand All @@ -147,7 +175,13 @@ tester.run('component-tags-order', rule, {
message: 'The <script> should be above the <template> on line 2.',
line: 3
}
]
],
output:
'\n' +
' <script></script>\n' +
' <template></template>\n' +
' <style></style>\n' +
' '
},
{
code: `
Expand All @@ -161,7 +195,13 @@ tester.run('component-tags-order', rule, {
message: 'The <template> should be above the <script> on line 2.',
line: 3
}
]
],
output:
'\n' +
' <template></template>\n' +
' <script></script>\n' +
' <style></style>\n' +
' '
},
{
code: `
Expand All @@ -176,7 +216,14 @@ tester.run('component-tags-order', rule, {
message: 'The <docs> should be above the <template> on line 2.',
line: 3
}
]
],
output:
'\n' +
' <docs></docs>\n' +
' <template></template>\n' +
' <script></script>\n' +
' <style></style>\n' +
' '
},
{
code: `
Expand All @@ -191,7 +238,14 @@ tester.run('component-tags-order', rule, {
message: 'The <script> should be above the <template> on line 2.',
line: 4
}
]
],
output:
'\n' +
' <script></script>\n' +
' <template></template>\n' +
' <docs></docs>\n' +
' <style></style>\n' +
' '
},
{
code: `
Expand All @@ -207,7 +261,15 @@ tester.run('component-tags-order', rule, {
message: 'The <script> should be above the <template> on line 2.',
line: 5
}
]
],
output:
'\n' +
' <script></script>\n' +
' <template></template>\n' +
' <docs>\n' +
' </docs>\n' +
' <style></style>\n' +
' '
},
{
code: `
Expand All @@ -220,7 +282,9 @@ tester.run('component-tags-order', rule, {
message: 'The <template> should be above the <script> on line 2.',
line: 3
}
]
],
output:
'\n <template></template>\n <script></script>\n '
},
{
code: `
Expand All @@ -237,7 +301,13 @@ tester.run('component-tags-order', rule, {
message: 'The <script> should be above the <style> on line 2.',
line: 4
}
]
],
output:
'\n' +
' <template></template>\n' +
' <style></style>\n' +
' <script></script>\n' +
' '
},
{
code: `
Expand All @@ -255,7 +325,14 @@ tester.run('component-tags-order', rule, {
message: 'The <script> should be above the <style> on line 2.',
line: 5
}
]
],
output:
'\n' +
' <template></template>\n' +
' <style></style>\n' +
' <docs></docs>\n' +
' <script></script>\n' +
' '
},
// no <template>
{
Expand All @@ -268,7 +345,23 @@ tester.run('component-tags-order', rule, {
message: 'The <script> should be above the <style> on line 2.',
line: 3
}
]
],
output: '\n <script></script>\n <style></style>\n '
}
]
})

describe('suppress reporting with eslint-disable-next-line', () => {
it('do not report if <!-- eslint-disable-next-line -->', async () => {
const code = `<style></style><template></template>
<!-- eslint-disable-next-line vue/component-tags-order -->
<script></script>`
const [{ messages }] = await eslint.lintText(code, { filePath: 'test.vue' })
assert.strictEqual(messages.length, 1)
// should not fix <script>
assert.strictEqual(
messages[0].fix.text,
'<template></template><style></style>'
)
})
})

0 comments on commit 1bba567

Please sign in to comment.