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 ca2c962

Browse files
Add avoidEscape option to vue/html-quotes rule (#1031)
1 parent 5980cdc commit ca2c962

File tree

3 files changed

+112
-6
lines changed

3 files changed

+112
-6
lines changed

‎docs/rules/html-quotes.md‎

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,19 @@ Default is set to `double`.
4343

4444
```json
4545
{
46-
"vue/html-quotes": ["error", "double" | "single"]
46+
"vue/html-quotes": ["error", "double" | "single", { "avoidEscape": false } ]
4747
}
4848
```
4949

50+
String option:
51+
5052
- `"double"` (default) ... requires double quotes.
5153
- `"single"` ... requires single quotes.
5254

55+
Object option:
56+
57+
- `avoidEscape` ... If `true`, allows strings to use single-quotes or double-quotes so long as the string contains a quote that would have to be escaped otherwise.
58+
5359
### `"single"`
5460

5561
<eslint-code-block fix :rules="{'vue/html-quotes': ['error', 'single']}">
@@ -67,6 +73,23 @@ Default is set to `double`.
6773

6874
</eslint-code-block>
6975

76+
### `"double", { "avoidEscape": true }`
77+
78+
<eslint-code-block fix :rules="{'vue/html-quotes': ['error', 'double', { avoidEscape: true }]}">
79+
80+
```vue
81+
<template>
82+
<!-- ✓ GOOD -->
83+
<img title='a string containing "double" quotes'>
84+
85+
<!-- ✗ BAD -->
86+
<img title='foo'>
87+
<img title=bar>
88+
</template>
89+
```
90+
91+
</eslint-code-block>
92+
7093
## :books: Further reading
7194

7295
- [Style guide - Quoted attribute values](https://vuejs.org/v2/style-guide/#Quoted-attribute-values-strongly-recommended)

‎lib/rules/html-quotes.js‎

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,25 @@ module.exports = {
2525
},
2626
fixable: 'code',
2727
schema: [
28-
{ enum: ['double', 'single'] }
28+
{ enum: ['double', 'single'] },
29+
{
30+
type: 'object',
31+
properties: {
32+
avoidEscape: {
33+
type: 'boolean'
34+
}
35+
},
36+
additionalProperties: false
37+
}
2938
]
3039
},
3140

3241
create (context) {
3342
const sourceCode = context.getSourceCode()
3443
const double = context.options[0] !== 'single'
44+
const avoidEscape = context.options[1] && context.options[1].avoidEscape === true
3545
const quoteChar = double ? '"' : "'"
3646
const quoteName = double ? 'double quotes' : 'single quotes'
37-
const quotePattern = double ? /"/g : /'/g
38-
const quoteEscaped = double ? '&quot;' : '&apos;'
3947
let hasInvalidEOF
4048

4149
return utils.defineTemplateBodyVisitor(context, {
@@ -48,14 +56,35 @@ module.exports = {
4856
const firstChar = text[0]
4957

5058
if (firstChar !== quoteChar) {
59+
const quoted = (firstChar === "'" || firstChar === '"')
60+
if (avoidEscape && quoted) {
61+
const contentText = text.slice(1, -1)
62+
if (contentText.includes(quoteChar)) {
63+
return
64+
}
65+
}
66+
5167
context.report({
5268
node: node.value,
5369
loc: node.value.loc,
5470
message: 'Expected to be enclosed by {{kind}}.',
5571
data: { kind: quoteName },
5672
fix (fixer) {
57-
const contentText = (firstChar === "'" || firstChar === '"') ? text.slice(1, -1) : text
58-
const replacement = quoteChar + contentText.replace(quotePattern, quoteEscaped) + quoteChar
73+
const contentText = quoted ? text.slice(1, -1) : text
74+
75+
const fixToDouble = avoidEscape && !quoted && contentText.includes(quoteChar)
76+
? (
77+
double
78+
? contentText.includes("'")
79+
: !contentText.includes('"')
80+
)
81+
: double
82+
83+
const quotePattern = fixToDouble ? /"/g : /'/g
84+
const quoteEscaped = fixToDouble ? '&quot;' : '&apos;'
85+
const fixQuoteChar = fixToDouble ? '"' : "'"
86+
87+
const replacement = fixQuoteChar + contentText.replace(quotePattern, quoteEscaped) + fixQuoteChar
5988
return fixer.replaceText(node.value, replacement)
6089
}
6190
})

‎tests/lib/rules/html-quotes.js‎

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,17 @@ tester.run('html-quotes', rule, {
5555
code: "<template><div :class='foo'></div></template>",
5656
options: ['single']
5757
},
58+
// avoidEscape
59+
{
60+
filename: 'test.vue',
61+
code: "<template><div attr='foo\"bar'></div></template>",
62+
options: ['double', { avoidEscape: true }]
63+
},
64+
{
65+
filename: 'test.vue',
66+
code: "<template><div attr=\"foo'bar\"></div></template>",
67+
options: ['single', { avoidEscape: true }]
68+
},
5869

5970
// Invalid EOF
6071
{
@@ -166,6 +177,49 @@ tester.run('html-quotes', rule, {
166177
output: "<template><div :class='foo+&apos;bar&apos;'></div></template>",
167178
options: ['single'],
168179
errors: ['Expected to be enclosed by single quotes.']
180+
},
181+
// avoidEscape
182+
{
183+
filename: 'test.vue',
184+
code: "<template><div attr='foo'></div></template>",
185+
output: '<template><div attr="foo"></div></template>',
186+
options: ['double', { avoidEscape: true }],
187+
errors: ['Expected to be enclosed by double quotes.']
188+
},
189+
{
190+
filename: 'test.vue',
191+
code: '<template><div attr="bar"></div></template>',
192+
output: "<template><div attr='bar'></div></template>",
193+
options: ['single', { avoidEscape: true }],
194+
errors: ['Expected to be enclosed by single quotes.']
195+
},
196+
{
197+
filename: 'test.vue',
198+
code: '<template><div attr=foo"bar></div></template>',
199+
output: '<template><div attr=\'foo"bar\'></div></template>',
200+
options: ['double', { avoidEscape: true }],
201+
errors: ['Expected to be enclosed by double quotes.']
202+
},
203+
{
204+
filename: 'test.vue',
205+
code: '<template><div attr=foo\'bar></div></template>',
206+
output: "<template><div attr=\"foo'bar\"></div></template>",
207+
options: ['single', { avoidEscape: true }],
208+
errors: ['Expected to be enclosed by single quotes.']
209+
},
210+
{
211+
filename: 'test.vue',
212+
code: '<template><div attr=foo"bar\'baz></div></template>',
213+
output: '<template><div attr="foo&quot;bar\'baz"></div></template>',
214+
options: ['double', { avoidEscape: true }],
215+
errors: ['Expected to be enclosed by double quotes.']
216+
},
217+
{
218+
filename: 'test.vue',
219+
code: '<template><div attr=foo"bar\'baz></div></template>',
220+
output: '<template><div attr=\'foo"bar&apos;baz\'></div></template>',
221+
options: ['single', { avoidEscape: true }],
222+
errors: ['Expected to be enclosed by single quotes.']
169223
}
170224
]
171225
})

0 commit comments

Comments
(0)

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