Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fix bug with multiple not pseudo-selectors
  • Loading branch information
doug-wade committed Apr 2, 2022
commit 918fca1e35534f79e04493a312e01ec3bd555249
42 changes: 26 additions & 16 deletions lib/rules/component-tags-order.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ module.exports = {
url: 'https://eslint.vuejs.org/rules/component-tags-order.html'
},
fixable: 'code',
messages: {
unexpected:
'The <{{elementName}}{{elementAttributes}}> should be above the <{{firstUnorderedName}}{{firstUnorderedAttributes}}> on line {{line}}.'
},
schema: [
{
type: 'object',
Expand Down Expand Up @@ -92,35 +96,34 @@ module.exports = {
* @return {Boolean} true if the element matches the selector, false otherwise
*/
function matches(ordering, element) {
let hasMatch = true
let attributeMatches = true
let isNegated = false
let tagMatches = true

parser((selectors) => {
selectors.walk((selector) => {
switch (selector.type) {
case 'tag':
hasMatch = hasMatch && selector.value === element.name
tagMatches = selector.value === element.name
break
case 'pseudo':
isNegated = selector.value === ':not'
break
case 'attribute':
hasMatch =
hasMatch &&
utils.hasAttribute(
element,
selector.qualifiedAttribute,
selector.value
)
attributeMatches = utils.hasAttribute(
element,
selector.qualifiedAttribute,
selector.value
)
break
}
})
}).processSync(ordering)

if (isNegated) {
return !hasMatch
return tagMatches && !attributeMatches
} else {
return hasMatch
return tagMatches && attributeMatches
}
}

Expand Down Expand Up @@ -170,11 +173,18 @@ module.exports = {
context.report({
node: element,
loc: element.loc,
message: `The <${element.name}${
elementAttributes ? ' ' + elementAttributes : ''
}> should be above the <${firstUnordered.name}${
firstUnorderedttributes ? ' ' + firstUnorderedttributes : ''
}> on line ${firstUnordered.loc.start.line}.`,
messageId: 'unexpected',
data: {
elementName: element.name,
elementAttributes: elementAttributes
? ' ' + elementAttributes
: '',
firstUnorderedName: firstUnordered.name,
firstUnorderedAttributes: firstUnorderedttributes
? ' ' + firstUnorderedttributes
: '',
line: firstUnordered.loc.start.line
},
*fix(fixer) {
// insert element before firstUnordered
const fixedElements = elements.flatMap((it) => {
Expand Down
81 changes: 81 additions & 0 deletions tests/lib/rules/component-tags-order.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,65 @@ tester.run('component-tags-order', rule, {
output: null,
options: [{ order: [['script[setup]', 'script', 'template'], 'style'] }]
},
{
code: '<script></script><script setup></script><template></template><style></style>',
output: null,
options: [{ order: ['script', 'script[setup]', 'template', 'style'] }]
},
{
code: '<template></template><script></script><script setup></script><style></style>',
output: null,
options: [{ order: [['script', 'script[setup]', 'template'], 'style'] }]
},
{
code: '<script></script><script setup></script><template></template><style></style>',
output: null,
options: [
{ order: ['script:not([setup])', 'script[setup]', 'template', 'style'] }
]
},
{
code: '<template></template><script></script><script setup></script><style></style>',
output: null,
options: [
{
order: [['script:not([setup])', 'script[setup]', 'template'], 'style']
}
]
},
{
code: '<template></template><script></script><script setup></script><style scoped></style><style></style><i18n lang="ja"></i18n><i18n lang="en"></i18n>',
output: null,
options: [
{
order: [
['script:not([setup])', 'script[setup]', 'template'],
'style[scoped]',
'style:not([scoped])',
'i18n:not([lang=en])',
'i18n:not([lang=ja])'
]
}
]
},
,
{
code: '<template></template><script></script><script setup></script><style scoped></style><style></style><i18n lang="en"></i18n><i18n lang="ja"></i18n>',
output: null,
options: [
{
order: [
'template',
'script:not([setup])',
'script[setup]',
'style[scoped]',
'style:not([scoped])',
'i18n[lang=en]',
'i18n[lang=ja]'
]
}
]
},
{
code: '<template></template><docs></docs><script></script><style></style>',
output: null,
Expand Down Expand Up @@ -393,6 +452,28 @@ tester.run('component-tags-order', rule, {
line: 1
}
]
},
{
code: '<style></style><style scoped></style>',
output: '<style scoped></style><style></style>',
options: [{ order: ['style[scoped]', 'style:not([scoped])'] }],
errors: [
{
message: 'The <style scoped> should be above the <style> on line 1.',
line: 1
}
]
},
{
code: '<style></style><script></script>',
output: '<script></script><style></style>',
options: [{ order: ['script:not([scoped])', 'style:not([scoped])'] }],
errors: [
{
message: 'The <script> should be above the <style> on line 1.',
line: 1
}
]
}
]
})
Expand Down