eslint-plugin-mpx 0.0.21 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/README.md +3 -0
  2. package/lib/.DS_Store +0 -0
  3. package/lib/configs/base.js +10 -5
  4. package/lib/configs/mpx-essential.js +0 -30
  5. package/lib/index.js +1 -150
  6. package/lib/rules/comment-directive.js +2 -2
  7. package/lib/rules/component-tags-order.js +2 -2
  8. package/lib/rules/eqeqeq.js +4 -2
  9. package/lib/rules/html-end-tags.js +1 -1
  10. package/lib/rules/no-arrow-functions-in-watch.js +2 -2
  11. package/lib/rules/no-async-in-computed-properties.js +5 -5
  12. package/lib/rules/no-dupe-keys.js +3 -3
  13. package/lib/rules/no-dupe-wx-elif.js +8 -3
  14. package/lib/rules/no-duplicate-attributes.js +6 -16
  15. package/lib/rules/no-parsing-error.js +2 -2
  16. package/lib/rules/no-reserved-keys.js +3 -3
  17. package/lib/rules/no-side-effects-in-computed-properties.js +8 -9
  18. package/lib/rules/return-in-computed-property.js +3 -3
  19. package/lib/rules/syntaxes/dynamic-directive-arguments.js +2 -1
  20. package/lib/rules/syntaxes/scope-attribute.js +2 -1
  21. package/lib/rules/syntaxes/slot-attribute.js +2 -1
  22. package/lib/rules/syntaxes/v-bind-prop-modifier-shorthand.js +2 -1
  23. package/lib/rules/valid-wx-elif.js +1 -1
  24. package/lib/rules/valid-wx-else.js +1 -1
  25. package/lib/rules/valid-wx-for.js +2 -2
  26. package/lib/rules/valid-wx-if.js +1 -1
  27. package/lib/rules/valid-wx-model.js +2 -2
  28. package/lib/utils/index.js +504 -490
  29. package/lib/utils/keycode-to-key.js +60 -60
  30. package/lib/utils/{vue-reserved.json → mpx-reserved.json} +2 -2
  31. package/package.json +18 -15
  32. package/lib/configs/essential.js +0 -51
  33. package/lib/configs/no-layout-rules.js +0 -47
  34. package/lib/configs/recommended.js +0 -17
  35. package/lib/configs/strongly-recommended.js +0 -32
  36. package/lib/configs/vue3-essential.js +0 -71
  37. package/lib/configs/vue3-recommended.js +0 -17
  38. package/lib/configs/vue3-strongly-recommended.js +0 -33
  39. package/lib/rules/array-bracket-spacing.js +0 -12
  40. package/lib/rules/arrow-spacing.js +0 -9
  41. package/lib/rules/attribute-hyphenation.js +0 -121
  42. package/lib/rules/attributes-order.js +0 -281
  43. package/lib/rules/block-spacing.js +0 -11
  44. package/lib/rules/brace-style.js +0 -11
  45. package/lib/rules/camelcase.js +0 -9
  46. package/lib/rules/comma-dangle.js +0 -9
  47. package/lib/rules/comma-spacing.js +0 -12
  48. package/lib/rules/comma-style.js +0 -20
  49. package/lib/rules/component-definition-name-casing.js +0 -108
  50. package/lib/rules/component-name-in-template-casing.js +0 -164
  51. package/lib/rules/custom-event-name-casing.js +0 -214
  52. package/lib/rules/dot-location.js +0 -9
  53. package/lib/rules/dot-notation.js +0 -9
  54. package/lib/rules/func-call-spacing.js +0 -11
  55. package/lib/rules/html-closing-bracket-newline.js +0 -115
  56. package/lib/rules/html-closing-bracket-spacing.js +0 -137
  57. package/lib/rules/html-comment-content-newline.js +0 -215
  58. package/lib/rules/html-comment-content-spacing.js +0 -179
  59. package/lib/rules/html-comment-indent.js +0 -258
  60. package/lib/rules/html-indent.js +0 -81
  61. package/lib/rules/html-quotes.js +0 -107
  62. package/lib/rules/html-self-closing.js +0 -222
  63. package/lib/rules/jsx-uses-vars.js +0 -73
  64. package/lib/rules/key-spacing.js +0 -11
  65. package/lib/rules/keyword-spacing.js +0 -11
  66. package/lib/rules/match-component-file-name.js +0 -151
  67. package/lib/rules/max-attributes-per-line.js +0 -194
  68. package/lib/rules/max-len.js +0 -561
  69. package/lib/rules/multiline-html-element-content-newline.js +0 -246
  70. package/lib/rules/mustache-interpolation-spacing.js +0 -107
  71. package/lib/rules/name-property-casing.js +0 -71
  72. package/lib/rules/no-bare-strings-in-template.js +0 -275
  73. package/lib/rules/no-boolean-default.js +0 -114
  74. package/lib/rules/no-confusing-v-for-v-if.js +0 -69
  75. package/lib/rules/no-custom-modifiers-on-v-model.js +0 -59
  76. package/lib/rules/no-deprecated-data-object-declaration.js +0 -95
  77. package/lib/rules/no-deprecated-destroyed-lifecycle.js +0 -101
  78. package/lib/rules/no-deprecated-dollar-listeners-api.js +0 -72
  79. package/lib/rules/no-deprecated-dollar-scopedslots-api.js +0 -79
  80. package/lib/rules/no-deprecated-events-api.js +0 -69
  81. package/lib/rules/no-deprecated-filter.js +0 -44
  82. package/lib/rules/no-deprecated-functional-template.js +0 -56
  83. package/lib/rules/no-deprecated-html-element-is.js +0 -54
  84. package/lib/rules/no-deprecated-inline-template.js +0 -47
  85. package/lib/rules/no-deprecated-scope-attribute.js +0 -31
  86. package/lib/rules/no-deprecated-slot-attribute.js +0 -29
  87. package/lib/rules/no-deprecated-slot-scope-attribute.js +0 -34
  88. package/lib/rules/no-deprecated-v-bind-sync.js +0 -62
  89. package/lib/rules/no-deprecated-v-on-native-modifier.js +0 -50
  90. package/lib/rules/no-deprecated-v-on-number-modifiers.js +0 -61
  91. package/lib/rules/no-deprecated-vue-config-keycodes.js +0 -53
  92. package/lib/rules/no-duplicate-attr-inheritance.js +0 -67
  93. package/lib/rules/no-empty-component-block.js +0 -109
  94. package/lib/rules/no-empty-pattern.js +0 -9
  95. package/lib/rules/no-extra-parens.js +0 -182
  96. package/lib/rules/no-irregular-whitespace.js +0 -251
  97. package/lib/rules/no-lifecycle-after-await.js +0 -133
  98. package/lib/rules/no-lone-template.js +0 -129
  99. package/lib/rules/no-multi-spaces.js +0 -107
  100. package/lib/rules/no-multiple-objects-in-class.js +0 -59
  101. package/lib/rules/no-multiple-slot-args.js +0 -118
  102. package/lib/rules/no-multiple-template-root.js +0 -101
  103. package/lib/rules/no-mutating-props.js +0 -323
  104. package/lib/rules/no-potential-component-option-typo.js +0 -125
  105. package/lib/rules/no-ref-as-operand.js +0 -189
  106. package/lib/rules/no-reserved-component-names.js +0 -187
  107. package/lib/rules/no-restricted-component-options.js +0 -215
  108. package/lib/rules/no-restricted-static-attribute.js +0 -164
  109. package/lib/rules/no-restricted-syntax.js +0 -9
  110. package/lib/rules/no-restricted-v-bind.js +0 -184
  111. package/lib/rules/no-setup-props-destructure.js +0 -149
  112. package/lib/rules/no-spaces-around-equal-signs-in-attribute.js +0 -57
  113. package/lib/rules/no-sparse-arrays.js +0 -9
  114. package/lib/rules/no-static-inline-styles.js +0 -141
  115. package/lib/rules/no-template-key.js +0 -48
  116. package/lib/rules/no-template-shadow.js +0 -101
  117. package/lib/rules/no-template-target-blank.js +0 -138
  118. package/lib/rules/no-textarea-mustache.js +0 -46
  119. package/lib/rules/no-unregistered-components.js +0 -187
  120. package/lib/rules/no-unsupported-features.js +0 -157
  121. package/lib/rules/no-unused-components.js +0 -143
  122. package/lib/rules/no-unused-properties.js +0 -742
  123. package/lib/rules/no-unused-vars.js +0 -147
  124. package/lib/rules/no-use-v-if-with-v-for.js +0 -119
  125. package/lib/rules/no-useless-concat.js +0 -9
  126. package/lib/rules/no-useless-mustaches.js +0 -154
  127. package/lib/rules/no-useless-v-bind.js +0 -150
  128. package/lib/rules/no-v-html.js +0 -36
  129. package/lib/rules/no-v-model-argument.js +0 -49
  130. package/lib/rules/no-watch-after-await.js +0 -142
  131. package/lib/rules/object-curly-newline.js +0 -12
  132. package/lib/rules/object-curly-spacing.js +0 -12
  133. package/lib/rules/object-property-newline.js +0 -12
  134. package/lib/rules/one-component-per-file.js +0 -50
  135. package/lib/rules/operator-linebreak.js +0 -9
  136. package/lib/rules/order-in-components.js +0 -341
  137. package/lib/rules/padding-line-between-blocks.js +0 -220
  138. package/lib/rules/prefer-template.js +0 -9
  139. package/lib/rules/prop-name-casing.js +0 -66
  140. package/lib/rules/require-component-is.js +0 -45
  141. package/lib/rules/require-default-prop.js +0 -190
  142. package/lib/rules/require-direct-export.js +0 -128
  143. package/lib/rules/require-explicit-emits.js +0 -511
  144. package/lib/rules/require-name-property.js +0 -43
  145. package/lib/rules/require-prop-type-constructor.js +0 -99
  146. package/lib/rules/require-prop-types.js +0 -103
  147. package/lib/rules/require-render-return.js +0 -50
  148. package/lib/rules/require-slots-as-functions.js +0 -120
  149. package/lib/rules/require-toggle-inside-transition.js +0 -89
  150. package/lib/rules/require-v-for-key.js +0 -62
  151. package/lib/rules/require-valid-default-prop.js +0 -338
  152. package/lib/rules/return-in-emits-validator.js +0 -141
  153. package/lib/rules/script-indent.js +0 -56
  154. package/lib/rules/singleline-html-element-content-newline.js +0 -215
  155. package/lib/rules/sort-keys.js +0 -282
  156. package/lib/rules/space-in-parens.js +0 -12
  157. package/lib/rules/space-infix-ops.js +0 -11
  158. package/lib/rules/space-unary-ops.js +0 -11
  159. package/lib/rules/static-class-names-order.js +0 -61
  160. package/lib/rules/template-curly-spacing.js +0 -12
  161. package/lib/rules/this-in-template.js +0 -128
  162. package/lib/rules/use-v-on-exact.js +0 -228
  163. package/lib/rules/v-bind-style.js +0 -76
  164. package/lib/rules/v-for-delimiter-style.js +0 -69
  165. package/lib/rules/v-on-function-call.js +0 -172
  166. package/lib/rules/v-on-style.js +0 -58
  167. package/lib/rules/v-slot-style.js +0 -155
  168. package/lib/rules/valid-template-root.js +0 -69
  169. package/lib/rules/valid-v-bind-sync.js +0 -179
  170. package/lib/rules/valid-v-bind.js +0 -62
  171. package/lib/rules/valid-v-cloak.js +0 -58
  172. package/lib/rules/valid-v-html.js +0 -58
  173. package/lib/rules/valid-v-is.js +0 -95
  174. package/lib/rules/valid-v-on.js +0 -153
  175. package/lib/rules/valid-v-once.js +0 -58
  176. package/lib/rules/valid-v-pre.js +0 -58
  177. package/lib/rules/valid-v-show.js +0 -58
  178. package/lib/rules/valid-v-slot.js +0 -290
  179. package/lib/rules/valid-v-text.js +0 -58
  180. package/lib/utils/indent-common.js +0 -2085
@@ -1,214 +0,0 @@
1
- /**
2
- * @author Yosuke Ota
3
- * See LICENSE file in root directory for full license.
4
- */
5
- 'use strict'
6
-
7
- // ------------------------------------------------------------------------------
8
- // Requirements
9
- // ------------------------------------------------------------------------------
10
-
11
- const { findVariable } = require('eslint-utils')
12
- const utils = require('../utils')
13
- const { isKebabCase } = require('../utils/casing')
14
-
15
- // ------------------------------------------------------------------------------
16
- // Helpers
17
- // ------------------------------------------------------------------------------
18
-
19
- /**
20
- * Check whether the given event name is valid.
21
- * @param {string} name The name to check.
22
- * @returns {boolean} `true` if the given event name is valid.
23
- */
24
- function isValidEventName(name) {
25
- return isKebabCase(name) || name.startsWith('update:')
26
- }
27
-
28
- /**
29
- * Get the name param node from the given CallExpression
30
- * @param {CallExpression} node CallExpression
31
- * @returns { Literal & { value: string } | null }
32
- */
33
- function getNameParamNode(node) {
34
- const nameLiteralNode = node.arguments[0]
35
- if (
36
- !nameLiteralNode ||
37
- nameLiteralNode.type !== 'Literal' ||
38
- typeof nameLiteralNode.value !== 'string'
39
- ) {
40
- // cannot check
41
- return null
42
- }
43
-
44
- return /** @type {Literal & { value: string }} */ (nameLiteralNode)
45
- }
46
- /**
47
- * Get the callee member node from the given CallExpression
48
- * @param {CallExpression} node CallExpression
49
- */
50
- function getCalleeMemberNode(node) {
51
- const callee = utils.skipChainExpression(node.callee)
52
-
53
- if (callee.type === 'MemberExpression') {
54
- const name = utils.getStaticPropertyName(callee)
55
- if (name) {
56
- return { name, member: callee }
57
- }
58
- }
59
- return null
60
- }
61
-
62
- // ------------------------------------------------------------------------------
63
- // Rule Definition
64
- // ------------------------------------------------------------------------------
65
-
66
- module.exports = {
67
- meta: {
68
- type: 'suggestion',
69
- docs: {
70
- description: 'enforce custom event names always use "kebab-case"',
71
- categories: ['vue3-essential', 'essential'],
72
- url: 'https://eslint.vuejs.org/rules/custom-event-name-casing.html'
73
- },
74
- fixable: null,
75
- schema: [],
76
- messages: {
77
- unexpected: "Custom event name '{{name}}' must be kebab-case."
78
- }
79
- },
80
- /** @param {RuleContext} context */
81
- create(context) {
82
- const setupContexts = new Map()
83
-
84
- /**
85
- * @param { Literal & { value: string } } nameLiteralNode
86
- */
87
- function verify(nameLiteralNode) {
88
- const name = nameLiteralNode.value
89
- if (isValidEventName(name)) {
90
- return
91
- }
92
- context.report({
93
- node: nameLiteralNode,
94
- messageId: 'unexpected',
95
- data: {
96
- name
97
- }
98
- })
99
- }
100
-
101
- return utils.defineTemplateBodyVisitor(
102
- context,
103
- {
104
- CallExpression(node) {
105
- const callee = node.callee
106
- const nameLiteralNode = getNameParamNode(node)
107
- if (!nameLiteralNode) {
108
- // cannot check
109
- return
110
- }
111
- if (callee.type === 'Identifier' && callee.name === '$emit') {
112
- verify(nameLiteralNode)
113
- }
114
- }
115
- },
116
- utils.compositingVisitors(
117
- utils.defineVueVisitor(context, {
118
- onSetupFunctionEnter(node, { node: vueNode }) {
119
- const contextParam = utils.skipDefaultParamValue(node.params[1])
120
- if (!contextParam) {
121
- // no arguments
122
- return
123
- }
124
- if (
125
- contextParam.type === 'RestElement' ||
126
- contextParam.type === 'ArrayPattern'
127
- ) {
128
- // cannot check
129
- return
130
- }
131
- const contextReferenceIds = new Set()
132
- const emitReferenceIds = new Set()
133
- if (contextParam.type === 'ObjectPattern') {
134
- const emitProperty = utils.findAssignmentProperty(
135
- contextParam,
136
- 'emit'
137
- )
138
- if (!emitProperty || emitProperty.value.type !== 'Identifier') {
139
- return
140
- }
141
- const emitParam = emitProperty.value
142
- // `setup(props, {emit})`
143
- const variable = findVariable(context.getScope(), emitParam)
144
- if (!variable) {
145
- return
146
- }
147
- for (const reference of variable.references) {
148
- emitReferenceIds.add(reference.identifier)
149
- }
150
- } else {
151
- // `setup(props, context)`
152
- const variable = findVariable(context.getScope(), contextParam)
153
- if (!variable) {
154
- return
155
- }
156
- for (const reference of variable.references) {
157
- contextReferenceIds.add(reference.identifier)
158
- }
159
- }
160
- setupContexts.set(vueNode, {
161
- contextReferenceIds,
162
- emitReferenceIds
163
- })
164
- },
165
- CallExpression(node, { node: vueNode }) {
166
- const nameLiteralNode = getNameParamNode(node)
167
- if (!nameLiteralNode) {
168
- // cannot check
169
- return
170
- }
171
-
172
- // verify setup context
173
- const setupContext = setupContexts.get(vueNode)
174
- if (setupContext) {
175
- const { contextReferenceIds, emitReferenceIds } = setupContext
176
- if (emitReferenceIds.has(node.callee)) {
177
- // verify setup(props,{emit}) {emit()}
178
- verify(nameLiteralNode)
179
- } else {
180
- const emit = getCalleeMemberNode(node)
181
- if (
182
- emit &&
183
- emit.name === 'emit' &&
184
- contextReferenceIds.has(emit.member.object)
185
- ) {
186
- // verify setup(props,context) {context.emit()}
187
- verify(nameLiteralNode)
188
- }
189
- }
190
- }
191
- },
192
- onVueObjectExit(node) {
193
- setupContexts.delete(node)
194
- }
195
- }),
196
- {
197
- CallExpression(node) {
198
- const nameLiteralNode = getNameParamNode(node)
199
- if (!nameLiteralNode) {
200
- // cannot check
201
- return
202
- }
203
- const emit = getCalleeMemberNode(node)
204
- // verify $emit
205
- if (emit && emit.name === '$emit') {
206
- // verify this.$emit()
207
- verify(nameLiteralNode)
208
- }
209
- }
210
- }
211
- )
212
- )
213
- }
214
- }
@@ -1,9 +0,0 @@
1
- /**
2
- * @author Yosuke Ota
3
- */
4
- 'use strict'
5
-
6
- const { wrapCoreRule } = require('../utils')
7
-
8
- // eslint-disable-next-line no-invalid-meta, no-invalid-meta-docs-categories
9
- module.exports = wrapCoreRule(require('eslint/lib/rules/dot-location'))
@@ -1,9 +0,0 @@
1
- /**
2
- * @author Yosuke Ota
3
- */
4
- 'use strict'
5
-
6
- const { wrapCoreRule } = require('../utils')
7
-
8
- // eslint-disable-next-line no-invalid-meta, no-invalid-meta-docs-categories
9
- module.exports = wrapCoreRule(require('eslint/lib/rules/dot-notation'))
@@ -1,11 +0,0 @@
1
- /**
2
- * @author Yosuke Ota
3
- */
4
- 'use strict'
5
-
6
- const { wrapCoreRule } = require('../utils')
7
-
8
- // eslint-disable-next-line no-invalid-meta, no-invalid-meta-docs-categories
9
- module.exports = wrapCoreRule(require('eslint/lib/rules/func-call-spacing'), {
10
- skipDynamicArguments: true
11
- })
@@ -1,115 +0,0 @@
1
- /**
2
- * @author Toru Nagashima
3
- * @copyright 2016 Toru Nagashima. All rights reserved.
4
- * See LICENSE file in root directory for full license.
5
- */
6
- 'use strict'
7
-
8
- // ------------------------------------------------------------------------------
9
- // Requirements
10
- // ------------------------------------------------------------------------------
11
-
12
- const utils = require('../utils')
13
-
14
- // ------------------------------------------------------------------------------
15
- // Helpers
16
- // ------------------------------------------------------------------------------
17
-
18
- /**
19
- * @param {number} lineBreaks
20
- */
21
- function getPhrase(lineBreaks) {
22
- switch (lineBreaks) {
23
- case 0:
24
- return 'no line breaks'
25
- case 1:
26
- return '1 line break'
27
- default:
28
- return `${lineBreaks} line breaks`
29
- }
30
- }
31
-
32
- // ------------------------------------------------------------------------------
33
- // Rule Definition
34
- // ------------------------------------------------------------------------------
35
-
36
- module.exports = {
37
- meta: {
38
- type: 'layout',
39
- docs: {
40
- description:
41
- "require or disallow a line break before tag's closing brackets",
42
- categories: ['vue3-strongly-recommended', 'strongly-recommended'],
43
- url: 'https://eslint.vuejs.org/rules/html-closing-bracket-newline.html'
44
- },
45
- fixable: 'whitespace',
46
- schema: [
47
- {
48
- type: 'object',
49
- properties: {
50
- singleline: { enum: ['always', 'never'] },
51
- multiline: { enum: ['always', 'never'] }
52
- },
53
- additionalProperties: false
54
- }
55
- ]
56
- },
57
- /** @param {RuleContext} context */
58
- create(context) {
59
- const options = Object.assign(
60
- {},
61
- {
62
- singleline: 'never',
63
- multiline: 'always'
64
- },
65
- context.options[0] || {}
66
- )
67
- const template =
68
- context.parserServices.getTemplateBodyTokenStore &&
69
- context.parserServices.getTemplateBodyTokenStore()
70
-
71
- return utils.defineTemplateBodyVisitor(context, {
72
- /** @param {VStartTag | VEndTag} node */
73
- 'VStartTag, VEndTag'(node) {
74
- const closingBracketToken = template.getLastToken(node)
75
- if (
76
- closingBracketToken.type !== 'HTMLSelfClosingTagClose' &&
77
- closingBracketToken.type !== 'HTMLTagClose'
78
- ) {
79
- return
80
- }
81
-
82
- const prevToken = template.getTokenBefore(closingBracketToken)
83
- const type =
84
- node.loc.start.line === prevToken.loc.end.line
85
- ? 'singleline'
86
- : 'multiline'
87
- const expectedLineBreaks = options[type] === 'always' ? 1 : 0
88
- const actualLineBreaks =
89
- closingBracketToken.loc.start.line - prevToken.loc.end.line
90
-
91
- if (actualLineBreaks !== expectedLineBreaks) {
92
- context.report({
93
- node,
94
- loc: {
95
- start: prevToken.loc.end,
96
- end: closingBracketToken.loc.start
97
- },
98
- message:
99
- 'Expected {{expected}} before closing bracket, but {{actual}} found.',
100
- data: {
101
- expected: getPhrase(expectedLineBreaks),
102
- actual: getPhrase(actualLineBreaks)
103
- },
104
- fix(fixer) {
105
- /** @type {Range} */
106
- const range = [prevToken.range[1], closingBracketToken.range[0]]
107
- const text = '\n'.repeat(expectedLineBreaks)
108
- return fixer.replaceTextRange(range, text)
109
- }
110
- })
111
- }
112
- }
113
- })
114
- }
115
- }
@@ -1,137 +0,0 @@
1
- /**
2
- * @author Toru Nagashima <https://github.com/mysticatea>
3
- */
4
-
5
- 'use strict'
6
-
7
- // -----------------------------------------------------------------------------
8
- // Requirements
9
- // -----------------------------------------------------------------------------
10
-
11
- const utils = require('../utils')
12
-
13
- // -----------------------------------------------------------------------------
14
- // Helpers
15
- // -----------------------------------------------------------------------------
16
-
17
- /**
18
- * @typedef { {startTag?:"always"|"never",endTag?:"always"|"never",selfClosingTag?:"always"|"never"} } Options
19
- */
20
-
21
- /**
22
- * Normalize options.
23
- * @param {Options} options The options user configured.
24
- * @param {ParserServices.TokenStore} tokens The token store of template body.
25
- * @returns {Options & { detectType: (node: VStartTag | VEndTag) => 'never' | 'always' | null }} The normalized options.
26
- */
27
- function parseOptions(options, tokens) {
28
- const opts = Object.assign(
29
- {
30
- startTag: 'never',
31
- endTag: 'never',
32
- selfClosingTag: 'always'
33
- },
34
- options
35
- )
36
- return Object.assign(opts, {
37
- /**
38
- * @param {VStartTag | VEndTag} node
39
- * @returns {'never' | 'always' | null}
40
- */
41
- detectType(node) {
42
- const openType = tokens.getFirstToken(node).type
43
- const closeType = tokens.getLastToken(node).type
44
-
45
- if (openType === 'HTMLEndTagOpen' && closeType === 'HTMLTagClose') {
46
- return opts.endTag
47
- }
48
- if (openType === 'HTMLTagOpen' && closeType === 'HTMLTagClose') {
49
- return opts.startTag
50
- }
51
- if (
52
- openType === 'HTMLTagOpen' &&
53
- closeType === 'HTMLSelfClosingTagClose'
54
- ) {
55
- return opts.selfClosingTag
56
- }
57
- return null
58
- }
59
- })
60
- }
61
-
62
- // -----------------------------------------------------------------------------
63
- // Rule Definition
64
- // -----------------------------------------------------------------------------
65
-
66
- module.exports = {
67
- meta: {
68
- type: 'layout',
69
- docs: {
70
- description: "require or disallow a space before tag's closing brackets",
71
- categories: ['vue3-strongly-recommended', 'strongly-recommended'],
72
- url: 'https://eslint.vuejs.org/rules/html-closing-bracket-spacing.html'
73
- },
74
- schema: [
75
- {
76
- type: 'object',
77
- properties: {
78
- startTag: { enum: ['always', 'never'] },
79
- endTag: { enum: ['always', 'never'] },
80
- selfClosingTag: { enum: ['always', 'never'] }
81
- },
82
- additionalProperties: false
83
- }
84
- ],
85
- fixable: 'whitespace'
86
- },
87
- /** @param {RuleContext} context */
88
- create(context) {
89
- const sourceCode = context.getSourceCode()
90
- const tokens =
91
- context.parserServices.getTemplateBodyTokenStore &&
92
- context.parserServices.getTemplateBodyTokenStore()
93
- const options = parseOptions(context.options[0], tokens)
94
-
95
- return utils.defineTemplateBodyVisitor(context, {
96
- /** @param {VStartTag | VEndTag} node */
97
- 'VStartTag, VEndTag'(node) {
98
- const type = options.detectType(node)
99
- const lastToken = tokens.getLastToken(node)
100
- const prevToken = tokens.getLastToken(node, 1)
101
-
102
- // Skip if EOF exists in the tag or linebreak exists before `>`.
103
- if (
104
- type == null ||
105
- prevToken == null ||
106
- prevToken.loc.end.line !== lastToken.loc.start.line
107
- ) {
108
- return
109
- }
110
-
111
- // Check and report.
112
- const hasSpace = prevToken.range[1] !== lastToken.range[0]
113
- if (type === 'always' && !hasSpace) {
114
- context.report({
115
- node,
116
- loc: lastToken.loc,
117
- message: "Expected a space before '{{bracket}}', but not found.",
118
- data: { bracket: sourceCode.getText(lastToken) },
119
- fix: (fixer) => fixer.insertTextBefore(lastToken, ' ')
120
- })
121
- } else if (type === 'never' && hasSpace) {
122
- context.report({
123
- node,
124
- loc: {
125
- start: prevToken.loc.end,
126
- end: lastToken.loc.end
127
- },
128
- message: "Expected no space before '{{bracket}}', but found.",
129
- data: { bracket: sourceCode.getText(lastToken) },
130
- fix: (fixer) =>
131
- fixer.removeRange([prevToken.range[1], lastToken.range[0]])
132
- })
133
- }
134
- }
135
- })
136
- }
137
- }