Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit cae6d29

Browse files
authored
Add consistent option to vue/padding-line-between-tags (#1982)
* Add consistent rule * Make consistent only considers blocks with consistent rule * Use first element as guide for rest of siblings * Simplify logic * Remove unused
1 parent f4f946a commit cae6d29

File tree

2 files changed

+364
-73
lines changed

2 files changed

+364
-73
lines changed

‎lib/rules/padding-line-between-tags.js‎

Lines changed: 95 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -24,44 +24,75 @@ function splitLines(text) {
2424
* @param {RuleContext} context
2525
* @param {VElement} tag
2626
* @param {VElement} sibling
27+
* @param {number} lineDifference
2728
*/
28-
function insertNewLine(context, tag, sibling) {
29-
context.report({
30-
messageId: 'always',
31-
loc: sibling.loc,
32-
// @ts-ignore
33-
fix(fixer) {
34-
return fixer.insertTextAfter(tag, '\n')
35-
}
36-
})
29+
function insertNewLine(context, tag, sibling, lineDifference) {
30+
const endTag = tag.endTag || tag.startTag
31+
32+
if (lineDifference === 1) {
33+
context.report({
34+
messageId: 'always',
35+
loc: sibling.loc,
36+
// @ts-ignore
37+
fix(fixer) {
38+
return fixer.insertTextAfter(tag, '\n')
39+
}
40+
})
41+
} else if (lineDifference === 0) {
42+
context.report({
43+
messageId: 'always',
44+
loc: sibling.loc,
45+
// @ts-ignore
46+
fix(fixer) {
47+
const lastSpaces = /** @type {RegExpExecArray} */ (
48+
/^\s*/.exec(context.getSourceCode().lines[endTag.loc.start.line - 1])
49+
)[0]
50+
51+
return fixer.insertTextAfter(endTag, `\n\n${lastSpaces}`)
52+
}
53+
})
54+
}
3755
}
3856

3957
/**
4058
* @param {RuleContext} context
4159
* @param {VEndTag | VStartTag} endTag
4260
* @param {VElement} sibling
61+
* @param {number} lineDifference
4362
*/
44-
function removeExcessLines(context, endTag, sibling) {
45-
context.report({
46-
messageId: 'never',
47-
loc: sibling.loc,
48-
// @ts-ignore
49-
fix(fixer) {
50-
const start = endTag.range[1]
51-
const end = sibling.range[0]
52-
const paddingText = context.getSourceCode().text.slice(start, end)
53-
const textBetween = splitLines(paddingText)
54-
let newTextBetween = `\n${textBetween.pop()}`
55-
for (let i = textBetween.length - 1; i >= 0; i--) {
56-
if (!/^\s*$/.test(textBetween[i])) {
57-
newTextBetween = `${i === 0 ? '' : '\n'}${
58-
textBetween[i]
59-
}${newTextBetween}`
63+
function removeExcessLines(context, endTag, sibling, lineDifference) {
64+
if (lineDifference > 1) {
65+
let hasOnlyTextBetween = true
66+
for (
67+
let i = endTag.loc.start.line;
68+
i < sibling.loc.start.line - 1 && hasOnlyTextBetween;
69+
i++
70+
) {
71+
hasOnlyTextBetween = !/^\s*$/.test(context.getSourceCode().lines[i])
72+
}
73+
if (!hasOnlyTextBetween) {
74+
context.report({
75+
messageId: 'never',
76+
loc: sibling.loc,
77+
// @ts-ignore
78+
fix(fixer) {
79+
const start = endTag.range[1]
80+
const end = sibling.range[0]
81+
const paddingText = context.getSourceCode().text.slice(start, end)
82+
const textBetween = splitLines(paddingText)
83+
let newTextBetween = `\n${textBetween.pop()}`
84+
for (let i = textBetween.length - 1; i >= 0; i--) {
85+
if (!/^\s*$/.test(textBetween[i])) {
86+
newTextBetween = `${i === 0 ? '' : '\n'}${
87+
textBetween[i]
88+
}${newTextBetween}`
89+
}
90+
}
91+
return fixer.replaceTextRange([start, end], `${newTextBetween}`)
6092
}
61-
}
62-
return fixer.replaceTextRange([start, end], `${newTextBetween}`)
93+
})
6394
}
64-
})
95+
}
6596
}
6697

6798
// ------------------------------------------------------------------------------
@@ -72,11 +103,19 @@ function removeExcessLines(context, endTag, sibling) {
72103
* @param {RuleContext} context
73104
*/
74105
function checkNewline(context) {
75-
/** @type {Array<{blankLine: "always" | "never", prev: string, next: string}>} */
106+
/** @type {Array<{blankLine: "always" | "never" | "consistent", prev: string, next: string}>} */
76107
const configureList = context.options[0] || [
77108
{ blankLine: 'always', prev: '*', next: '*' }
78109
]
79110

111+
const reverseConfigureList = [...configureList].reverse()
112+
113+
/**
114+
* It has the style of the first `blankLine="consistent"`.
115+
* @type {Map<VElement, "always" | "never">}
116+
*/
117+
const firstConsistentBlankLines = new Map()
118+
80119
/**
81120
* @param {VElement} block
82121
*/
@@ -99,53 +138,36 @@ function checkNewline(context) {
99138

100139
const closestSibling = /** @type {VElement} */ (lowerSiblings[0])
101140

102-
for (let i = configureList.length - 1; i >= 0; --i) {
103-
const configure = configureList[i]
104-
const matched =
141+
const configure = reverseConfigureList.find(
142+
(configure) =>
105143
(configure.prev === '*' || block.name === configure.prev) &&
106144
(configure.next === '*' || closestSibling.name === configure.next)
145+
)
107146

108-
if (matched) {
109-
const lineDifference =
110-
closestSibling.loc.start.line - endTag.loc.end.line
111-
if (configure.blankLine === 'always') {
112-
if (lineDifference === 1) {
113-
insertNewLine(context, block, closestSibling)
114-
} else if (lineDifference === 0) {
115-
context.report({
116-
messageId: 'always',
117-
loc: closestSibling.loc,
118-
// @ts-ignore
119-
fix(fixer) {
120-
const lastSpaces = /** @type {RegExpExecArray} */ (
121-
/^\s*/.exec(
122-
context.getSourceCode().lines[endTag.loc.start.line - 1]
123-
)
124-
)[0]
125-
126-
return fixer.insertTextAfter(endTag, `\n\n${lastSpaces}`)
127-
}
128-
})
129-
}
130-
} else {
131-
if (lineDifference > 1) {
132-
let hasOnlyTextBetween = true
133-
for (
134-
let i = endTag.loc.start.line;
135-
i < closestSibling.loc.start.line - 1 && hasOnlyTextBetween;
136-
i++
137-
) {
138-
hasOnlyTextBetween = !/^\s*$/.test(
139-
context.getSourceCode().lines[i]
140-
)
141-
}
142-
if (!hasOnlyTextBetween) {
143-
removeExcessLines(context, endTag, closestSibling)
144-
}
145-
}
146-
}
147-
break
147+
if (!configure) {
148+
return
149+
}
150+
const lineDifference = closestSibling.loc.start.line - endTag.loc.end.line
151+
152+
let blankLine = configure.blankLine
153+
if (blankLine === 'consistent') {
154+
const firstConsistentBlankLine = firstConsistentBlankLines.get(
155+
block.parent
156+
)
157+
if (firstConsistentBlankLine == null) {
158+
firstConsistentBlankLines.set(
159+
block.parent,
160+
lineDifference > 1 ? 'always' : 'never'
161+
)
162+
return
148163
}
164+
blankLine = firstConsistentBlankLine
165+
}
166+
167+
if (blankLine === 'always') {
168+
insertNewLine(context, block, closestSibling, lineDifference)
169+
} else {
170+
removeExcessLines(context, endTag, closestSibling, lineDifference)
149171
}
150172
}
151173
}
@@ -166,7 +188,7 @@ module.exports = {
166188
items: {
167189
type: 'object',
168190
properties: {
169-
blankLine: { enum: ['always', 'never'] },
191+
blankLine: { enum: ['always', 'never','consistent'] },
170192
prev: { type: 'string' },
171193
next: { type: 'string' }
172194
},

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /