eslint-plugin-react-jsx 0.0.0 → 4.0.0-beta.2

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 Rel1cx
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.
package/README.md CHANGED
@@ -1,15 +1,38 @@
1
1
  # eslint-plugin-react-jsx
2
2
 
3
- To install dependencies:
3
+ React Flavored JSX rules for React.
4
4
 
5
- ```bash
6
- bun install
5
+ ## Install
6
+
7
+ ```sh
8
+ # npm
9
+ npm install --save-dev eslint-plugin-react-jsx
7
10
  ```
8
11
 
9
- To run:
12
+ ## Setup
13
+
14
+ ```ts
15
+ import js from "@eslint/js";
16
+ import reactJsx from "eslint-plugin-react-jsx";
17
+ import { defineConfig } from "eslint/config";
18
+ import tseslint from "typescript-eslint";
10
19
 
11
- ```bash
12
- bun run index.ts
20
+ export default defineConfig(
21
+ {
22
+ files: ["**/*.{ts,tsx}"],
23
+ extends: [
24
+ js.configs.recommended,
25
+ tseslint.configs.recommended,
26
+ // Add configs from eslint-plugin-react-jsx
27
+ reactJsx.configs.recommended,
28
+ ],
29
+ rules: {
30
+ // Put rules you want to override here
31
+ },
32
+ },
33
+ );
13
34
  ```
14
35
 
15
- This project was created using `bun init` in bun v1.3.10. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.
36
+ ## Rules
37
+
38
+ <https://eslint-react.xyz/docs/rules/overview#jsx-rules>
@@ -0,0 +1,9 @@
1
+ import { ESLint, Linter } from "eslint";
2
+
3
+ //#region src/index.d.ts
4
+ type ConfigName = "recommended" | "strict";
5
+ declare const finalPlugin: ESLint.Plugin & {
6
+ configs: Record<ConfigName, Linter.Config>;
7
+ };
8
+ //#endregion
9
+ export { finalPlugin as default };
package/dist/index.js ADDED
@@ -0,0 +1,505 @@
1
+ import { DEFAULT_ESLINT_REACT_SETTINGS, WEBSITE_URL, defineRuleListener } from "@eslint-react/shared";
2
+ import { JsxEmit, findAttribute, getChildren, getElementFullType, getJsxConfig, hasAnyAttribute, hasChildren, isFragmentElement, isHostElement, isWhitespaceText } from "@eslint-react/jsx";
3
+ import { AST_NODE_TYPES } from "@typescript-eslint/types";
4
+ import { ESLintUtils } from "@typescript-eslint/utils";
5
+ import * as ast from "@eslint-react/ast";
6
+
7
+ //#region \0rolldown/runtime.js
8
+ var __defProp = Object.defineProperty;
9
+ var __exportAll = (all, no_symbols) => {
10
+ let target = {};
11
+ for (var name in all) {
12
+ __defProp(target, name, {
13
+ get: all[name],
14
+ enumerable: true
15
+ });
16
+ }
17
+ if (!no_symbols) {
18
+ __defProp(target, Symbol.toStringTag, { value: "Module" });
19
+ }
20
+ return target;
21
+ };
22
+
23
+ //#endregion
24
+ //#region package.json
25
+ var name$2 = "eslint-plugin-react-jsx";
26
+ var version = "4.0.0-beta.2";
27
+
28
+ //#endregion
29
+ //#region src/utils/create-rule.ts
30
+ function getDocsUrl(ruleName) {
31
+ return `${WEBSITE_URL}/docs/rules/${ruleName}`;
32
+ }
33
+ const createRule = ESLintUtils.RuleCreator(getDocsUrl);
34
+
35
+ //#endregion
36
+ //#region src/utils/jsx.ts
37
+ /**
38
+ * Trim leading / trailing whitespace the same way React does when rendering
39
+ * JSX text. Whitespace that contains a newline is stripped entirely;
40
+ * whitespace that stays on the same line is preserved.
41
+ * @param text
42
+ */
43
+ function trimLikeReact(text) {
44
+ const leadingSpaces = /^\s*/.exec(text)?.[0] ?? "";
45
+ const trailingSpaces = /\s*$/.exec(text)?.[0] ?? "";
46
+ const start = leadingSpaces.includes("\n") ? leadingSpaces.length : 0;
47
+ const end = trailingSpaces.includes("\n") ? text.length - trailingSpaces.length : text.length;
48
+ return text.slice(start, end);
49
+ }
50
+ /**
51
+ * Compute the removal range for a JSX attribute, consuming any leading
52
+ * whitespace (spaces, tabs, newlines) so the resulting markup stays clean.
53
+ * @param context
54
+ * @param prop
55
+ */
56
+ function getPropRemovalRange(context, prop) {
57
+ const { sourceCode } = context;
58
+ let start = prop.range[0];
59
+ const end = prop.range[1];
60
+ while (start > 0 && /\s/.test(sourceCode.text[start - 1])) start--;
61
+ return [start, end];
62
+ }
63
+ /**
64
+ * Extract the text to use as JSX children content from a `children` prop.
65
+ *
66
+ * - `children="text"` -> `text` (raw string, no quotes)
67
+ * - `children={<div />}` -> `<div />` (JSX element, no braces)
68
+ * - `children={<>…</>}` -> `<>…</>` (JSX fragment, no braces)
69
+ * - `children={expression}` -> `{expression}` (wrapped in braces)
70
+ * - `children` -> `null` (boolean shorthand, cannot extract)
71
+ * @param context
72
+ * @param prop
73
+ */
74
+ function getChildrenPropText(context, prop) {
75
+ const { sourceCode } = context;
76
+ const { value } = prop;
77
+ if (value == null) return null;
78
+ if (value.type === AST_NODE_TYPES.Literal) return String(value.value);
79
+ if (value.type === AST_NODE_TYPES.JSXExpressionContainer) {
80
+ const { expression } = value;
81
+ if (expression.type === AST_NODE_TYPES.JSXEmptyExpression) return null;
82
+ const exprText = sourceCode.getText(expression);
83
+ if (ast.isJSXElementLike(expression)) return exprText;
84
+ return `{${exprText}}`;
85
+ }
86
+ return null;
87
+ }
88
+ /**
89
+ * Compute the range covering **all** children content of a JSX element or
90
+ * fragment (from the start of the first child to the end of the last child).
91
+ *
92
+ * Returns `null` when there are no children at all.
93
+ * @param node
94
+ */
95
+ function getChildrenContentRange(node) {
96
+ if (node.children.length === 0) return null;
97
+ const first = node.children[0];
98
+ const last = node.children[node.children.length - 1];
99
+ return [first.range[0], last.range[1]];
100
+ }
101
+ /**
102
+ * Extract the raw source text of an element's / fragment's children
103
+ * (everything between the opening and closing tags).
104
+ *
105
+ * Returns `""` for self-closing elements like `<Fragment />`.
106
+ * @param context
107
+ * @param node
108
+ */
109
+ function getChildrenSourceText(context, node) {
110
+ const { sourceCode } = context;
111
+ const opener = node.type === AST_NODE_TYPES.JSXFragment ? node.openingFragment : node.openingElement;
112
+ const closer = node.type === AST_NODE_TYPES.JSXFragment ? node.closingFragment : node.closingElement;
113
+ if (opener.type === AST_NODE_TYPES.JSXOpeningElement && opener.selfClosing) return "";
114
+ return sourceCode.text.slice(opener.range[1], closer?.range[0]);
115
+ }
116
+
117
+ //#endregion
118
+ //#region src/rules/no-children-prop-with-children/no-children-prop-with-children.ts
119
+ const RULE_NAME$5 = "no-children-prop-with-children";
120
+ var no_children_prop_with_children_default = createRule({
121
+ meta: {
122
+ type: "problem",
123
+ docs: { description: "Disallows passing 'children' as a prop when children are also passed as nested content." },
124
+ fixable: "code",
125
+ hasSuggestions: true,
126
+ messages: {
127
+ default: "Do not pass 'children' as a prop when the element already has children content.",
128
+ removeChildrenContent: "Remove the nested children content.",
129
+ removeChildrenProp: "Remove the 'children' prop."
130
+ },
131
+ schema: []
132
+ },
133
+ name: RULE_NAME$5,
134
+ create: create$5,
135
+ defaultOptions: []
136
+ });
137
+ function create$5(context) {
138
+ return defineRuleListener({ JSXElement(node) {
139
+ const childrenProp = findAttribute(context, node, "children");
140
+ if (childrenProp == null) return;
141
+ if (!hasChildren(node)) return;
142
+ if (childrenProp.type !== AST_NODE_TYPES.JSXAttribute) {
143
+ context.report({
144
+ messageId: "default",
145
+ node: childrenProp
146
+ });
147
+ return;
148
+ }
149
+ context.report({
150
+ messageId: "default",
151
+ node: childrenProp,
152
+ suggest: [{
153
+ fix(fixer) {
154
+ const [start, end] = getPropRemovalRange(context, childrenProp);
155
+ return fixer.removeRange([start, end]);
156
+ },
157
+ messageId: "removeChildrenProp"
158
+ }, {
159
+ fix(fixer) {
160
+ const range = getChildrenContentRange(node);
161
+ if (range == null) return [];
162
+ return fixer.removeRange(range);
163
+ },
164
+ messageId: "removeChildrenContent"
165
+ }]
166
+ });
167
+ } });
168
+ }
169
+
170
+ //#endregion
171
+ //#region src/rules/no-children-prop/no-children-prop.ts
172
+ const RULE_NAME$4 = "no-children-prop";
173
+ var no_children_prop_default = createRule({
174
+ meta: {
175
+ type: "suggestion",
176
+ docs: { description: "Disallows passing 'children' as a prop." },
177
+ fixable: "code",
178
+ hasSuggestions: true,
179
+ messages: {
180
+ default: "Do not pass 'children' as props.",
181
+ moveChildrenToContent: "Move 'children' to element content."
182
+ },
183
+ schema: []
184
+ },
185
+ name: RULE_NAME$4,
186
+ create: create$4,
187
+ defaultOptions: []
188
+ });
189
+ function create$4(context) {
190
+ return defineRuleListener({ JSXElement(node) {
191
+ const childrenProp = findAttribute(context, node, "children");
192
+ if (childrenProp == null) return;
193
+ if (childrenProp.type !== AST_NODE_TYPES.JSXAttribute) {
194
+ context.report({
195
+ messageId: "default",
196
+ node: childrenProp
197
+ });
198
+ return;
199
+ }
200
+ const childrenText = getChildrenPropText(context, childrenProp);
201
+ if (childrenText == null) {
202
+ context.report({
203
+ messageId: "default",
204
+ node: childrenProp
205
+ });
206
+ return;
207
+ }
208
+ context.report({
209
+ messageId: "default",
210
+ node: childrenProp,
211
+ suggest: [{
212
+ fix(fixer) {
213
+ const sourceCode = context.sourceCode;
214
+ const { openingElement } = node;
215
+ const [removeStart, removeEnd] = getPropRemovalRange(context, childrenProp);
216
+ if (openingElement.selfClosing) {
217
+ const tagName = sourceCode.getText(openingElement.name);
218
+ const selfCloseOffset = sourceCode.getText(openingElement).lastIndexOf("/>");
219
+ let wsStart = openingElement.range[0] + selfCloseOffset;
220
+ while (wsStart > removeEnd && /\s/.test(sourceCode.text[wsStart - 1])) wsStart--;
221
+ return [fixer.removeRange([removeStart, removeEnd]), fixer.replaceTextRange([wsStart, openingElement.range[1]], `>${childrenText}</${tagName}>`)];
222
+ }
223
+ const fixes = [fixer.removeRange([removeStart, removeEnd])];
224
+ if (node.closingElement != null) fixes.push(fixer.insertTextBefore(node.closingElement, childrenText));
225
+ return fixes;
226
+ },
227
+ messageId: "moveChildrenToContent"
228
+ }]
229
+ });
230
+ } });
231
+ }
232
+
233
+ //#endregion
234
+ //#region src/rules/no-comment-textnodes/no-comment-textnodes.ts
235
+ const RULE_NAME$3 = "no-comment-textnodes";
236
+ var no_comment_textnodes_default = createRule({
237
+ meta: {
238
+ type: "problem",
239
+ docs: { description: "Prevents comment strings (ex: beginning with '//' or '/*') from being accidentally inserted into a JSX element's text nodes." },
240
+ messages: { default: "Possible misused comment in text node. Comments inside children section of tag should be placed inside braces." },
241
+ schema: []
242
+ },
243
+ name: RULE_NAME$3,
244
+ create: create$3,
245
+ defaultOptions: []
246
+ });
247
+ function create$3(context) {
248
+ function hasCommentLike(node) {
249
+ if (ast.isOneOf([AST_NODE_TYPES.JSXAttribute, AST_NODE_TYPES.JSXExpressionContainer])(node.parent)) return false;
250
+ return /^\s*\/(?:\/|\*)/mu.test(context.sourceCode.getText(node));
251
+ }
252
+ const visitorFunction = (node) => {
253
+ if (!ast.isJSXElementLike(node.parent)) return;
254
+ if (!hasCommentLike(node)) return;
255
+ context.report({
256
+ messageId: "default",
257
+ node
258
+ });
259
+ };
260
+ return defineRuleListener({
261
+ JSXText: visitorFunction,
262
+ Literal: visitorFunction
263
+ });
264
+ }
265
+
266
+ //#endregion
267
+ //#region src/rules/no-deoptimization/no-deoptimization.ts
268
+ const RULE_NAME$2 = "no-deoptimization";
269
+ var no_deoptimization_default = createRule({
270
+ meta: {
271
+ type: "problem",
272
+ docs: { description: "Prevent patterns that cause deoptimization when using the automatic JSX runtime." },
273
+ messages: { noKeyAfterSpread: "Placing 'key' after spread props causes deoptimization when using the automatic JSX runtime. Put 'key' before any spread props." },
274
+ schema: []
275
+ },
276
+ name: RULE_NAME$2,
277
+ create: create$2,
278
+ defaultOptions: []
279
+ });
280
+ function create$2(context) {
281
+ const { jsx } = getJsxConfig(context);
282
+ if (!(jsx === JsxEmit.ReactJSX || jsx === JsxEmit.ReactJSXDev)) return {};
283
+ return defineRuleListener({ JSXOpeningElement(node) {
284
+ let firstSpreadPropIndex = null;
285
+ for (const [index, prop] of node.attributes.entries()) {
286
+ if (prop.type === AST_NODE_TYPES.JSXSpreadAttribute) {
287
+ firstSpreadPropIndex ??= index;
288
+ continue;
289
+ }
290
+ if (firstSpreadPropIndex == null) continue;
291
+ if (prop.name.name === "key" && index > firstSpreadPropIndex) context.report({
292
+ messageId: "noKeyAfterSpread",
293
+ node: prop
294
+ });
295
+ }
296
+ } });
297
+ }
298
+
299
+ //#endregion
300
+ //#region src/rules/no-namespace/no-namespace.ts
301
+ const RULE_NAME$1 = "no-namespace";
302
+ var no_namespace_default = createRule({
303
+ meta: {
304
+ type: "problem",
305
+ docs: { description: "Disallow JSX namespace syntax, as React does not support them." },
306
+ messages: { noNamespace: "A React component '{{name}}' must not be in a namespace, as React does not support them." },
307
+ schema: []
308
+ },
309
+ name: RULE_NAME$1,
310
+ create: create$1,
311
+ defaultOptions: []
312
+ });
313
+ function create$1(context) {
314
+ return defineRuleListener({ JSXElement(node) {
315
+ const name = getElementFullType(node);
316
+ if (typeof name !== "string" || !name.includes(":")) return;
317
+ context.report({
318
+ data: { name },
319
+ messageId: "noNamespace",
320
+ node: node.openingElement.name
321
+ });
322
+ } });
323
+ }
324
+
325
+ //#endregion
326
+ //#region src/rules/no-useless-fragment/no-useless-fragment.ts
327
+ const RULE_NAME = "no-useless-fragment";
328
+ const defaultOptions = [{
329
+ allowEmptyFragment: false,
330
+ allowExpressions: true
331
+ }];
332
+ const schema = [{
333
+ type: "object",
334
+ additionalProperties: false,
335
+ properties: {
336
+ allowEmptyFragment: {
337
+ type: "boolean",
338
+ description: "Allow empty fragments"
339
+ },
340
+ allowExpressions: {
341
+ type: "boolean",
342
+ description: "Allow fragments with a single expression child"
343
+ }
344
+ }
345
+ }];
346
+ var no_useless_fragment_default = createRule({
347
+ meta: {
348
+ type: "suggestion",
349
+ defaultOptions: [...defaultOptions],
350
+ docs: { description: "Disallows useless fragment elements." },
351
+ fixable: "code",
352
+ messages: { default: "A fragment {{reason}} is useless." },
353
+ schema
354
+ },
355
+ name: RULE_NAME,
356
+ create,
357
+ defaultOptions
358
+ });
359
+ function create(context, [option]) {
360
+ const { allowEmptyFragment = false, allowExpressions = true } = option;
361
+ const jsxConfig = getJsxConfig(context);
362
+ /**
363
+ * Whether the fragment has too few meaningful children to justify its
364
+ * existence (the "contains less than two children" reason).
365
+ * @param node
366
+ */
367
+ function isContentUseless(node) {
368
+ if (node.children.length === 0) return !allowEmptyFragment;
369
+ const insideJsx = ast.isJSXElementLike(node.parent);
370
+ if (!allowExpressions) {
371
+ if (insideJsx) return true;
372
+ if (node.children.length === 1) return true;
373
+ }
374
+ if (allowExpressions && !insideJsx && node.children.length === 1) {
375
+ const child = node.children[0];
376
+ if (child != null && child.type === AST_NODE_TYPES.JSXText) return false;
377
+ }
378
+ const meaningful = getChildren(node);
379
+ if (meaningful.length === 0) return true;
380
+ if (meaningful.length === 1 && meaningful[0].type !== AST_NODE_TYPES.JSXExpressionContainer) return true;
381
+ return false;
382
+ }
383
+ /**
384
+ * Whether it is safe to auto-fix the fragment by unwrapping it.
385
+ * @param node
386
+ */
387
+ function isSafeToFix(node) {
388
+ if (ast.isJSXElementLike(node.parent)) return isHostElement(node.parent);
389
+ if (node.children.length === 0) return false;
390
+ return !node.children.some((child) => {
391
+ if (child.type === AST_NODE_TYPES.JSXExpressionContainer) return true;
392
+ if (child.type === AST_NODE_TYPES.JSXText) return !isWhitespaceText(child);
393
+ return false;
394
+ });
395
+ }
396
+ /**
397
+ * Build an autofix that unwraps the fragment, replacing it with its
398
+ * trimmed children text. Returns `null` when the fix is unsafe.
399
+ * @param node
400
+ */
401
+ function buildFix(node) {
402
+ if (!isSafeToFix(node)) return null;
403
+ return (fixer) => {
404
+ const childrenText = getChildrenSourceText(context, node);
405
+ return fixer.replaceText(node, trimLikeReact(childrenText));
406
+ };
407
+ }
408
+ /**
409
+ * Inspect a fragment node and report if it is useless.
410
+ *
411
+ * A fragment may be reported for **two independent reasons** on the same
412
+ * node (e.g. `<p><>foo</></p>` is both "placed inside a host component"
413
+ * and* "contains less than two children").
414
+ * @param node
415
+ */
416
+ function checkNode(node) {
417
+ if (isHostElement(node.parent)) context.report({
418
+ data: { reason: "placed inside a host component" },
419
+ fix: buildFix(node),
420
+ messageId: "default",
421
+ node
422
+ });
423
+ if (isContentUseless(node)) context.report({
424
+ data: { reason: "contains less than two children" },
425
+ fix: buildFix(node),
426
+ messageId: "default",
427
+ node
428
+ });
429
+ }
430
+ return defineRuleListener({
431
+ JSXElement(node) {
432
+ if (!isFragmentElement(node, jsxConfig.jsxFragmentFactory)) return;
433
+ if (hasAnyAttribute(context, node, ["key", "ref"])) return;
434
+ checkNode(node);
435
+ },
436
+ JSXFragment(node) {
437
+ checkNode(node);
438
+ }
439
+ });
440
+ }
441
+
442
+ //#endregion
443
+ //#region src/plugin.ts
444
+ const plugin = {
445
+ meta: {
446
+ name: name$2,
447
+ version
448
+ },
449
+ rules: {
450
+ "no-children-prop": no_children_prop_default,
451
+ "no-children-prop-with-children": no_children_prop_with_children_default,
452
+ "no-comment-textnodes": no_comment_textnodes_default,
453
+ "no-deoptimization": no_deoptimization_default,
454
+ "no-namespace": no_namespace_default,
455
+ "no-useless-fragment": no_useless_fragment_default
456
+ }
457
+ };
458
+
459
+ //#endregion
460
+ //#region src/configs/recommended.ts
461
+ var recommended_exports = /* @__PURE__ */ __exportAll({
462
+ name: () => name$1,
463
+ plugins: () => plugins$1,
464
+ rules: () => rules$1,
465
+ settings: () => settings$1
466
+ });
467
+ const name$1 = "react-jsx/recommended";
468
+ const rules$1 = {
469
+ "react-jsx/no-children-prop": "warn",
470
+ "react-jsx/no-comment-textnodes": "warn",
471
+ "react-jsx/no-deoptimization": "error",
472
+ "react-jsx/no-namespace": "error"
473
+ };
474
+ const plugins$1 = { "react-jsx": plugin };
475
+ const settings$1 = { "react-x": DEFAULT_ESLINT_REACT_SETTINGS };
476
+
477
+ //#endregion
478
+ //#region src/configs/strict.ts
479
+ var strict_exports = /* @__PURE__ */ __exportAll({
480
+ name: () => name,
481
+ plugins: () => plugins,
482
+ rules: () => rules,
483
+ settings: () => settings
484
+ });
485
+ const name = "react-jsx/strict";
486
+ const rules = {
487
+ ...rules$1,
488
+ "react-jsx/no-children-prop": "error",
489
+ "react-jsx/no-useless-fragment": "warn"
490
+ };
491
+ const plugins = { ...plugins$1 };
492
+ const settings = { ...settings$1 };
493
+
494
+ //#endregion
495
+ //#region src/index.ts
496
+ const finalPlugin = {
497
+ ...plugin,
498
+ configs: {
499
+ ["recommended"]: recommended_exports,
500
+ ["strict"]: strict_exports
501
+ }
502
+ };
503
+
504
+ //#endregion
505
+ export { finalPlugin as default };
package/package.json CHANGED
@@ -1,12 +1,78 @@
1
1
  {
2
2
  "name": "eslint-plugin-react-jsx",
3
- "module": "index.ts",
4
- "version": "0.0.0",
3
+ "version": "4.0.0-beta.2",
4
+ "description": "ESLint React's ESLint plugin for React Flavored JSX rules.",
5
+ "keywords": [
6
+ "react",
7
+ "jsx",
8
+ "eslint",
9
+ "eslint-react",
10
+ "eslint-plugin",
11
+ "eslint-plugin-react-jsx"
12
+ ],
13
+ "homepage": "https://github.com/Rel1cx/eslint-react",
14
+ "bugs": {
15
+ "url": "https://github.com/Rel1cx/eslint-react/issues"
16
+ },
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/Rel1cx/eslint-react.git",
20
+ "directory": "packages/plugins/eslint-plugin-react-jsx"
21
+ },
22
+ "license": "MIT",
23
+ "author": "Rel1cx",
24
+ "sideEffects": false,
5
25
  "type": "module",
26
+ "exports": {
27
+ ".": {
28
+ "types": "./dist/index.d.ts",
29
+ "import": "./dist/index.js"
30
+ },
31
+ "./package.json": "./package.json"
32
+ },
33
+ "main": "./dist/index.js",
34
+ "module": "./dist/index.js",
35
+ "types": "./dist/index.d.ts",
36
+ "files": [
37
+ "dist",
38
+ "./package.json"
39
+ ],
40
+ "dependencies": {
41
+ "@typescript-eslint/scope-manager": "^8.57.2",
42
+ "@typescript-eslint/types": "^8.57.2",
43
+ "@typescript-eslint/utils": "^8.57.2",
44
+ "compare-versions": "^6.1.1",
45
+ "ts-pattern": "^5.9.0",
46
+ "@eslint-react/ast": "4.0.0-beta.2",
47
+ "@eslint-react/core": "4.0.0-beta.2",
48
+ "@eslint-react/shared": "4.0.0-beta.2",
49
+ "@eslint-react/var": "4.0.0-beta.2",
50
+ "@eslint-react/jsx": "4.0.0-beta.2"
51
+ },
6
52
  "devDependencies": {
7
- "@types/bun": "latest"
53
+ "@types/react": "^19.2.14",
54
+ "@types/react-dom": "^19.2.3",
55
+ "eslint": "^10.1.0",
56
+ "tsdown": "^0.21.5",
57
+ "@local/eff": "3.0.0-beta.72",
58
+ "@local/configs": "0.0.0"
8
59
  },
9
60
  "peerDependencies": {
10
- "typescript": "^5"
61
+ "eslint": "^10.0.0",
62
+ "typescript": "*"
63
+ },
64
+ "engines": {
65
+ "node": ">=22.0.0"
66
+ },
67
+ "publishConfig": {
68
+ "access": "public"
69
+ },
70
+ "inlinedDependencies": {
71
+ "@local/eff": "workspace:*"
72
+ },
73
+ "scripts": {
74
+ "build": "tsdown",
75
+ "lint:publish": "publint",
76
+ "lint:ts": "tsl"
11
77
  }
12
78
  }
package/bun.lock DELETED
@@ -1,26 +0,0 @@
1
- {
2
- "lockfileVersion": 1,
3
- "configVersion": 1,
4
- "workspaces": {
5
- "": {
6
- "name": "eslint-plugin-react-jsx",
7
- "devDependencies": {
8
- "@types/bun": "latest",
9
- },
10
- "peerDependencies": {
11
- "typescript": "^5",
12
- },
13
- },
14
- },
15
- "packages": {
16
- "@types/bun": ["@types/bun@1.3.10", "", { "dependencies": { "bun-types": "1.3.10" } }, "sha512-0+rlrUrOrTSskibryHbvQkDOWRJwJZqZlxrUs1u4oOoTln8+WIXBPmAuCF35SWB2z4Zl3E84Nl/D0P7803nigQ=="],
17
-
18
- "@types/node": ["@types/node@25.5.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw=="],
19
-
20
- "bun-types": ["bun-types@1.3.10", "", { "dependencies": { "@types/node": "*" } }, "sha512-tcpfCCl6XWo6nCVnpcVrxQ+9AYN1iqMIzgrSKYMB/fjLtV2eyAVEg7AxQJuCq/26R6HpKWykQXuSOq/21RYcbg=="],
21
-
22
- "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
23
-
24
- "undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="],
25
- }
26
- }
package/index.ts DELETED
@@ -1 +0,0 @@
1
- console.log("Hello via Bun!");
package/tsconfig.json DELETED
@@ -1,29 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- // Environment setup & latest features
4
- "lib": ["ESNext"],
5
- "target": "ESNext",
6
- "module": "Preserve",
7
- "moduleDetection": "force",
8
- "jsx": "react-jsx",
9
- "allowJs": true,
10
-
11
- // Bundler mode
12
- "moduleResolution": "bundler",
13
- "allowImportingTsExtensions": true,
14
- "verbatimModuleSyntax": true,
15
- "noEmit": true,
16
-
17
- // Best practices
18
- "strict": true,
19
- "skipLibCheck": true,
20
- "noFallthroughCasesInSwitch": true,
21
- "noUncheckedIndexedAccess": true,
22
- "noImplicitOverride": true,
23
-
24
- // Some stricter flags (disabled by default)
25
- "noUnusedLocals": false,
26
- "noUnusedParameters": false,
27
- "noPropertyAccessFromIndexSignature": false
28
- }
29
- }