Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add consistent option to vue/padding-line-between-tags #1982

Merged
merged 5 commits into from Sep 30, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
165 changes: 104 additions & 61 deletions lib/rules/padding-line-between-tags.js
Expand Up @@ -24,44 +24,89 @@ function splitLines(text) {
* @param {RuleContext} context
* @param {VElement} tag
* @param {VElement} sibling
* @param {number} lineDifference
*/
function insertNewLine(context, tag, sibling) {
context.report({
messageId: 'always',
loc: sibling.loc,
// @ts-ignore
fix(fixer) {
return fixer.insertTextAfter(tag, '\n')
}
})
function insertNewLine(context, tag, sibling, lineDifference) {
const endTag = tag.endTag || tag.startTag

if (lineDifference === 1) {
context.report({
messageId: 'always',
loc: sibling.loc,
// @ts-ignore
fix(fixer) {
return fixer.insertTextAfter(tag, '\n')
}
})
} else if (lineDifference === 0) {
context.report({
messageId: 'always',
loc: sibling.loc,
// @ts-ignore
fix(fixer) {
const lastSpaces = /** @type {RegExpExecArray} */ (
/^\s*/.exec(context.getSourceCode().lines[endTag.loc.start.line - 1])
)[0]

return fixer.insertTextAfter(endTag, `\n\n${lastSpaces}`)
}
})
}
}

/**
* @param {RuleContext} context
* @param {VEndTag | VStartTag} endTag
* @param {VElement} sibling
* @param {number} lineDifference
*/
function removeExcessLines(context, endTag, sibling) {
context.report({
messageId: 'never',
loc: sibling.loc,
// @ts-ignore
fix(fixer) {
const start = endTag.range[1]
const end = sibling.range[0]
const paddingText = context.getSourceCode().text.slice(start, end)
const textBetween = splitLines(paddingText)
let newTextBetween = `\n${textBetween.pop()}`
for (let i = textBetween.length - 1; i >= 0; i--) {
if (!/^\s*$/.test(textBetween[i])) {
newTextBetween = `${i === 0 ? '' : '\n'}${
textBetween[i]
}${newTextBetween}`
function removeExcessLines(context, endTag, sibling, lineDifference) {
if (lineDifference > 1) {
let hasOnlyTextBetween = true
for (
let i = endTag.loc.start.line;
i < sibling.loc.start.line - 1 && hasOnlyTextBetween;
i++
) {
hasOnlyTextBetween = !/^\s*$/.test(context.getSourceCode().lines[i])
}
if (!hasOnlyTextBetween) {
context.report({
messageId: 'never',
loc: sibling.loc,
// @ts-ignore
fix(fixer) {
const start = endTag.range[1]
const end = sibling.range[0]
const paddingText = context.getSourceCode().text.slice(start, end)
const textBetween = splitLines(paddingText)
let newTextBetween = `\n${textBetween.pop()}`
for (let i = textBetween.length - 1; i >= 0; i--) {
if (!/^\s*$/.test(textBetween[i])) {
newTextBetween = `${i === 0 ? '' : '\n'}${
textBetween[i]
}${newTextBetween}`
}
}
return fixer.replaceTextRange([start, end], `${newTextBetween}`)
}
}
return fixer.replaceTextRange([start, end], `${newTextBetween}`)
})
}
})
}
}

/**
* @param {VElement} block
* @param {Array<{blankLine: "always" | "never" | "consistent", prev: string, next: string}>} configureList
*/
function hasConsistentConfiguration(block, configureList) {
for (let i = configureList.length - 1; i >= 0; --i) {
const configure = configureList[i];
if (configure.blankLine !== 'consistent' && configure.prev === "*" || configure.prev === block.name) {
return false;
}
}
return true
}

// ------------------------------------------------------------------------------
Expand All @@ -72,7 +117,7 @@ function removeExcessLines(context, endTag, sibling) {
* @param {RuleContext} context
*/
function checkNewline(context) {
/** @type {Array<{blankLine: "always" | "never", prev: string, next: string}>} */
/** @type {Array<{blankLine: "always" | "never" | "consistent", prev: string, next: string}>} */
const configureList = context.options[0] || [
{ blankLine: 'always', prev: '*', next: '*' }
]
Expand Down Expand Up @@ -109,40 +154,38 @@ function checkNewline(context) {
const lineDifference =
closestSibling.loc.start.line - endTag.loc.end.line
if (configure.blankLine === 'always') {
if (lineDifference === 1) {
insertNewLine(context, block, closestSibling)
} else if (lineDifference === 0) {
context.report({
messageId: 'always',
loc: closestSibling.loc,
// @ts-ignore
fix(fixer) {
const lastSpaces = /** @type {RegExpExecArray} */ (
/^\s*/.exec(
context.getSourceCode().lines[endTag.loc.start.line - 1]
)
)[0]

return fixer.insertTextAfter(endTag, `\n\n${lastSpaces}`)
}
})
}
} else {
if (lineDifference > 1) {
let hasOnlyTextBetween = true
for (
let i = endTag.loc.start.line;
i < closestSibling.loc.start.line - 1 && hasOnlyTextBetween;
i++
) {
hasOnlyTextBetween = !/^\s*$/.test(
context.getSourceCode().lines[i]
)
insertNewLine(context, block, closestSibling, lineDifference)
} else if (configure.blankLine === 'consistent') {
dev1437 marked this conversation as resolved.
Show resolved Hide resolved
let newlineCount = 0
let siblingLineDifference = 0
/** @type {VElement | null} */
let prevChild = null
const siblingElements = block.parent.children.filter(
(element) => element.type === 'VElement' && hasConsistentConfiguration(element, configureList)
)
// get parent
for (const child of siblingElements) {
if (!prevChild) {
prevChild = /** @type {VElement} */ (child)
continue
}
if (!hasOnlyTextBetween) {
removeExcessLines(context, endTag, closestSibling)
siblingLineDifference =
child.loc.start.line - prevChild.loc.end.line

if (siblingLineDifference > 1) {
newlineCount++
}
prevChild = /** @type {VElement} */ (child)
}
const ratio = newlineCount / (siblingElements.length - 1)

if (0.5 - ratio < 0.005) {
dev1437 marked this conversation as resolved.
Show resolved Hide resolved
insertNewLine(context, block, closestSibling, lineDifference)
} else {
removeExcessLines(context, endTag, closestSibling, lineDifference)
}
} else {
removeExcessLines(context, endTag, closestSibling, lineDifference)
}
break
}
Expand All @@ -166,7 +209,7 @@ module.exports = {
items: {
type: 'object',
properties: {
blankLine: { enum: ['always', 'never'] },
blankLine: { enum: ['always', 'never', 'consistent'] },
prev: { type: 'string' },
next: { type: 'string' }
},
Expand Down