diff --git a/docs/rules/html-quotes.md b/docs/rules/html-quotes.md
index aa0180de9..2d95009fe 100644
--- a/docs/rules/html-quotes.md
+++ b/docs/rules/html-quotes.md
@@ -43,13 +43,19 @@ Default is set to `double`.
```json
{
- "vue/html-quotes": ["error", "double" | "single"]
+ "vue/html-quotes": [ "error", "double" | "single", { "avoidEscape": false } ]
}
```
+String option:
+
- `"double"` (default) ... requires double quotes.
- `"single"` ... requires single quotes.
+Object option:
+
+- `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.
+
### `"single"`
@@ -67,6 +73,23 @@ Default is set to `double`.
+### `"double", { "avoidEscape": true }`
+
+
+
+```vue
+
+
+
+
+
+
+
+
+```
+
+
+
## :books: Further reading
- [Style guide - Quoted attribute values](https://vuejs.org/v2/style-guide/#Quoted-attribute-values-strongly-recommended)
diff --git a/lib/rules/html-quotes.js b/lib/rules/html-quotes.js
index c8392abef..b27b9d98d 100644
--- a/lib/rules/html-quotes.js
+++ b/lib/rules/html-quotes.js
@@ -25,17 +25,25 @@ module.exports = {
},
fixable: 'code',
schema: [
- { enum: ['double', 'single'] }
+ { enum: ['double', 'single'] },
+ {
+ type: 'object',
+ properties: {
+ avoidEscape: {
+ type: 'boolean'
+ }
+ },
+ additionalProperties: false
+ }
]
},
create (context) {
const sourceCode = context.getSourceCode()
const double = context.options[0] !== 'single'
+ const avoidEscape = context.options[1] && context.options[1].avoidEscape === true
const quoteChar = double ? '"' : "'"
const quoteName = double ? 'double quotes' : 'single quotes'
- const quotePattern = double ? /"/g : /'/g
- const quoteEscaped = double ? '"' : '''
let hasInvalidEOF
return utils.defineTemplateBodyVisitor(context, {
@@ -48,14 +56,35 @@ module.exports = {
const firstChar = text[0]
if (firstChar !== quoteChar) {
+ const quoted = (firstChar === "'" || firstChar === '"')
+ if (avoidEscape && quoted) {
+ const contentText = text.slice(1, -1)
+ if (contentText.includes(quoteChar)) {
+ return
+ }
+ }
+
context.report({
node: node.value,
loc: node.value.loc,
message: 'Expected to be enclosed by {{kind}}.',
data: { kind: quoteName },
fix (fixer) {
- const contentText = (firstChar === "'" || firstChar === '"') ? text.slice(1, -1) : text
- const replacement = quoteChar + contentText.replace(quotePattern, quoteEscaped) + quoteChar
+ const contentText = quoted ? text.slice(1, -1) : text
+
+ const fixToDouble = avoidEscape && !quoted && contentText.includes(quoteChar)
+ ? (
+ double
+ ? contentText.includes("'")
+ : !contentText.includes('"')
+ )
+ : double
+
+ const quotePattern = fixToDouble ? /"/g : /'/g
+ const quoteEscaped = fixToDouble ? '"' : '''
+ const fixQuoteChar = fixToDouble ? '"' : "'"
+
+ const replacement = fixQuoteChar + contentText.replace(quotePattern, quoteEscaped) + fixQuoteChar
return fixer.replaceText(node.value, replacement)
}
})
diff --git a/tests/lib/rules/html-quotes.js b/tests/lib/rules/html-quotes.js
index f54cc1d50..95338825a 100644
--- a/tests/lib/rules/html-quotes.js
+++ b/tests/lib/rules/html-quotes.js
@@ -55,6 +55,17 @@ tester.run('html-quotes', rule, {
code: "",
options: ['single']
},
+ // avoidEscape
+ {
+ filename: 'test.vue',
+ code: "",
+ options: ['double', { avoidEscape: true }]
+ },
+ {
+ filename: 'test.vue',
+ code: "",
+ options: ['single', { avoidEscape: true }]
+ },
// Invalid EOF
{
@@ -166,6 +177,49 @@ tester.run('html-quotes', rule, {
output: "",
options: ['single'],
errors: ['Expected to be enclosed by single quotes.']
+ },
+ // avoidEscape
+ {
+ filename: 'test.vue',
+ code: "",
+ output: '',
+ options: ['double', { avoidEscape: true }],
+ errors: ['Expected to be enclosed by double quotes.']
+ },
+ {
+ filename: 'test.vue',
+ code: '',
+ output: "",
+ options: ['single', { avoidEscape: true }],
+ errors: ['Expected to be enclosed by single quotes.']
+ },
+ {
+ filename: 'test.vue',
+ code: '',
+ output: '',
+ options: ['double', { avoidEscape: true }],
+ errors: ['Expected to be enclosed by double quotes.']
+ },
+ {
+ filename: 'test.vue',
+ code: '',
+ output: "",
+ options: ['single', { avoidEscape: true }],
+ errors: ['Expected to be enclosed by single quotes.']
+ },
+ {
+ filename: 'test.vue',
+ code: '',
+ output: '',
+ options: ['double', { avoidEscape: true }],
+ errors: ['Expected to be enclosed by double quotes.']
+ },
+ {
+ filename: 'test.vue',
+ code: '',
+ output: '',
+ options: ['single', { avoidEscape: true }],
+ errors: ['Expected to be enclosed by single quotes.']
}
]
})