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
13 changes: 4 additions & 9 deletions lib/rules/block-tag-newline.js
Original file line number Diff line number Diff line change
Expand Up @@ -347,13 +347,6 @@ module.exports = {

const verify = normalizeOptionValue(context.options[0])

/**
* @returns {VElement[]}
*/
function getTopLevelHTMLElements() {
return documentFragment.children.filter(utils.isVElement)
}

return utils.defineTemplateBodyVisitor(
context,
{},
Expand All @@ -364,8 +357,10 @@ module.exports = {
return
}

for (const element of getTopLevelHTMLElements()) {
verify(element)
for (const element of documentFragment.children) {
if (utils.isVElement(element)) {
verify(element)
}
}
}
}
Expand Down
111 changes: 73 additions & 38 deletions lib/rules/html-closing-bracket-newline.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ module.exports = {
},
/** @param {RuleContext} context */
create(context) {
const df =
context.parserServices.getDocumentFragment &&
context.parserServices.getDocumentFragment()
if (!df) {
return {}
}

const options = Object.assign(
{},
{
Expand All @@ -68,48 +75,76 @@ module.exports = {
context.parserServices.getTemplateBodyTokenStore &&
context.parserServices.getTemplateBodyTokenStore()

return utils.defineTemplateBodyVisitor(context, {
/** @param {VStartTag | VEndTag} node */
'VStartTag, VEndTag'(node) {
const closingBracketToken = template.getLastToken(node)
if (
closingBracketToken.type !== 'HTMLSelfClosingTagClose' &&
closingBracketToken.type !== 'HTMLTagClose'
) {
return
}
/** @param {VStartTag | VEndTag} node */
function verify(node) {
const closingBracketToken = template.getLastToken(node)
if (
closingBracketToken.type !== 'HTMLSelfClosingTagClose' &&
closingBracketToken.type !== 'HTMLTagClose'
) {
return
}

const prevToken = template.getTokenBefore(closingBracketToken)
const type =
node.loc.start.line === prevToken.loc.end.line
? 'singleline'
: 'multiline'
const expectedLineBreaks = options[type] === 'always' ? 1 : 0
const actualLineBreaks =
closingBracketToken.loc.start.line - prevToken.loc.end.line

if (actualLineBreaks !== expectedLineBreaks) {
context.report({
node,
loc: {
start: prevToken.loc.end,
end: closingBracketToken.loc.start
},
message:
'Expected {{expected}} before closing bracket, but {{actual}} found.',
data: {
expected: getPhrase(expectedLineBreaks),
actual: getPhrase(actualLineBreaks)
},
fix(fixer) {
/** @type {Range} */
const range = [prevToken.range[1], closingBracketToken.range[0]]
const text = '\n'.repeat(expectedLineBreaks)
return fixer.replaceTextRange(range, text)
}
})
}
}

const documentFragment = df

const prevToken = template.getTokenBefore(closingBracketToken)
const type =
node.loc.start.line === prevToken.loc.end.line
? 'singleline'
: 'multiline'
const expectedLineBreaks = options[type] === 'always' ? 1 : 0
const actualLineBreaks =
closingBracketToken.loc.start.line - prevToken.loc.end.line
return utils.defineTemplateBodyVisitor(
context,
{
/** @param {VStartTag | VEndTag} node */
'VStartTag, VEndTag': verify
},
{
/** @param {Program} node */
Program(node) {
if (utils.hasInvalidEOF(node)) {
return
}

if (actualLineBreaks !== expectedLineBreaks) {
context.report({
node,
loc: {
start: prevToken.loc.end,
end: closingBracketToken.loc.start
},
message:
'Expected {{expected}} before closing bracket, but {{actual}} found.',
data: {
expected: getPhrase(expectedLineBreaks),
actual: getPhrase(actualLineBreaks)
},
fix(fixer) {
/** @type {Range} */
const range = [prevToken.range[1], closingBracketToken.range[0]]
const text = '\n'.repeat(expectedLineBreaks)
return fixer.replaceTextRange(range, text)
for (const element of documentFragment.children) {
if (!utils.isVElement(element) || element.name === 'template') {
continue
}
})

verify(element.startTag)

if (element.endTag !== null) {
verify(element.endTag)
}
}
}
}
})
)
}
}
110 changes: 72 additions & 38 deletions lib/rules/html-closing-bracket-spacing.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,52 +86,86 @@ module.exports = {
},
/** @param {RuleContext} context */
create(context) {
const df =
context.parserServices.getDocumentFragment &&
context.parserServices.getDocumentFragment()
if (!df) {
return {}
}

const sourceCode = context.getSourceCode()
const tokens =
context.parserServices.getTemplateBodyTokenStore &&
context.parserServices.getTemplateBodyTokenStore()
const options = parseOptions(context.options[0], tokens)

return utils.defineTemplateBodyVisitor(context, {
/** @param {VStartTag | VEndTag} node */
'VStartTag, VEndTag'(node) {
const type = options.detectType(node)
const lastToken = tokens.getLastToken(node)
const prevToken = tokens.getLastToken(node, 1)

// Skip if EOF exists in the tag or linebreak exists before `>`.
if (
type == null ||
prevToken == null ||
prevToken.loc.end.line !== lastToken.loc.start.line
) {
return
}
/** @param {VStartTag | VEndTag} node */
function verify(node) {
const type = options.detectType(node)
const lastToken = tokens.getLastToken(node)
const prevToken = tokens.getLastToken(node, 1)

// Skip if EOF exists in the tag or linebreak exists before `>`.
if (
type == null ||
prevToken == null ||
prevToken.loc.end.line !== lastToken.loc.start.line
) {
return
}

// Check and report.
const hasSpace = prevToken.range[1] !== lastToken.range[0]
if (type === 'always' && !hasSpace) {
context.report({
node,
loc: lastToken.loc,
message: "Expected a space before '{{bracket}}', but not found.",
data: { bracket: sourceCode.getText(lastToken) },
fix: (fixer) => fixer.insertTextBefore(lastToken, ' ')
})
} else if (type === 'never' && hasSpace) {
context.report({
node,
loc: {
start: prevToken.loc.end,
end: lastToken.loc.end
},
message: "Expected no space before '{{bracket}}', but found.",
data: { bracket: sourceCode.getText(lastToken) },
fix: (fixer) =>
fixer.removeRange([prevToken.range[1], lastToken.range[0]])
})
}
}

const documentFragment = df

return utils.defineTemplateBodyVisitor(
context,
{
'VStartTag, VEndTag': verify
},
{
/** @param {Program} node */
Program(node) {
if (utils.hasInvalidEOF(node)) {
return
}

for (const element of documentFragment.children) {
if (!utils.isVElement(element) || element.name === 'template') {
continue
}

verify(element.startTag)

// Check and report.
const hasSpace = prevToken.range[1] !== lastToken.range[0]
if (type === 'always' && !hasSpace) {
context.report({
node,
loc: lastToken.loc,
message: "Expected a space before '{{bracket}}', but not found.",
data: { bracket: sourceCode.getText(lastToken) },
fix: (fixer) => fixer.insertTextBefore(lastToken, ' ')
})
} else if (type === 'never' && hasSpace) {
context.report({
node,
loc: {
start: prevToken.loc.end,
end: lastToken.loc.end
},
message: "Expected no space before '{{bracket}}', but found.",
data: { bracket: sourceCode.getText(lastToken) },
fix: (fixer) =>
fixer.removeRange([prevToken.range[1], lastToken.range[0]])
})
if (element.endTag !== null) {
verify(element.endTag)
}
}
}
}
})
)
}
}
Loading