@vue-jsx/eslint 3.3.0-beta.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 zhiyuanzmj <https://github.com/zhiyuanzmj>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,48 @@
1
+ import * as _$_typescript_eslint_utils_ts_eslint0 from "@typescript-eslint/utils/ts-eslint";
2
+ import { ClassicConfig, Linter } from "@typescript-eslint/utils/ts-eslint";
3
+
4
+ //#region src/rules/jsx-sort-props/types.d.ts
5
+ interface JsxSortPropsSchema0 {
6
+ callbacksLast?: boolean;
7
+ shorthandFirst?: boolean;
8
+ shorthandLast?: boolean;
9
+ multiline?: 'ignore' | 'first' | 'last';
10
+ ignoreCase?: boolean;
11
+ noSortAlphabetically?: boolean;
12
+ reservedFirst?: string[] | boolean;
13
+ reservedLast?: string[];
14
+ locale?: string;
15
+ }
16
+ type JsxSortPropsRuleOptions = [JsxSortPropsSchema0?];
17
+ type MessageIds$1 = 'listIsEmpty' | 'listReservedPropsFirst' | 'listReservedPropsLast' | 'listCallbacksLast' | 'listShorthandFirst' | 'listShorthandLast' | 'listMultilineFirst' | 'listMultilineLast' | 'sortPropsByAlpha';
18
+ //#endregion
19
+ //#region src/rules/define-style/types.d.ts
20
+ interface DefineStyleSchema0 {
21
+ tabWidth?: number;
22
+ }
23
+ type DefineStyleRuleOptions = [DefineStyleSchema0?];
24
+ type MessageIds = 'define-style' | 'define-style-syntax-error';
25
+ //#endregion
26
+ //#region src/rules/index.d.ts
27
+ declare const ruleOptions: {
28
+ 'jsx-sort-props': _$_typescript_eslint_utils_ts_eslint0.RuleModule<MessageIds$1, JsxSortPropsRuleOptions, unknown, _$_typescript_eslint_utils_ts_eslint0.RuleListener>;
29
+ 'define-style': _$_typescript_eslint_utils_ts_eslint0.RuleModule<MessageIds, DefineStyleRuleOptions, unknown, _$_typescript_eslint_utils_ts_eslint0.RuleListener>;
30
+ };
31
+ interface RuleOptions {
32
+ 'vue-jsx-vapor/jsx-sort-props': JsxSortPropsRuleOptions;
33
+ 'vue-jsx-vapor/define-style': DefineStyleRuleOptions;
34
+ }
35
+ type Rules = Partial<{ [K in keyof RuleOptions]: Linter.Severity | [Linter.Severity, ...RuleOptions[K]] }>;
36
+ //#endregion
37
+ //#region src/index.d.ts
38
+ declare const plugins: {
39
+ 'vue-jsx-vapor': {
40
+ rules: {
41
+ 'jsx-sort-props': _$_typescript_eslint_utils_ts_eslint0.RuleModule<MessageIds$1, JsxSortPropsRuleOptions, unknown, _$_typescript_eslint_utils_ts_eslint0.RuleListener>;
42
+ 'define-style': _$_typescript_eslint_utils_ts_eslint0.RuleModule<MessageIds, DefineStyleRuleOptions, unknown, _$_typescript_eslint_utils_ts_eslint0.RuleListener>;
43
+ };
44
+ };
45
+ };
46
+ declare const config: (options: ClassicConfig.Config) => Record<string, unknown>;
47
+ //#endregion
48
+ export { type Rules, config as default, plugins, ruleOptions as rules };
package/dist/index.js ADDED
@@ -0,0 +1,524 @@
1
+ import prettier from "@prettier/sync";
2
+ //#region src/rules/define-style/index.ts
3
+ const rule$1 = {
4
+ defaultOptions: [{ tabWidth: 2 }],
5
+ meta: {
6
+ type: "layout",
7
+ docs: { description: "Enforce consistent formatting in defineStyle CSS" },
8
+ fixable: "code",
9
+ messages: {
10
+ "define-style": "Style in defineStyle should be properly formatted",
11
+ "define-style-syntax-error": "Syntax error in defineStyle"
12
+ },
13
+ schema: [{
14
+ type: "object",
15
+ properties: { tabWidth: {
16
+ type: "number",
17
+ default: 2
18
+ } }
19
+ }]
20
+ },
21
+ create(context) {
22
+ const tabWidth = (context.options[0] || {}).tabWidth || 2;
23
+ return { CallExpression(node) {
24
+ const callee = node.callee.type === "MemberExpression" ? node.callee.object : node.callee;
25
+ const parser = node.callee.type === "MemberExpression" && node.callee.property.type === "Identifier" ? node.callee.property.name : "css";
26
+ if (callee.type === "Identifier" && callee.name === "defineStyle") {
27
+ const arg = node.arguments[0];
28
+ if (arg?.type === "TemplateLiteral") {
29
+ let index = 0;
30
+ const cssRaw = context.sourceCode.text.slice(arg.range[0] + 1, arg.range[1] - 1);
31
+ let formattedCss;
32
+ try {
33
+ formattedCss = prettier.format(arg.quasis.map((i) => i.value.raw + (arg.expressions[index] ? `-MACROS_START-${context.sourceCode.text.slice(...arg.expressions[index++].range)}-MACROS_END-` : "")).join(""), {
34
+ parser,
35
+ tabWidth
36
+ }).replaceAll("-MACROS_START-", "${").replaceAll("-MACROS_END-", "}");
37
+ } catch {
38
+ return context.report({
39
+ node: arg,
40
+ messageId: "define-style-syntax-error"
41
+ });
42
+ }
43
+ const line = callee.loc.start.line;
44
+ function getOffset(node) {
45
+ if (node.parent?.loc.start.line === line) return getOffset(node.parent);
46
+ return node.loc.start.column;
47
+ }
48
+ const column = getOffset(callee);
49
+ const placeholder = " ".repeat(column + tabWidth);
50
+ const result = `\n${placeholder}${formattedCss.slice(0, -1).replaceAll("\n", `\n${placeholder}`)}\n${" ".repeat(column)}`;
51
+ if (result !== cssRaw) context.report({
52
+ node: arg,
53
+ messageId: "define-style",
54
+ fix(fixer) {
55
+ return fixer.replaceTextRange([arg.range[0] + 1, arg.range[1] - 1], result);
56
+ }
57
+ });
58
+ }
59
+ }
60
+ } };
61
+ }
62
+ };
63
+ //#endregion
64
+ //#region src/rules/jsx-sort-props/index.ts
65
+ const COMPAT_TAG_REGEX = /^[a-z]/;
66
+ /**
67
+ * Checks if a node represents a DOM element according to React.
68
+ * @param node - JSXOpeningElement to check.
69
+ * @returns Whether or not the node corresponds to a DOM element.
70
+ */
71
+ function isDOMComponent(node) {
72
+ const name = getElementType(node);
73
+ return COMPAT_TAG_REGEX.test(name);
74
+ }
75
+ /**
76
+ * Returns the name of the prop given the JSXAttribute object.
77
+ *
78
+ * Ported from `jsx-ast-utils/propName` to reduce bundle size
79
+ * @see https://github.com/jsx-eslint/jsx-ast-utils/blob/main/src/propName.js
80
+ */
81
+ function getPropName(prop) {
82
+ if (!prop.type || prop.type !== "JSXAttribute") throw new Error("The prop must be a JSXAttribute collected by the AST parser.");
83
+ if (prop.name.type === "JSXNamespacedName") return `${prop.name.namespace.name}:${prop.name.name.name}`;
84
+ return prop.name.name;
85
+ }
86
+ function resolveMemberExpressions(object, property) {
87
+ if (object.type === "JSXMemberExpression") return `${resolveMemberExpressions(object.object, object.property)}.${property.name}`;
88
+ return `${object.name}.${property.name}`;
89
+ }
90
+ /**
91
+ * Returns the tagName associated with a JSXElement.
92
+ *
93
+ * Ported from `jsx-ast-utils/elementType` to reduce bundle size
94
+ * @see https://github.com/jsx-eslint/jsx-ast-utils/blob/main/src/elementType.js
95
+ */
96
+ function getElementType(node) {
97
+ if (node.type === "JSXOpeningFragment") return "<>";
98
+ const { name } = node;
99
+ if (!name) throw new Error("The argument provided is not a JSXElement node.");
100
+ if (name.type === "JSXMemberExpression") {
101
+ const { object, property } = name;
102
+ return resolveMemberExpressions(object, property);
103
+ }
104
+ if (name.type === "JSXNamespacedName") return `${name.namespace.name}:${name.name.name}`;
105
+ return node.name.name;
106
+ }
107
+ function isCallbackPropName(name) {
108
+ return /^on[A-Z]/.test(name);
109
+ }
110
+ function isMultilineProp(node) {
111
+ return node.loc.start.line !== node.loc.end.line;
112
+ }
113
+ const messages = {
114
+ listIsEmpty: "A customized reserved first list must not be empty",
115
+ listReservedPropsFirst: "Reserved props must be listed before all other props",
116
+ listReservedPropsLast: "Reserved props must be listed after all other props",
117
+ listCallbacksLast: "Callbacks must be listed after all other props",
118
+ listShorthandFirst: "Shorthand props must be listed before all other props",
119
+ listShorthandLast: "Shorthand props must be listed after all other props",
120
+ listMultilineFirst: "Multiline props must be listed before all other props",
121
+ listMultilineLast: "Multiline props must be listed after all other props",
122
+ sortPropsByAlpha: "Props should be sorted alphabetically"
123
+ };
124
+ const RESERVED_PROPS_LIST = [
125
+ "children",
126
+ "dangerouslySetInnerHTML",
127
+ "key",
128
+ "ref"
129
+ ];
130
+ function getReservedPropIndex(name, list) {
131
+ return list.indexOf(name.split(":")[0]);
132
+ }
133
+ let attributeMap;
134
+ function shouldSortToEnd(node) {
135
+ const attr = attributeMap.get(node);
136
+ return !!attr && !!attr.hasComment;
137
+ }
138
+ function contextCompare(a, b, options) {
139
+ let aProp = getPropName(a);
140
+ let bProp = getPropName(b);
141
+ const aPropNamespace = aProp.split(":")[0];
142
+ const bPropNamespace = bProp.split(":")[0];
143
+ const aSortToEnd = shouldSortToEnd(a);
144
+ const bSortToEnd = shouldSortToEnd(b);
145
+ if (aSortToEnd && !bSortToEnd) return 1;
146
+ if (!aSortToEnd && bSortToEnd) return -1;
147
+ if (options.reservedFirst) {
148
+ const aIndex = getReservedPropIndex(aProp, options.reservedList);
149
+ const bIndex = getReservedPropIndex(bProp, options.reservedList);
150
+ if (aIndex > -1 && bIndex === -1) return -1;
151
+ if (aIndex === -1 && bIndex > -1) return 1;
152
+ if (aIndex > -1 && bIndex > -1 && aPropNamespace !== bPropNamespace) return aIndex > bIndex ? 1 : -1;
153
+ }
154
+ if (options.reservedLast.length > 0) {
155
+ const aLastIndex = getReservedPropIndex(aProp, options.reservedLast);
156
+ const bLastIndex = getReservedPropIndex(bProp, options.reservedLast);
157
+ if (aLastIndex > -1 && bLastIndex === -1) return 1;
158
+ if (aLastIndex === -1 && bLastIndex > -1) return -1;
159
+ if (aLastIndex > -1 && bLastIndex > -1 && aPropNamespace !== bPropNamespace) return aLastIndex > bLastIndex ? -1 : 1;
160
+ }
161
+ if (options.callbacksLast) {
162
+ const aIsCallback = isCallbackPropName(aProp);
163
+ const bIsCallback = isCallbackPropName(bProp);
164
+ if (aIsCallback && !bIsCallback) return 1;
165
+ if (!aIsCallback && bIsCallback) return -1;
166
+ }
167
+ if (options.shorthandFirst || options.shorthandLast) {
168
+ const shorthandSign = options.shorthandFirst ? -1 : 1;
169
+ if (!a.value && b.value) return shorthandSign;
170
+ if (a.value && !b.value) return -shorthandSign;
171
+ }
172
+ if (options.multiline !== "ignore") {
173
+ const multilineSign = options.multiline === "first" ? -1 : 1;
174
+ const aIsMultiline = isMultilineProp(a);
175
+ const bIsMultiline = isMultilineProp(b);
176
+ if (aIsMultiline && !bIsMultiline) return multilineSign;
177
+ if (!aIsMultiline && bIsMultiline) return -multilineSign;
178
+ }
179
+ if (options.noSortAlphabetically) return 0;
180
+ const actualLocale = options.locale === "auto" ? void 0 : options.locale;
181
+ if (options.ignoreCase) {
182
+ aProp = aProp.toLowerCase();
183
+ bProp = bProp.toLowerCase();
184
+ return aProp.localeCompare(bProp, actualLocale);
185
+ }
186
+ if (aProp === bProp) return 0;
187
+ if (options.locale === "auto") return aProp < bProp ? -1 : 1;
188
+ return aProp.localeCompare(bProp, actualLocale);
189
+ }
190
+ /**
191
+ * Create an array of arrays where each subarray is composed of attributes
192
+ * that are considered sortable.
193
+ * @param attributes
194
+ * @param context The context of the rule
195
+ */
196
+ function getGroupsOfSortableAttributes(attributes, context) {
197
+ const sourceCode = context.sourceCode;
198
+ const sortableAttributeGroups = [];
199
+ let groupCount = 0;
200
+ function addtoSortableAttributeGroups(attribute) {
201
+ sortableAttributeGroups[groupCount - 1].push(attribute);
202
+ }
203
+ for (let i = 0; i < attributes.length; i++) {
204
+ const attribute = attributes[i];
205
+ const nextAttribute = attributes[i + 1];
206
+ const attributeline = attribute.loc.start.line;
207
+ let comment = [];
208
+ try {
209
+ comment = sourceCode.getCommentsAfter(attribute);
210
+ } catch {}
211
+ const lastAttr = attributes[i - 1];
212
+ const attrIsSpread = attribute.type === "JSXSpreadAttribute";
213
+ if (!lastAttr || lastAttr.type === "JSXSpreadAttribute" && !attrIsSpread) {
214
+ groupCount += 1;
215
+ sortableAttributeGroups[groupCount - 1] = [];
216
+ }
217
+ if (!attrIsSpread) if (comment.length === 0) {
218
+ attributeMap.set(attribute, {
219
+ end: attribute.range[1],
220
+ hasComment: false
221
+ });
222
+ addtoSortableAttributeGroups(attribute);
223
+ } else {
224
+ const firstComment = comment[0];
225
+ const commentline = firstComment.loc.start.line;
226
+ if (comment.length === 1) {
227
+ if (attributeline + 1 === commentline && nextAttribute) {
228
+ attributeMap.set(attribute, {
229
+ end: nextAttribute.range[1],
230
+ hasComment: true
231
+ });
232
+ addtoSortableAttributeGroups(attribute);
233
+ i += 1;
234
+ } else if (attributeline === commentline) {
235
+ if (firstComment.type === "Block" && nextAttribute) {
236
+ attributeMap.set(attribute, {
237
+ end: nextAttribute.range[1],
238
+ hasComment: true
239
+ });
240
+ i += 1;
241
+ } else if (firstComment.type === "Block") attributeMap.set(attribute, {
242
+ end: firstComment.range[1],
243
+ hasComment: true
244
+ });
245
+ else attributeMap.set(attribute, {
246
+ end: firstComment.range[1],
247
+ hasComment: false
248
+ });
249
+ addtoSortableAttributeGroups(attribute);
250
+ }
251
+ } else if (comment.length > 1 && attributeline + 1 === comment[1].loc.start.line && nextAttribute) {
252
+ const commentNextAttribute = sourceCode.getCommentsAfter(nextAttribute);
253
+ attributeMap.set(attribute, {
254
+ end: nextAttribute.range[1],
255
+ hasComment: true
256
+ });
257
+ if (commentNextAttribute.length === 1 && nextAttribute.loc.start.line === commentNextAttribute[0].loc.start.line) attributeMap.set(attribute, {
258
+ end: commentNextAttribute[0].range[1],
259
+ hasComment: true
260
+ });
261
+ addtoSortableAttributeGroups(attribute);
262
+ i += 1;
263
+ }
264
+ }
265
+ }
266
+ return sortableAttributeGroups;
267
+ }
268
+ function generateFixerFunction(node, context, reservedList) {
269
+ const sourceCode = context.sourceCode;
270
+ const attributes = node.attributes.slice(0);
271
+ const configuration = context.options[0] || {};
272
+ const options = {
273
+ ignoreCase: configuration.ignoreCase || false,
274
+ callbacksLast: configuration.callbacksLast || false,
275
+ shorthandFirst: configuration.shorthandFirst || false,
276
+ shorthandLast: configuration.shorthandLast || false,
277
+ multiline: configuration.multiline || "ignore",
278
+ noSortAlphabetically: configuration.noSortAlphabetically || false,
279
+ reservedFirst: configuration.reservedFirst || false,
280
+ reservedList,
281
+ reservedLast: configuration.reservedLast || [],
282
+ locale: configuration.locale || "auto"
283
+ };
284
+ const sortableAttributeGroups = getGroupsOfSortableAttributes(attributes, context);
285
+ const sortedAttributeGroups = sortableAttributeGroups.slice(0).map((group) => [...group].sort((a, b) => contextCompare(a, b, options)));
286
+ return function fixFunction(fixer) {
287
+ const fixers = [];
288
+ let source = sourceCode.getText();
289
+ sortableAttributeGroups.forEach((sortableGroup, ii) => {
290
+ sortableGroup.forEach((attr, jj) => {
291
+ const sortedAttr = sortedAttributeGroups[ii][jj];
292
+ const sortedAttrText = source.slice(sortedAttr.range[0], attributeMap.get(sortedAttr).end);
293
+ fixers.push({
294
+ range: [attr.range[0], attributeMap.get(attr).end],
295
+ text: sortedAttrText
296
+ });
297
+ });
298
+ });
299
+ fixers.sort((a, b) => b.range[0] - a.range[0]);
300
+ const firstFixer = fixers[0];
301
+ const lastFixer = fixers.at(-1);
302
+ const rangeStart = lastFixer ? lastFixer.range[0] : 0;
303
+ const rangeEnd = firstFixer ? firstFixer.range[1] : -0;
304
+ fixers.forEach((fix) => {
305
+ source = `${source.slice(0, fix.range[0])}${fix.text}${source.slice(fix.range[1])}`;
306
+ });
307
+ return fixer.replaceTextRange([rangeStart, rangeEnd], source.slice(rangeStart, rangeEnd));
308
+ };
309
+ }
310
+ /**
311
+ * Checks if the `reservedFirst` option is valid
312
+ * @param context The context of the rule
313
+ * @param reservedFirst The `reservedFirst` option
314
+ * @return {Function|undefined} If an error is detected, a function to generate the error message, otherwise, `undefined`
315
+ */
316
+ function validateReservedFirstConfig(context, reservedFirst) {
317
+ if (reservedFirst && Array.isArray(reservedFirst) && reservedFirst.length === 0) return function Report(decl) {
318
+ context.report({
319
+ node: decl,
320
+ messageId: "listIsEmpty"
321
+ });
322
+ };
323
+ }
324
+ const reportedNodeAttributes = /* @__PURE__ */ new WeakMap();
325
+ /**
326
+ * Check if the current node attribute has already been reported with the same error type
327
+ * if that's the case then we don't report a new error
328
+ * otherwise we report the error
329
+ * @param nodeAttribute The node attribute to be reported
330
+ * @param errorType The error type to be reported
331
+ * @param node The parent node for the node attribute
332
+ * @param context The context of the rule
333
+ * @param reservedList The list of reserved props
334
+ */
335
+ function reportNodeAttribute(nodeAttribute, errorType, node, context, reservedList) {
336
+ const errors = reportedNodeAttributes.get(nodeAttribute) || [];
337
+ if (errors.includes(errorType)) return;
338
+ errors.push(errorType);
339
+ reportedNodeAttributes.set(nodeAttribute, errors);
340
+ context.report({
341
+ node: nodeAttribute.name ?? "",
342
+ messageId: errorType,
343
+ fix: generateFixerFunction(node, context, reservedList)
344
+ });
345
+ }
346
+ //#endregion
347
+ //#region src/rules/index.ts
348
+ const ruleOptions = {
349
+ "jsx-sort-props": {
350
+ defaultOptions: [{
351
+ multiline: "ignore",
352
+ locale: "auto"
353
+ }],
354
+ meta: {
355
+ type: "layout",
356
+ docs: { description: "Enforce props alphabetical sorting" },
357
+ fixable: "code",
358
+ messages,
359
+ schema: [{
360
+ type: "object",
361
+ properties: {
362
+ callbacksLast: { type: "boolean" },
363
+ shorthandFirst: { type: "boolean" },
364
+ shorthandLast: { type: "boolean" },
365
+ multiline: {
366
+ type: "string",
367
+ enum: [
368
+ "ignore",
369
+ "first",
370
+ "last"
371
+ ],
372
+ default: "ignore"
373
+ },
374
+ ignoreCase: { type: "boolean" },
375
+ noSortAlphabetically: { type: "boolean" },
376
+ reservedFirst: { type: ["array", "boolean"] },
377
+ reservedLast: { type: "array" },
378
+ locale: {
379
+ type: "string",
380
+ default: "auto"
381
+ }
382
+ },
383
+ additionalProperties: false
384
+ }]
385
+ },
386
+ create(context) {
387
+ const configuration = context.options[0] || {};
388
+ const ignoreCase = configuration.ignoreCase || false;
389
+ const callbacksLast = configuration.callbacksLast || false;
390
+ const shorthandFirst = configuration.shorthandFirst || false;
391
+ const shorthandLast = configuration.shorthandLast || false;
392
+ const multiline = configuration.multiline || "ignore";
393
+ const noSortAlphabetically = configuration.noSortAlphabetically || false;
394
+ const reservedFirst = configuration.reservedFirst || false;
395
+ const reservedFirstError = validateReservedFirstConfig(context, reservedFirst);
396
+ const reservedList = Array.isArray(reservedFirst) ? reservedFirst : RESERVED_PROPS_LIST;
397
+ const reservedLastList = configuration.reservedLast || [];
398
+ const locale = configuration.locale || "auto";
399
+ return {
400
+ Program() {
401
+ attributeMap = /* @__PURE__ */ new WeakMap();
402
+ },
403
+ JSXOpeningElement(node) {
404
+ const nodeReservedList = reservedFirst && !isDOMComponent(node) ? reservedList.filter((prop) => prop !== "dangerouslySetInnerHTML") : reservedList;
405
+ node.attributes.reduce((memo, decl, idx, attrs) => {
406
+ if (decl.type === "JSXSpreadAttribute") return attrs[idx + 1];
407
+ let previousPropName = getPropName(memo);
408
+ let currentPropName = getPropName(decl);
409
+ const previousReservedNamespace = previousPropName.split(":")[0];
410
+ const currentReservedNamespace = currentPropName.split(":")[0];
411
+ const previousValue = memo.value;
412
+ const currentValue = decl.value;
413
+ const previousIsCallback = isCallbackPropName(previousPropName);
414
+ const currentIsCallback = isCallbackPropName(currentPropName);
415
+ if (ignoreCase) {
416
+ previousPropName = previousPropName.toLowerCase();
417
+ currentPropName = currentPropName.toLowerCase();
418
+ }
419
+ if (reservedFirst) {
420
+ if (reservedFirstError) {
421
+ reservedFirstError(decl);
422
+ return memo;
423
+ }
424
+ const previousReservedIndex = getReservedPropIndex(previousPropName, nodeReservedList);
425
+ const currentReservedIndex = getReservedPropIndex(currentPropName, nodeReservedList);
426
+ if (previousReservedIndex > -1 && currentReservedIndex === -1) return decl;
427
+ if (reservedFirst !== true && previousReservedIndex > currentReservedIndex || previousReservedIndex === -1 && currentReservedIndex > -1) {
428
+ reportNodeAttribute(decl, "listReservedPropsFirst", node, context, nodeReservedList);
429
+ return memo;
430
+ }
431
+ if (previousReservedIndex > -1 && currentReservedIndex > -1 && currentReservedIndex > previousReservedIndex && previousReservedNamespace !== currentReservedNamespace) return decl;
432
+ }
433
+ if (reservedLastList.length > 0) {
434
+ const previousReservedIndex = getReservedPropIndex(previousPropName, reservedLastList);
435
+ const currentReservedIndex = getReservedPropIndex(currentPropName, reservedLastList);
436
+ if (previousReservedIndex === -1 && currentReservedIndex > -1) return decl;
437
+ if (previousReservedIndex < currentReservedIndex || previousReservedIndex > -1 && currentReservedIndex === -1) {
438
+ reportNodeAttribute(decl, "listReservedPropsLast", node, context, nodeReservedList);
439
+ return memo;
440
+ }
441
+ if (previousReservedIndex > -1 && currentReservedIndex > -1 && currentReservedIndex > previousReservedIndex && previousReservedNamespace !== currentReservedNamespace) return decl;
442
+ }
443
+ if (callbacksLast) {
444
+ if (!previousIsCallback && currentIsCallback) return decl;
445
+ if (previousIsCallback && !currentIsCallback) {
446
+ reportNodeAttribute(memo, "listCallbacksLast", node, context, nodeReservedList);
447
+ return memo;
448
+ }
449
+ }
450
+ if (shorthandFirst) {
451
+ if (currentValue && !previousValue) return decl;
452
+ if (!currentValue && previousValue) {
453
+ reportNodeAttribute(decl, "listShorthandFirst", node, context, nodeReservedList);
454
+ return memo;
455
+ }
456
+ }
457
+ if (shorthandLast) {
458
+ if (!currentValue && previousValue) return decl;
459
+ if (currentValue && !previousValue) {
460
+ reportNodeAttribute(memo, "listShorthandLast", node, context, nodeReservedList);
461
+ return memo;
462
+ }
463
+ }
464
+ const previousIsMultiline = isMultilineProp(memo);
465
+ const currentIsMultiline = isMultilineProp(decl);
466
+ if (multiline === "first") {
467
+ if (previousIsMultiline && !currentIsMultiline) return decl;
468
+ if (!previousIsMultiline && currentIsMultiline) {
469
+ reportNodeAttribute(decl, "listMultilineFirst", node, context, nodeReservedList);
470
+ return memo;
471
+ }
472
+ } else if (multiline === "last") {
473
+ if (!previousIsMultiline && currentIsMultiline) return decl;
474
+ if (previousIsMultiline && !currentIsMultiline) {
475
+ reportNodeAttribute(memo, "listMultilineLast", node, context, nodeReservedList);
476
+ return memo;
477
+ }
478
+ }
479
+ if (!noSortAlphabetically && (ignoreCase || locale !== "auto" ? previousPropName.localeCompare(currentPropName, locale === "auto" ? void 0 : locale) > 0 : previousPropName > currentPropName)) {
480
+ reportNodeAttribute(decl, "sortPropsByAlpha", node, context, nodeReservedList);
481
+ return memo;
482
+ }
483
+ return decl;
484
+ }, node.attributes[0]);
485
+ }
486
+ };
487
+ }
488
+ },
489
+ "define-style": rule$1
490
+ };
491
+ //#endregion
492
+ //#region src/index.ts
493
+ const plugins = { "vue-jsx-vapor": { rules: ruleOptions } };
494
+ const config = ({ rules = {}, ...options } = {}) => ({
495
+ name: "vue-jsx-vapor",
496
+ plugins,
497
+ rules: {
498
+ "style/jsx-sort-props": "off",
499
+ "react/jsx-sort-props": "off",
500
+ "vue-jsx-vapor/jsx-sort-props": rules["vue-jsx-vapor/jsx-sort-props"] || ["warn", {
501
+ callbacksLast: true,
502
+ shorthandFirst: true,
503
+ reservedFirst: [
504
+ "v-if",
505
+ "v-else-if",
506
+ "v-else",
507
+ "v-for",
508
+ "key",
509
+ "ref",
510
+ "v-model"
511
+ ],
512
+ reservedLast: [
513
+ "v-slot",
514
+ "v-slots",
515
+ "v-text",
516
+ "v-html"
517
+ ]
518
+ }],
519
+ "vue-jsx-vapor/define-style": rules["vue-jsx-vapor/define-style"] || "warn"
520
+ },
521
+ ...options
522
+ });
523
+ //#endregion
524
+ export { config as default, plugins, ruleOptions as rules };
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@vue-jsx/eslint",
3
+ "type": "module",
4
+ "version": "3.3.0-beta.0",
5
+ "description": "Vue JSX ESLint Plugin",
6
+ "license": "MIT",
7
+ "homepage": "https://github.com/vuejs/vue-jsx-vapor#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/vuejs/vue-jsx-vapor.git"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/vuejs/vue-jsx-vapor/issues"
14
+ },
15
+ "keywords": [
16
+ "vue",
17
+ "jsx",
18
+ "vapor",
19
+ "eslint"
20
+ ],
21
+ "exports": {
22
+ ".": "./dist/index.js",
23
+ "./*": "./*"
24
+ },
25
+ "main": "dist/index.js",
26
+ "types": "dist/index.d.ts",
27
+ "files": [
28
+ "dist"
29
+ ],
30
+ "dependencies": {
31
+ "@prettier/sync": "^0.6.1",
32
+ "@typescript-eslint/utils": "^8.59.1"
33
+ },
34
+ "devDependencies": {
35
+ "eslint-vitest-rule-tester": "^3.1.0"
36
+ },
37
+ "scripts": {
38
+ "build": "tsdown",
39
+ "dev": "DEV=true tsdown",
40
+ "release": "bumpp && npm publish",
41
+ "test": "vitest"
42
+ }
43
+ }