eslint-plugin-crisp 1.7.13 → 1.7.15
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.
- package/README.md +1 -0
- package/index.js +2 -0
- package/package.json +1 -1
- package/recommended-vue.js +1 -0
- package/rules/vue-event-listener-section.js +290 -0
- package/tests/rules/vue-event-listener-section.test.js +228 -0
package/README.md
CHANGED
|
@@ -228,6 +228,7 @@ Each item has emojis denoting:
|
|
|
228
228
|
| [crisp/vue-define-component](https://github.com/crisp-oss/eslint-plugin-crisp/blob/master/rules/vue-define-component.js) | Enforces mixins and components to use the `defineComponent` wrapper | | 🟢 |
|
|
229
229
|
| [crisp/vue-emits-order](https://github.com/crisp-oss/eslint-plugin-crisp/blob/master/rules/vue-emits-order.js) | Ensures emits properties are alphabetically ordered | | 🟢 |
|
|
230
230
|
| [crisp/vue-event-listener-jsdoc](https://github.com/crisp-oss/eslint-plugin-crisp/blob/master/rules/vue-event-listener-jsdoc.js) | Requires event listener method JSDoc descriptions to start with `Triggers on` | | 🟢 |
|
|
231
|
+
| [crisp/vue-event-listener-section](https://github.com/crisp-oss/eslint-plugin-crisp/blob/master/rules/vue-event-listener-section.js) | Requires methods named `on` followed by an uppercase letter to be in the event listeners section | | 🟢 |
|
|
231
232
|
| [crisp/vue-header-check](https://github.com/crisp-oss/eslint-plugin-crisp/blob/master/rules/vue-header-check.js) | Ensures `script`, `template` and `style` tags start with corresponding comment block | | 🟢 |
|
|
232
233
|
| [crisp/vue-html-indent](https://github.com/crisp-oss/eslint-plugin-crisp/blob/master/rules/vue-html-indent.js) | Enforces consistent indentation in `template` (supports for Pug) | | 🟢 |
|
|
233
234
|
| [crisp/vue-html-quotes](https://github.com/crisp-oss/eslint-plugin-crisp/blob/master/rules/vue-html-quotes.js) | Enforces HTML attributes to be enclosed with double quotes | | 🟢 |
|
package/index.js
CHANGED
|
@@ -51,6 +51,7 @@ import ruleVueDataComment from "./rules/vue-data-comment.js";
|
|
|
51
51
|
import ruleVueDefineComponent from "./rules/vue-define-component.js";
|
|
52
52
|
import ruleVueEmitsOrder from "./rules/vue-emits-order.js";
|
|
53
53
|
import ruleVueEventListenerJsdoc from "./rules/vue-event-listener-jsdoc.js";
|
|
54
|
+
import ruleVueEventListenerSection from "./rules/vue-event-listener-section.js";
|
|
54
55
|
import ruleVueHeaderCheck from "./rules/vue-header-check.js";
|
|
55
56
|
import ruleVueHtmlIndent from "./rules/vue-html-indent.js";
|
|
56
57
|
import ruleVueHtmlQuotes from "./rules/vue-html-quotes.js";
|
|
@@ -131,6 +132,7 @@ const plugin = {
|
|
|
131
132
|
"vue-define-component": ruleVueDefineComponent,
|
|
132
133
|
"vue-emits-order": ruleVueEmitsOrder,
|
|
133
134
|
"vue-event-listener-jsdoc": ruleVueEventListenerJsdoc,
|
|
135
|
+
"vue-event-listener-section": ruleVueEventListenerSection,
|
|
134
136
|
"vue-header-check": ruleVueHeaderCheck,
|
|
135
137
|
"vue-html-indent": ruleVueHtmlIndent,
|
|
136
138
|
"vue-html-quotes": ruleVueHtmlQuotes,
|
package/package.json
CHANGED
package/recommended-vue.js
CHANGED
|
@@ -386,6 +386,7 @@ export default function configRecommendedVue(pluginCrisp) {
|
|
|
386
386
|
"crisp/vue-define-component": "error",
|
|
387
387
|
"crisp/vue-emits-order": "error",
|
|
388
388
|
"crisp/vue-event-listener-jsdoc": "error",
|
|
389
|
+
"crisp/vue-event-listener-section": "error",
|
|
389
390
|
"crisp/vue-header-check": "error",
|
|
390
391
|
"crisp/vue-html-indent": "error",
|
|
391
392
|
"crisp/vue-html-quotes": "error",
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
const EVENT_LISTENERS_SEPARATOR = "--> EVENT LISTENERS <--";
|
|
2
|
+
const EVENT_LISTENER_NAME_PATTERN = /^on[A-Z]/;
|
|
3
|
+
const SEPARATOR_LIKE_PATTERN = /^--> .+ <--$/;
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
meta: {
|
|
7
|
+
type: "suggestion",
|
|
8
|
+
docs: {
|
|
9
|
+
description:
|
|
10
|
+
"require on-prefixed Vue methods to be in the event listeners section",
|
|
11
|
+
category: "Stylistic Issues",
|
|
12
|
+
recommended: false
|
|
13
|
+
},
|
|
14
|
+
fixable: "code",
|
|
15
|
+
schema: [],
|
|
16
|
+
messages: {
|
|
17
|
+
wrongSection:
|
|
18
|
+
"Method '{{name}}' must be declared in the EVENT LISTENERS section."
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
create(context) {
|
|
23
|
+
const sourceCode = context.sourceCode;
|
|
24
|
+
|
|
25
|
+
function getLineStart(node) {
|
|
26
|
+
return sourceCode.getIndexFromLoc({
|
|
27
|
+
line: node.loc.start.line,
|
|
28
|
+
column: 0
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function getPropertyName(property) {
|
|
33
|
+
if (property.type !== "Property" || property.computed) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (property.key.type === "Identifier") {
|
|
38
|
+
return property.key.name;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (
|
|
42
|
+
property.key.type === "Literal" &&
|
|
43
|
+
typeof property.key.value === "string"
|
|
44
|
+
) {
|
|
45
|
+
return property.key.value;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function getTopLevelComments(node, properties) {
|
|
52
|
+
return sourceCode.getCommentsInside(node.value).filter((comment) => {
|
|
53
|
+
return !properties.some((property) => {
|
|
54
|
+
return (
|
|
55
|
+
comment.range[0] >= property.range[0] &&
|
|
56
|
+
comment.range[1] <= property.range[1]
|
|
57
|
+
);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function getMethodBlock(node, property) {
|
|
63
|
+
const comments = sourceCode.getCommentsBefore(property);
|
|
64
|
+
const lastSeparatorIndex = comments.findLastIndex((comment) => {
|
|
65
|
+
return (
|
|
66
|
+
comment.type === "Line" &&
|
|
67
|
+
SEPARATOR_LIKE_PATTERN.test(comment.value.trim())
|
|
68
|
+
);
|
|
69
|
+
});
|
|
70
|
+
const ownedComments = comments.slice(lastSeparatorIndex + 1);
|
|
71
|
+
const firstNode = ownedComments[0] || property;
|
|
72
|
+
const start = getLineStart(firstNode);
|
|
73
|
+
const linePrefix = sourceCode.text.slice(start, firstNode.range[0]);
|
|
74
|
+
|
|
75
|
+
if (linePrefix.trim() !== "") {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const tokenAfter = sourceCode.getTokenAfter(property);
|
|
80
|
+
const comma = (
|
|
81
|
+
tokenAfter?.value === "," &&
|
|
82
|
+
tokenAfter.range[0] < node.value.range[1]
|
|
83
|
+
)
|
|
84
|
+
? tokenAfter
|
|
85
|
+
: null;
|
|
86
|
+
const propertyEnd = comma?.range[1] || property.range[1];
|
|
87
|
+
const remainingText = sourceCode.text.slice(
|
|
88
|
+
propertyEnd,
|
|
89
|
+
node.value.range[1] - 1
|
|
90
|
+
);
|
|
91
|
+
const nextContentMatch = remainingText.match(/\S/);
|
|
92
|
+
let removalEnd = propertyEnd;
|
|
93
|
+
|
|
94
|
+
if (nextContentMatch) {
|
|
95
|
+
const nextContent = propertyEnd + nextContentMatch.index;
|
|
96
|
+
const nextContentLocation = sourceCode.getLocFromIndex(nextContent);
|
|
97
|
+
|
|
98
|
+
if (nextContentLocation.line > property.loc.end.line) {
|
|
99
|
+
removalEnd = sourceCode.getIndexFromLoc({
|
|
100
|
+
line: nextContentLocation.line,
|
|
101
|
+
column: 0
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
start,
|
|
108
|
+
end: removalEnd,
|
|
109
|
+
text: sourceCode.text.slice(start, property.range[1]).trimEnd()
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function createMoveFix(node, properties, violations) {
|
|
114
|
+
const topLevelComments = getTopLevelComments(node, properties);
|
|
115
|
+
const eventSeparators = topLevelComments.filter((comment) => {
|
|
116
|
+
return (
|
|
117
|
+
comment.type === "Line" &&
|
|
118
|
+
comment.value.trim() === EVENT_LISTENERS_SEPARATOR
|
|
119
|
+
);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
if (eventSeparators.length > 1) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const eventSeparator = eventSeparators[0] || null;
|
|
127
|
+
const hasSectionAfterEvent = eventSeparator && topLevelComments.some(
|
|
128
|
+
(comment) => {
|
|
129
|
+
return (
|
|
130
|
+
comment.range[0] > eventSeparator.range[1] &&
|
|
131
|
+
comment.type === "Line" &&
|
|
132
|
+
SEPARATOR_LIKE_PATTERN.test(comment.value.trim())
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
if (hasSectionAfterEvent) {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const lastProperty = properties.at(-1);
|
|
142
|
+
const trailingComments = topLevelComments.filter((comment) => {
|
|
143
|
+
return comment.range[0] > lastProperty.range[1];
|
|
144
|
+
});
|
|
145
|
+
const hasUnsafeTrailingComment = trailingComments.some((comment) => {
|
|
146
|
+
return comment !== eventSeparator;
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
if (hasUnsafeTrailingComment) {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const methodBlocks = violations.map(({ property }) => {
|
|
154
|
+
return getMethodBlock(node, property);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
if (methodBlocks.some((block) => block === null)) {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const movedProperties = new Set(
|
|
162
|
+
violations.map(({ property }) => property)
|
|
163
|
+
);
|
|
164
|
+
const remainingProperties = properties.filter((property) => {
|
|
165
|
+
return !movedProperties.has(property);
|
|
166
|
+
});
|
|
167
|
+
const interiorStart = node.value.range[0] + 1;
|
|
168
|
+
const interiorEnd = node.value.range[1] - 1;
|
|
169
|
+
const interiorText = sourceCode.text.slice(interiorStart, interiorEnd);
|
|
170
|
+
const suffixMatch = interiorText.match(/\s*$/);
|
|
171
|
+
const suffix = suffixMatch?.[0] || "";
|
|
172
|
+
const edits = methodBlocks.map((block) => {
|
|
173
|
+
return {
|
|
174
|
+
start: block.start - interiorStart,
|
|
175
|
+
end: block.end - interiorStart,
|
|
176
|
+
text: ""
|
|
177
|
+
};
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
if (remainingProperties.length > 0) {
|
|
181
|
+
const lastRemainingProperty = remainingProperties.at(-1);
|
|
182
|
+
const tokenAfter = sourceCode.getTokenAfter(lastRemainingProperty);
|
|
183
|
+
const hasComma = (
|
|
184
|
+
tokenAfter?.value === "," &&
|
|
185
|
+
tokenAfter.range[0] < interiorEnd
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
if (!hasComma) {
|
|
189
|
+
const propertyEnd = lastRemainingProperty.range[1] - interiorStart;
|
|
190
|
+
|
|
191
|
+
edits.push({
|
|
192
|
+
start: propertyEnd,
|
|
193
|
+
end: propertyEnd,
|
|
194
|
+
text: ","
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const transformedText = [...edits]
|
|
200
|
+
.sort((first, second) => {
|
|
201
|
+
return second.start - first.start || second.end - first.end;
|
|
202
|
+
})
|
|
203
|
+
.reduce((text, edit) => {
|
|
204
|
+
return (
|
|
205
|
+
text.slice(0, edit.start) +
|
|
206
|
+
edit.text +
|
|
207
|
+
text.slice(edit.end)
|
|
208
|
+
);
|
|
209
|
+
}, interiorText)
|
|
210
|
+
.trimEnd();
|
|
211
|
+
const movedText = methodBlocks
|
|
212
|
+
.map((block) => block.text)
|
|
213
|
+
.join(",\n\n");
|
|
214
|
+
const methodIndent = movedText.match(/^[\t ]*/)?.[0] || "";
|
|
215
|
+
const sectionText = eventSeparator
|
|
216
|
+
? movedText
|
|
217
|
+
: (
|
|
218
|
+
`${methodIndent}// ${EVENT_LISTENERS_SEPARATOR}\n\n` +
|
|
219
|
+
movedText
|
|
220
|
+
);
|
|
221
|
+
const fixedInterior = transformedText === ""
|
|
222
|
+
? `\n${sectionText}${suffix}`
|
|
223
|
+
: `${transformedText}\n\n${sectionText}${suffix}`;
|
|
224
|
+
|
|
225
|
+
return (fixer) => {
|
|
226
|
+
return fixer.replaceTextRange(
|
|
227
|
+
[interiorStart, interiorEnd],
|
|
228
|
+
fixedInterior
|
|
229
|
+
);
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function checkMethods(node) {
|
|
234
|
+
const properties = node.value.properties;
|
|
235
|
+
|
|
236
|
+
if (!properties) {
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
let eventListenersStarted = false;
|
|
241
|
+
const violations = [];
|
|
242
|
+
|
|
243
|
+
properties.forEach((property) => {
|
|
244
|
+
const comments = sourceCode.getCommentsBefore(property);
|
|
245
|
+
|
|
246
|
+
if (!eventListenersStarted) {
|
|
247
|
+
eventListenersStarted = comments.some((comment) => {
|
|
248
|
+
return (
|
|
249
|
+
comment.type === "Line" &&
|
|
250
|
+
comment.value.trim() === EVENT_LISTENERS_SEPARATOR
|
|
251
|
+
);
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (eventListenersStarted) {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const name = getPropertyName(property);
|
|
260
|
+
|
|
261
|
+
if (name && EVENT_LISTENER_NAME_PATTERN.test(name)) {
|
|
262
|
+
violations.push({
|
|
263
|
+
property,
|
|
264
|
+
name
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
const moveFix = violations.length > 0
|
|
270
|
+
? createMoveFix(node, properties, violations)
|
|
271
|
+
: null;
|
|
272
|
+
|
|
273
|
+
violations.forEach(({ property, name }, index) => {
|
|
274
|
+
context.report({
|
|
275
|
+
node: property.key,
|
|
276
|
+
messageId: "wrongSection",
|
|
277
|
+
data: { name },
|
|
278
|
+
...(index === 0 && moveFix ? { fix: moveFix } : {})
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
return {
|
|
284
|
+
'ExportDefaultDeclaration > ObjectExpression > Property[key.name="methods"]':
|
|
285
|
+
checkMethods,
|
|
286
|
+
'ExportDefaultDeclaration > CallExpression[callee.name="defineComponent"] > ObjectExpression > Property[key.name="methods"]':
|
|
287
|
+
checkMethods
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
};
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import rule from "../../rules/vue-event-listener-section.js";
|
|
2
|
+
import { createVueRuleTester } from "../rule-tester.js";
|
|
3
|
+
|
|
4
|
+
const ruleTester = createVueRuleTester();
|
|
5
|
+
|
|
6
|
+
ruleTester.run("vue-event-listener-section", rule, {
|
|
7
|
+
valid: [
|
|
8
|
+
{
|
|
9
|
+
code: "export default { methods: {} };"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
code: `
|
|
13
|
+
export default {
|
|
14
|
+
methods: {
|
|
15
|
+
// --> ACTIONS <--
|
|
16
|
+
save() {},
|
|
17
|
+
// --> HELPERS <--
|
|
18
|
+
onlyOnce() {},
|
|
19
|
+
onload() {},
|
|
20
|
+
on_save() {},
|
|
21
|
+
on2Factor() {}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
`
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
code: `
|
|
28
|
+
export default defineComponent({
|
|
29
|
+
methods: {
|
|
30
|
+
// --> EVENT LISTENERS <--
|
|
31
|
+
onSave() {},
|
|
32
|
+
onURLChange() {},
|
|
33
|
+
"onClose"() {}
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
`
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
code: `
|
|
40
|
+
export default {
|
|
41
|
+
methods: {
|
|
42
|
+
// --> HELPERS <--
|
|
43
|
+
createHandlers() {
|
|
44
|
+
return {
|
|
45
|
+
onSave() {}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
`
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
filename: "Component.vue",
|
|
54
|
+
code: `
|
|
55
|
+
<script>
|
|
56
|
+
export default defineComponent({
|
|
57
|
+
methods: {
|
|
58
|
+
// --> ACTIONS <--
|
|
59
|
+
save() {},
|
|
60
|
+
// --> EVENT LISTENERS <--
|
|
61
|
+
onLoadMore() {}
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
</script>
|
|
65
|
+
`
|
|
66
|
+
}
|
|
67
|
+
],
|
|
68
|
+
|
|
69
|
+
invalid: [
|
|
70
|
+
{
|
|
71
|
+
code: `
|
|
72
|
+
export default {
|
|
73
|
+
methods: {
|
|
74
|
+
// --> ACTIONS <--
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Saves content
|
|
78
|
+
*/
|
|
79
|
+
save() {},
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Triggers on save
|
|
83
|
+
*/
|
|
84
|
+
onSave() {}
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
`,
|
|
88
|
+
output: `
|
|
89
|
+
export default {
|
|
90
|
+
methods: {
|
|
91
|
+
// --> ACTIONS <--
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Saves content
|
|
95
|
+
*/
|
|
96
|
+
save() {},
|
|
97
|
+
|
|
98
|
+
// --> EVENT LISTENERS <--
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Triggers on save
|
|
102
|
+
*/
|
|
103
|
+
onSave() {}
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
`,
|
|
107
|
+
errors: [
|
|
108
|
+
{
|
|
109
|
+
messageId: "wrongSection",
|
|
110
|
+
data: { name: "onSave" }
|
|
111
|
+
}
|
|
112
|
+
]
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
code: `
|
|
116
|
+
export default {
|
|
117
|
+
methods: {
|
|
118
|
+
// --> HELPERS <--
|
|
119
|
+
|
|
120
|
+
format() {},
|
|
121
|
+
|
|
122
|
+
onLoadMore() {}
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
`,
|
|
126
|
+
output: `
|
|
127
|
+
export default {
|
|
128
|
+
methods: {
|
|
129
|
+
// --> HELPERS <--
|
|
130
|
+
|
|
131
|
+
format() {},
|
|
132
|
+
|
|
133
|
+
// --> EVENT LISTENERS <--
|
|
134
|
+
|
|
135
|
+
onLoadMore() {}
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
`,
|
|
139
|
+
errors: [
|
|
140
|
+
{
|
|
141
|
+
messageId: "wrongSection",
|
|
142
|
+
data: { name: "onLoadMore" }
|
|
143
|
+
}
|
|
144
|
+
]
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
code: `
|
|
148
|
+
export default {
|
|
149
|
+
methods: {
|
|
150
|
+
"onClose": function() {}
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
`,
|
|
154
|
+
output: `
|
|
155
|
+
export default {
|
|
156
|
+
methods: {
|
|
157
|
+
// --> EVENT LISTENERS <--
|
|
158
|
+
|
|
159
|
+
"onClose": function() {}
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
`,
|
|
163
|
+
errors: [
|
|
164
|
+
{
|
|
165
|
+
messageId: "wrongSection",
|
|
166
|
+
data: { name: "onClose" }
|
|
167
|
+
}
|
|
168
|
+
]
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
filename: "Component.vue",
|
|
172
|
+
code: `
|
|
173
|
+
<script>
|
|
174
|
+
export default defineComponent({
|
|
175
|
+
methods: {
|
|
176
|
+
// --> ACTIONS <--
|
|
177
|
+
|
|
178
|
+
save() {},
|
|
179
|
+
|
|
180
|
+
onSave() {},
|
|
181
|
+
// --> HELPERS <--
|
|
182
|
+
|
|
183
|
+
format() {},
|
|
184
|
+
|
|
185
|
+
onFormatComplete() {},
|
|
186
|
+
// --> EVENT LISTENERS <--
|
|
187
|
+
|
|
188
|
+
onClose() {}
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
</script>
|
|
192
|
+
`,
|
|
193
|
+
output: `
|
|
194
|
+
<script>
|
|
195
|
+
export default defineComponent({
|
|
196
|
+
methods: {
|
|
197
|
+
// --> ACTIONS <--
|
|
198
|
+
|
|
199
|
+
save() {},
|
|
200
|
+
|
|
201
|
+
// --> HELPERS <--
|
|
202
|
+
|
|
203
|
+
format() {},
|
|
204
|
+
|
|
205
|
+
// --> EVENT LISTENERS <--
|
|
206
|
+
|
|
207
|
+
onClose() {},
|
|
208
|
+
|
|
209
|
+
onSave() {},
|
|
210
|
+
|
|
211
|
+
onFormatComplete() {}
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
</script>
|
|
215
|
+
`,
|
|
216
|
+
errors: [
|
|
217
|
+
{
|
|
218
|
+
messageId: "wrongSection",
|
|
219
|
+
data: { name: "onSave" }
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
messageId: "wrongSection",
|
|
223
|
+
data: { name: "onFormatComplete" }
|
|
224
|
+
}
|
|
225
|
+
]
|
|
226
|
+
}
|
|
227
|
+
]
|
|
228
|
+
});
|