@conorroberts/utils 0.0.59 → 0.0.60

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 (47) hide show
  1. package/package.json +1 -45
  2. package/dist/env.d.mts +0 -19
  3. package/dist/env.mjs +0 -32
  4. package/dist/env.mjs.map +0 -1
  5. package/dist/images.d.mts +0 -101
  6. package/dist/images.mjs +0 -130
  7. package/dist/images.mjs.map +0 -1
  8. package/dist/oxlint/config.json +0 -71
  9. package/dist/oxlint/index.d.mts +0 -7
  10. package/dist/oxlint/index.mjs +0 -35
  11. package/dist/oxlint/index.mjs.map +0 -1
  12. package/dist/oxlint/jsx-component-pascal-case.d.mts +0 -17
  13. package/dist/oxlint/jsx-component-pascal-case.mjs +0 -155
  14. package/dist/oxlint/jsx-component-pascal-case.mjs.map +0 -1
  15. package/dist/oxlint/no-component-date-instantiation.d.mts +0 -19
  16. package/dist/oxlint/no-component-date-instantiation.mjs +0 -156
  17. package/dist/oxlint/no-component-date-instantiation.mjs.map +0 -1
  18. package/dist/oxlint/no-emoji.d.mts +0 -8
  19. package/dist/oxlint/no-emoji.mjs +0 -85
  20. package/dist/oxlint/no-emoji.mjs.map +0 -1
  21. package/dist/oxlint/no-finally.d.mts +0 -8
  22. package/dist/oxlint/no-finally.mjs +0 -28
  23. package/dist/oxlint/no-finally.mjs.map +0 -1
  24. package/dist/oxlint/no-function-call-in-jsx.d.mts +0 -11
  25. package/dist/oxlint/no-function-call-in-jsx.mjs +0 -70
  26. package/dist/oxlint/no-function-call-in-jsx.mjs.map +0 -1
  27. package/dist/oxlint/no-inline-components.d.mts +0 -36
  28. package/dist/oxlint/no-inline-components.mjs +0 -374
  29. package/dist/oxlint/no-inline-components.mjs.map +0 -1
  30. package/dist/oxlint/no-react-namespace.d.mts +0 -8
  31. package/dist/oxlint/no-react-namespace.mjs +0 -71
  32. package/dist/oxlint/no-react-namespace.mjs.map +0 -1
  33. package/dist/oxlint/no-switch-plugin.d.mts +0 -9
  34. package/dist/oxlint/no-switch-plugin.mjs +0 -27
  35. package/dist/oxlint/no-switch-plugin.mjs.map +0 -1
  36. package/dist/oxlint/no-top-level-let.d.mts +0 -8
  37. package/dist/oxlint/no-top-level-let.mjs +0 -62
  38. package/dist/oxlint/no-top-level-let.mjs.map +0 -1
  39. package/dist/oxlint/no-type-cast.d.mts +0 -8
  40. package/dist/oxlint/no-type-cast.mjs +0 -45
  41. package/dist/oxlint/no-type-cast.mjs.map +0 -1
  42. package/dist/oxlint/pretty-props.d.mts +0 -11
  43. package/dist/oxlint/pretty-props.mjs +0 -127
  44. package/dist/oxlint/pretty-props.mjs.map +0 -1
  45. package/dist/react.d.mts +0 -73
  46. package/dist/react.mjs +0 -113
  47. package/dist/react.mjs.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"jsx-component-pascal-case.mjs","names":[],"sources":["../../src/oxlint-plugins/jsx-component-pascal-case.js"],"sourcesContent":["import { defineRule } from \"oxlint\";\n\n/**\n * @typedef {import(\"oxlint\").Context} RuleContext\n * @typedef {import(\"oxlint\").ESTree.Node} ESTNode\n * @typedef {import(\"oxlint\").ESTree.Expression} ESTExpression\n * @typedef {import(\"oxlint\").ESTree.ReturnStatement} ReturnStatementNode\n * @typedef {import(\"oxlint\").ESTree.Function | import(\"oxlint\").ESTree.ArrowFunctionExpression} FunctionLikeNode\n */\n\n/**\n * @typedef {object} FunctionContext\n * @property {FunctionLikeNode} node\n * @property {string} name\n * @property {boolean} returnsJsx\n */\n\nconst JSX_NODE_TYPES = new Set([\"JSXElement\", \"JSXFragment\"]);\nconst FUNCTION_NODE_TYPES = new Set([\"FunctionDeclaration\", \"FunctionExpression\", \"ArrowFunctionExpression\"]);\n\n/**\n * @param {unknown} node\n * @returns {node is ESTNode & { type: string }}\n */\nconst isNode = (node) => Boolean(node && typeof node === \"object\" && \"type\" in node);\n\n/**\n * @param {unknown} node\n * @returns {node is FunctionLikeNode}\n */\nconst isFunctionLike = (node) => isNode(node) && FUNCTION_NODE_TYPES.has(node.type);\n\n/**\n * @param {unknown} name\n * @returns {name is string}\n */\nconst isPascalCase = (name) => typeof name === \"string\" && /^[A-Z]/.test(name);\n\n/**\n * Check if a name is a valid higher-order component name (starts with \"with\")\n * @param {unknown} name\n * @returns {name is string}\n */\nconst isHOCName = (name) => typeof name === \"string\" && /^with[A-Z]/.test(name);\n\n/**\n * @param {FunctionLikeNode} node\n */\nconst getFunctionName = (node) => {\n if (node.type === \"FunctionDeclaration\" && node.id && node.id.type === \"Identifier\") {\n return node.id.name;\n }\n\n if ((node.type === \"FunctionExpression\" || node.type === \"ArrowFunctionExpression\") && node.id) {\n if (node.id.type === \"Identifier\") return node.id.name;\n }\n\n const parent = node.parent;\n if (!parent || !isNode(parent)) return \"\";\n\n if (parent.type === \"VariableDeclarator\") {\n return parent.id && parent.id.type === \"Identifier\" ? parent.id.name : \"\";\n }\n\n if (parent.type === \"AssignmentExpression\") {\n return parent.left && parent.left.type === \"Identifier\" ? parent.left.name : \"\";\n }\n\n // Don't enforce naming for functions used as object property values or JSX props\n // These are often callbacks or configuration options, not standalone components\n if (parent.type === \"Property\" || parent.type === \"MethodDefinition\") {\n return \"\";\n }\n\n // Handle functions passed as arguments to calls (e.g., useCallback, useMemo)\n if (parent.type === \"CallExpression\") {\n const callParent = parent.parent;\n if (callParent && isNode(callParent)) {\n if (callParent.type === \"VariableDeclarator\") {\n return callParent.id && callParent.id.type === \"Identifier\" ? callParent.id.name : \"\";\n }\n if (callParent.type === \"AssignmentExpression\") {\n return callParent.left && callParent.left.type === \"Identifier\" ? callParent.left.name : \"\";\n }\n }\n }\n\n return \"\";\n};\n\n/**\n * @param {ESTExpression | null | undefined} root\n */\nconst expressionContainsJsx = (root) => {\n if (!root || !isNode(root)) return false;\n\n const stack = [root];\n\n while (stack.length > 0) {\n const current = stack.pop();\n if (!current || !isNode(current)) continue;\n\n if (JSX_NODE_TYPES.has(current.type)) {\n return true;\n }\n\n if (FUNCTION_NODE_TYPES.has(current.type) && current !== root) {\n continue;\n }\n\n for (const key of Object.keys(current)) {\n if (key === \"parent\") continue;\n\n const value = current[key];\n if (!value) continue;\n\n if (Array.isArray(value)) {\n for (const element of value) {\n if (isNode(element)) {\n stack.push(element);\n }\n }\n } else if (isNode(value)) {\n stack.push(value);\n }\n }\n }\n\n return false;\n};\n\nconst rule = defineRule({\n meta: {\n type: \"problem\",\n docs: {\n description: \"Enforce PascalCase naming for functions that return JSX elements (components).\",\n recommended: false,\n },\n schema: [],\n },\n\n createOnce(context) {\n /** @type {FunctionContext[]} */\n const functionStack = [];\n\n const currentFunction = () => functionStack[functionStack.length - 1] ?? null;\n\n /**\n * @param {FunctionLikeNode} node\n */\n const enterFunction = (node) => {\n const name = getFunctionName(node);\n\n /** @type {FunctionContext} */\n const fnCtx = {\n node,\n name,\n returnsJsx: false,\n };\n\n functionStack.push(fnCtx);\n\n if (node.type === \"ArrowFunctionExpression\" && node.body && node.body.type !== \"BlockStatement\") {\n if (expressionContainsJsx(node.body)) {\n fnCtx.returnsJsx = true;\n }\n }\n };\n\n const exitFunction = () => {\n const fnCtx = functionStack.pop();\n if (!fnCtx) return;\n\n // Allow PascalCase or HOC naming (withXxx)\n if (fnCtx.returnsJsx && fnCtx.name && !isPascalCase(fnCtx.name) && !isHOCName(fnCtx.name)) {\n context.report({\n node: fnCtx.node,\n message: `Function '${fnCtx.name}' returns JSX and should use PascalCase naming (e.g., '${fnCtx.name.charAt(0).toUpperCase()}${fnCtx.name.slice(1)}').`,\n });\n }\n };\n\n /** @param {ReturnStatementNode} node */\n const handleReturnStatement = (node) => {\n const fnCtx = currentFunction();\n if (!fnCtx) return;\n\n const argument = node.argument;\n if (!argument || isFunctionLike(argument)) return;\n\n if (expressionContainsJsx(argument)) {\n fnCtx.returnsJsx = true;\n }\n };\n\n return /** @type {import(\"oxlint\").VisitorWithHooks} */ ({\n FunctionDeclaration(node) {\n if (isFunctionLike(node)) enterFunction(node);\n },\n \"FunctionDeclaration:exit\": exitFunction,\n FunctionExpression(node) {\n if (isFunctionLike(node)) enterFunction(node);\n },\n \"FunctionExpression:exit\": exitFunction,\n ArrowFunctionExpression(node) {\n if (isFunctionLike(node)) enterFunction(node);\n },\n \"ArrowFunctionExpression:exit\": exitFunction,\n ReturnStatement(node) {\n if (node.type === \"ReturnStatement\") handleReturnStatement(node);\n },\n });\n },\n});\n\nexport const jsxComponentPascalCaseRule = rule;\n\n"],"mappings":"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"}
@@ -1,19 +0,0 @@
1
- import * as oxlint15 from "oxlint";
2
-
3
- //#region src/oxlint-plugins/no-component-date-instantiation.d.ts
4
- declare const noComponentDateInstantiationRule: oxlint15.Rule;
5
- type RuleContext = oxlint15.Context;
6
- type ESTNode = oxlint15.ESTree.Node;
7
- type NewExpressionNode = oxlint15.ESTree.NewExpression;
8
- type ReturnStatementNode = oxlint15.ESTree.ReturnStatement;
9
- type FunctionLikeNode = oxlint15.ESTree.Function | oxlint15.ESTree.ArrowFunctionExpression;
10
- type FunctionContext = {
11
- node: FunctionLikeNode;
12
- parent: FunctionContext | null;
13
- name: string;
14
- returnsJsx: boolean;
15
- dateInstantiations: NewExpressionNode[];
16
- };
17
- //#endregion
18
- export { ESTNode, FunctionContext, FunctionLikeNode, NewExpressionNode, ReturnStatementNode, RuleContext, noComponentDateInstantiationRule };
19
- //# sourceMappingURL=no-component-date-instantiation.d.mts.map
@@ -1,156 +0,0 @@
1
- import { defineRule } from "oxlint";
2
-
3
- //#region src/oxlint-plugins/no-component-date-instantiation.js
4
- /**
5
- * @typedef {import("oxlint").Context} RuleContext
6
- * @typedef {import("oxlint").ESTree.Node} ESTNode
7
- * @typedef {import("oxlint").ESTree.NewExpression} NewExpressionNode
8
- * @typedef {import("oxlint").ESTree.ReturnStatement} ReturnStatementNode
9
- * @typedef {import("oxlint").ESTree.Function | import("oxlint").ESTree.ArrowFunctionExpression} FunctionLikeNode
10
- */
11
- /**
12
- * @typedef {object} FunctionContext
13
- * @property {FunctionLikeNode} node
14
- * @property {FunctionContext | null} parent
15
- * @property {string} name
16
- * @property {boolean} returnsJsx
17
- * @property {NewExpressionNode[]} dateInstantiations
18
- */
19
- const FUNCTION_NODE_TYPES = new Set([
20
- "FunctionDeclaration",
21
- "FunctionExpression",
22
- "ArrowFunctionExpression"
23
- ]);
24
- /**
25
- * @param {unknown} node
26
- * @returns {node is ESTNode & { type: string }}
27
- */
28
- const isNode = (node) => Boolean(node && typeof node === "object" && "type" in node);
29
- /**
30
- * @param {unknown} node
31
- * @returns {node is FunctionLikeNode}
32
- */
33
- const isFunctionLike = (node) => isNode(node) && FUNCTION_NODE_TYPES.has(node.type);
34
- /**
35
- * Check if a function name follows React component naming convention (PascalCase)
36
- * @param {unknown} name
37
- * @returns {name is string}
38
- */
39
- const isComponentName = (name) => typeof name === "string" && /^[A-Z]/.test(name);
40
- /**
41
- * Get the name of a function node
42
- * @param {FunctionLikeNode} node
43
- * @returns {string}
44
- */
45
- const getFunctionName = (node) => {
46
- if (node.type === "FunctionDeclaration" && node.id && node.id.type === "Identifier") return node.id.name;
47
- if ((node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression") && node.id) {
48
- if (node.id.type === "Identifier") return node.id.name;
49
- }
50
- const parent = node.parent;
51
- if (!parent || !isNode(parent)) return "";
52
- if (parent.type === "VariableDeclarator") return parent.id && parent.id.type === "Identifier" ? parent.id.name : "";
53
- if (parent.type === "AssignmentExpression") return parent.left && parent.left.type === "Identifier" ? parent.left.name : "";
54
- if (parent.type === "Property" || parent.type === "MethodDefinition") return parent.key && parent.key.type === "Identifier" ? parent.key.name : "";
55
- return "";
56
- };
57
- /**
58
- * Check if a node is a JSX element or fragment
59
- * @param {ESTNode | null | undefined} node
60
- * @returns {boolean}
61
- */
62
- const isJSXNode = (node) => {
63
- if (!node || !isNode(node)) return false;
64
- return node.type === "JSXElement" || node.type === "JSXFragment";
65
- };
66
- /**
67
- * Check if a NewExpression is creating a Date instance
68
- * @param {NewExpressionNode} node
69
- * @returns {boolean}
70
- */
71
- const isDateInstantiation = (node) => {
72
- if (node.callee.type === "Identifier" && node.callee.name === "Date") return true;
73
- return false;
74
- };
75
- const rule = defineRule({
76
- meta: {
77
- type: "problem",
78
- docs: {
79
- description: "Disallow Date instantiation in the top scope of React components. Date instances declared on every render are bad because they change every render.",
80
- recommended: true
81
- },
82
- schema: []
83
- },
84
- createOnce(context) {
85
- /** @type {FunctionContext[]} */
86
- const functionStack = [];
87
- const currentFunction = () => functionStack[functionStack.length - 1] ?? null;
88
- /**
89
- * @param {FunctionLikeNode} node
90
- */
91
- const enterFunction = (node) => {
92
- /** @type {FunctionContext} */
93
- const fnCtx = {
94
- node,
95
- parent: currentFunction(),
96
- name: getFunctionName(node),
97
- returnsJsx: false,
98
- dateInstantiations: []
99
- };
100
- functionStack.push(fnCtx);
101
- if (node.type === "ArrowFunctionExpression" && node.body && node.body.type !== "BlockStatement") {
102
- if (isJSXNode(node.body)) fnCtx.returnsJsx = true;
103
- }
104
- };
105
- const exitFunction = () => {
106
- const fnCtx = functionStack.pop();
107
- if (!fnCtx) return;
108
- if (!fnCtx.returnsJsx) return;
109
- if (!isComponentName(fnCtx.name)) return;
110
- for (const dateNode of fnCtx.dateInstantiations) context.report({
111
- node: dateNode,
112
- message: `Avoid instantiating Date in the top scope of component '${fnCtx.name}'. Date instances change on every render. Move it inside an effect, event handler, or use useMemo/useCallback.`
113
- });
114
- };
115
- /** @param {ReturnStatementNode} node */
116
- const handleReturnStatement = (node) => {
117
- const fnCtx = currentFunction();
118
- if (!fnCtx) return;
119
- const argument = node.argument;
120
- if (!argument) return;
121
- if (isJSXNode(argument)) fnCtx.returnsJsx = true;
122
- };
123
- /** @param {NewExpressionNode} node */
124
- const handleNewExpression = (node) => {
125
- if (!isDateInstantiation(node)) return;
126
- const fnCtx = currentFunction();
127
- if (!fnCtx) return;
128
- fnCtx.dateInstantiations.push(node);
129
- };
130
- return {
131
- FunctionDeclaration(node) {
132
- if (isFunctionLike(node)) enterFunction(node);
133
- },
134
- "FunctionDeclaration:exit": exitFunction,
135
- FunctionExpression(node) {
136
- if (isFunctionLike(node)) enterFunction(node);
137
- },
138
- "FunctionExpression:exit": exitFunction,
139
- ArrowFunctionExpression(node) {
140
- if (isFunctionLike(node)) enterFunction(node);
141
- },
142
- "ArrowFunctionExpression:exit": exitFunction,
143
- ReturnStatement(node) {
144
- if (node.type === "ReturnStatement") handleReturnStatement(node);
145
- },
146
- NewExpression(node) {
147
- if (node.type === "NewExpression") handleNewExpression(node);
148
- }
149
- };
150
- }
151
- });
152
- const noComponentDateInstantiationRule = rule;
153
-
154
- //#endregion
155
- export { noComponentDateInstantiationRule };
156
- //# sourceMappingURL=no-component-date-instantiation.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"no-component-date-instantiation.mjs","names":[],"sources":["../../src/oxlint-plugins/no-component-date-instantiation.js"],"sourcesContent":["import { defineRule } from \"oxlint\";\n\n/**\n * @typedef {import(\"oxlint\").Context} RuleContext\n * @typedef {import(\"oxlint\").ESTree.Node} ESTNode\n * @typedef {import(\"oxlint\").ESTree.NewExpression} NewExpressionNode\n * @typedef {import(\"oxlint\").ESTree.ReturnStatement} ReturnStatementNode\n * @typedef {import(\"oxlint\").ESTree.Function | import(\"oxlint\").ESTree.ArrowFunctionExpression} FunctionLikeNode\n */\n\n/**\n * @typedef {object} FunctionContext\n * @property {FunctionLikeNode} node\n * @property {FunctionContext | null} parent\n * @property {string} name\n * @property {boolean} returnsJsx\n * @property {NewExpressionNode[]} dateInstantiations\n */\n\nconst FUNCTION_NODE_TYPES = new Set([\"FunctionDeclaration\", \"FunctionExpression\", \"ArrowFunctionExpression\"]);\n\n/**\n * @param {unknown} node\n * @returns {node is ESTNode & { type: string }}\n */\nconst isNode = (node) => Boolean(node && typeof node === \"object\" && \"type\" in node);\n\n/**\n * @param {unknown} node\n * @returns {node is FunctionLikeNode}\n */\nconst isFunctionLike = (node) => isNode(node) && FUNCTION_NODE_TYPES.has(node.type);\n\n/**\n * Check if a function name follows React component naming convention (PascalCase)\n * @param {unknown} name\n * @returns {name is string}\n */\nconst isComponentName = (name) => typeof name === \"string\" && /^[A-Z]/.test(name);\n\n/**\n * Get the name of a function node\n * @param {FunctionLikeNode} node\n * @returns {string}\n */\nconst getFunctionName = (node) => {\n if (node.type === \"FunctionDeclaration\" && node.id && node.id.type === \"Identifier\") {\n return node.id.name;\n }\n\n if ((node.type === \"FunctionExpression\" || node.type === \"ArrowFunctionExpression\") && node.id) {\n if (node.id.type === \"Identifier\") return node.id.name;\n }\n\n const parent = node.parent;\n if (!parent || !isNode(parent)) return \"\";\n\n if (parent.type === \"VariableDeclarator\") {\n return parent.id && parent.id.type === \"Identifier\" ? parent.id.name : \"\";\n }\n\n if (parent.type === \"AssignmentExpression\") {\n return parent.left && parent.left.type === \"Identifier\" ? parent.left.name : \"\";\n }\n\n if (parent.type === \"Property\" || parent.type === \"MethodDefinition\") {\n return parent.key && parent.key.type === \"Identifier\" ? parent.key.name : \"\";\n }\n\n return \"\";\n};\n\n/**\n * Check if a node is a JSX element or fragment\n * @param {ESTNode | null | undefined} node\n * @returns {boolean}\n */\nconst isJSXNode = (node) => {\n if (!node || !isNode(node)) return false;\n return node.type === \"JSXElement\" || node.type === \"JSXFragment\";\n};\n\n/**\n * Check if a NewExpression is creating a Date instance\n * @param {NewExpressionNode} node\n * @returns {boolean}\n */\nconst isDateInstantiation = (node) => {\n if (node.callee.type === \"Identifier\" && node.callee.name === \"Date\") {\n return true;\n }\n return false;\n};\n\nconst rule = defineRule({\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Disallow Date instantiation in the top scope of React components. Date instances declared on every render are bad because they change every render.\",\n recommended: true,\n },\n schema: [],\n },\n createOnce(context) {\n /** @type {FunctionContext[]} */\n const functionStack = [];\n\n const currentFunction = () => functionStack[functionStack.length - 1] ?? null;\n\n /**\n * @param {FunctionLikeNode} node\n */\n const enterFunction = (node) => {\n const parent = currentFunction();\n /** @type {FunctionContext} */\n const fnCtx = {\n node,\n parent,\n name: getFunctionName(node),\n returnsJsx: false,\n dateInstantiations: [],\n };\n\n functionStack.push(fnCtx);\n\n // Check for arrow functions with expression body that returns JSX\n if (node.type === \"ArrowFunctionExpression\" && node.body && node.body.type !== \"BlockStatement\") {\n if (isJSXNode(node.body)) {\n fnCtx.returnsJsx = true;\n }\n }\n };\n\n const exitFunction = () => {\n const fnCtx = functionStack.pop();\n if (!fnCtx) return;\n\n // Only report if this is a React component (PascalCase name + returns JSX)\n if (!fnCtx.returnsJsx) return;\n if (!isComponentName(fnCtx.name)) return;\n\n // Report all Date instantiations in the top scope of this component\n for (const dateNode of fnCtx.dateInstantiations) {\n context.report({\n node: dateNode,\n message: `Avoid instantiating Date in the top scope of component '${fnCtx.name}'. Date instances change on every render. Move it inside an effect, event handler, or use useMemo/useCallback.`,\n });\n }\n };\n\n /** @param {ReturnStatementNode} node */\n const handleReturnStatement = (node) => {\n const fnCtx = currentFunction();\n if (!fnCtx) return;\n\n const argument = node.argument;\n if (!argument) return;\n\n if (isJSXNode(argument)) {\n fnCtx.returnsJsx = true;\n }\n };\n\n /** @param {NewExpressionNode} node */\n const handleNewExpression = (node) => {\n if (!isDateInstantiation(node)) return;\n\n const fnCtx = currentFunction();\n if (!fnCtx) return;\n\n // Record this Date instantiation - we'll check if it's in top scope when the function exits\n fnCtx.dateInstantiations.push(node);\n };\n\n return /** @type {import(\"oxlint\").VisitorWithHooks} */ ({\n FunctionDeclaration(node) {\n if (isFunctionLike(node)) enterFunction(node);\n },\n \"FunctionDeclaration:exit\": exitFunction,\n FunctionExpression(node) {\n if (isFunctionLike(node)) enterFunction(node);\n },\n \"FunctionExpression:exit\": exitFunction,\n ArrowFunctionExpression(node) {\n if (isFunctionLike(node)) enterFunction(node);\n },\n \"ArrowFunctionExpression:exit\": exitFunction,\n ReturnStatement(node) {\n if (node.type === \"ReturnStatement\") handleReturnStatement(node);\n },\n NewExpression(node) {\n if (node.type === \"NewExpression\") handleNewExpression(node);\n },\n });\n },\n});\n\nexport const noComponentDateInstantiationRule = rule;\n\n"],"mappings":";;;;;;;;;;;;;;;;;;AAmBA,MAAM,sBAAsB,IAAI,IAAI;CAAC;CAAuB;CAAsB;CAA0B,CAAC;;;;;AAM7G,MAAM,UAAU,SAAS,QAAQ,QAAQ,OAAO,SAAS,YAAY,UAAU,KAAK;;;;;AAMpF,MAAM,kBAAkB,SAAS,OAAO,KAAK,IAAI,oBAAoB,IAAI,KAAK,KAAK;;;;;;AAOnF,MAAM,mBAAmB,SAAS,OAAO,SAAS,YAAY,SAAS,KAAK,KAAK;;;;;;AAOjF,MAAM,mBAAmB,SAAS;AAChC,KAAI,KAAK,SAAS,yBAAyB,KAAK,MAAM,KAAK,GAAG,SAAS,aACrE,QAAO,KAAK,GAAG;AAGjB,MAAK,KAAK,SAAS,wBAAwB,KAAK,SAAS,8BAA8B,KAAK,IAC1F;MAAI,KAAK,GAAG,SAAS,aAAc,QAAO,KAAK,GAAG;;CAGpD,MAAM,SAAS,KAAK;AACpB,KAAI,CAAC,UAAU,CAAC,OAAO,OAAO,CAAE,QAAO;AAEvC,KAAI,OAAO,SAAS,qBAClB,QAAO,OAAO,MAAM,OAAO,GAAG,SAAS,eAAe,OAAO,GAAG,OAAO;AAGzE,KAAI,OAAO,SAAS,uBAClB,QAAO,OAAO,QAAQ,OAAO,KAAK,SAAS,eAAe,OAAO,KAAK,OAAO;AAG/E,KAAI,OAAO,SAAS,cAAc,OAAO,SAAS,mBAChD,QAAO,OAAO,OAAO,OAAO,IAAI,SAAS,eAAe,OAAO,IAAI,OAAO;AAG5E,QAAO;;;;;;;AAQT,MAAM,aAAa,SAAS;AAC1B,KAAI,CAAC,QAAQ,CAAC,OAAO,KAAK,CAAE,QAAO;AACnC,QAAO,KAAK,SAAS,gBAAgB,KAAK,SAAS;;;;;;;AAQrD,MAAM,uBAAuB,SAAS;AACpC,KAAI,KAAK,OAAO,SAAS,gBAAgB,KAAK,OAAO,SAAS,OAC5D,QAAO;AAET,QAAO;;AAGT,MAAM,OAAO,WAAW;CACtB,MAAM;EACJ,MAAM;EACN,MAAM;GACJ,aACE;GACF,aAAa;GACd;EACD,QAAQ,EAAE;EACX;CACD,WAAW,SAAS;;EAElB,MAAM,gBAAgB,EAAE;EAExB,MAAM,wBAAwB,cAAc,cAAc,SAAS,MAAM;;;;EAKzE,MAAM,iBAAiB,SAAS;;GAG9B,MAAM,QAAQ;IACZ;IACA,QAJa,iBAAiB;IAK9B,MAAM,gBAAgB,KAAK;IAC3B,YAAY;IACZ,oBAAoB,EAAE;IACvB;AAED,iBAAc,KAAK,MAAM;AAGzB,OAAI,KAAK,SAAS,6BAA6B,KAAK,QAAQ,KAAK,KAAK,SAAS,kBAC7E;QAAI,UAAU,KAAK,KAAK,CACtB,OAAM,aAAa;;;EAKzB,MAAM,qBAAqB;GACzB,MAAM,QAAQ,cAAc,KAAK;AACjC,OAAI,CAAC,MAAO;AAGZ,OAAI,CAAC,MAAM,WAAY;AACvB,OAAI,CAAC,gBAAgB,MAAM,KAAK,CAAE;AAGlC,QAAK,MAAM,YAAY,MAAM,mBAC3B,SAAQ,OAAO;IACb,MAAM;IACN,SAAS,2DAA2D,MAAM,KAAK;IAChF,CAAC;;;EAKN,MAAM,yBAAyB,SAAS;GACtC,MAAM,QAAQ,iBAAiB;AAC/B,OAAI,CAAC,MAAO;GAEZ,MAAM,WAAW,KAAK;AACtB,OAAI,CAAC,SAAU;AAEf,OAAI,UAAU,SAAS,CACrB,OAAM,aAAa;;;EAKvB,MAAM,uBAAuB,SAAS;AACpC,OAAI,CAAC,oBAAoB,KAAK,CAAE;GAEhC,MAAM,QAAQ,iBAAiB;AAC/B,OAAI,CAAC,MAAO;AAGZ,SAAM,mBAAmB,KAAK,KAAK;;AAGrC,SAAyD;GACvD,oBAAoB,MAAM;AACxB,QAAI,eAAe,KAAK,CAAE,eAAc,KAAK;;GAE/C,4BAA4B;GAC5B,mBAAmB,MAAM;AACvB,QAAI,eAAe,KAAK,CAAE,eAAc,KAAK;;GAE/C,2BAA2B;GAC3B,wBAAwB,MAAM;AAC5B,QAAI,eAAe,KAAK,CAAE,eAAc,KAAK;;GAE/C,gCAAgC;GAChC,gBAAgB,MAAM;AACpB,QAAI,KAAK,SAAS,kBAAmB,uBAAsB,KAAK;;GAElE,cAAc,MAAM;AAClB,QAAI,KAAK,SAAS,gBAAiB,qBAAoB,KAAK;;GAE/D;;CAEJ,CAAC;AAEF,MAAa,mCAAmC"}
@@ -1,8 +0,0 @@
1
- import * as oxlint13 from "oxlint";
2
-
3
- //#region src/oxlint-plugins/no-emoji.d.ts
4
- declare const noEmojiRule: oxlint13.Rule;
5
- type ESTNode = oxlint13.ESTree.Node;
6
- //#endregion
7
- export { ESTNode, noEmojiRule };
8
- //# sourceMappingURL=no-emoji.d.mts.map
@@ -1,85 +0,0 @@
1
- import { defineRule } from "oxlint";
2
-
3
- //#region src/oxlint-plugins/no-emoji.js
4
- /** @typedef {import("oxlint").ESTree.Node} ESTNode */
5
- /**
6
- * Regex pattern to match emojis
7
- * Covers most common emoji ranges in Unicode
8
- */
9
- const EMOJI_REGEX = /[\u{1F300}-\u{1F9FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}\u{1F000}-\u{1F02F}\u{1F0A0}-\u{1F0FF}\u{1F100}-\u{1F64F}\u{1F680}-\u{1F6FF}\u{1F900}-\u{1F9FF}\u{1FA00}-\u{1FA6F}\u{1FA70}-\u{1FAFF}\u{FE00}-\u{FE0F}\u{203C}\u{2049}\u{20E3}\u{2139}\u{2194}-\u{2199}\u{21A9}-\u{21AA}\u{231A}-\u{231B}\u{2328}\u{23CF}\u{23E9}-\u{23F3}\u{23F8}-\u{23FA}\u{24C2}\u{25AA}-\u{25AB}\u{25B6}\u{25C0}\u{25FB}-\u{25FE}\u{2600}-\u{2604}\u{260E}\u{2611}\u{2614}-\u{2615}\u{2618}\u{261D}\u{2620}\u{2622}-\u{2623}\u{2626}\u{262A}\u{262E}-\u{262F}\u{2638}-\u{263A}\u{2640}\u{2642}\u{2648}-\u{2653}\u{265F}-\u{2660}\u{2663}\u{2665}-\u{2666}\u{2668}\u{267B}\u{267E}-\u{267F}\u{2692}-\u{2697}\u{2699}\u{269B}-\u{269C}\u{26A0}-\u{26A1}\u{26A7}\u{26AA}-\u{26AB}\u{26B0}-\u{26B1}\u{26BD}-\u{26BE}\u{26C4}-\u{26C5}\u{26C8}\u{26CE}\u{26CF}\u{26D1}\u{26D3}-\u{26D4}\u{26E9}-\u{26EA}\u{26F0}-\u{26F5}\u{26F7}-\u{26FA}\u{26FD}\u{2702}\u{2705}\u{2708}-\u{270D}\u{270F}\u{2712}\u{2714}\u{2716}\u{271D}\u{2721}\u{2728}\u{2733}-\u{2734}\u{2744}\u{2747}\u{274C}\u{274E}\u{2753}-\u{2755}\u{2757}\u{2763}-\u{2764}\u{2795}-\u{2797}\u{27A1}\u{27B0}\u{27BF}\u{2934}-\u{2935}\u{2B05}-\u{2B07}\u{2B1B}-\u{2B1C}\u{2B50}\u{2B55}\u{3030}\u{303D}\u{3297}\u{3299}]/gu;
10
- /**
11
- * Find emojis in a string
12
- * @param {string} text
13
- * @returns {RegExpMatchArray | null}
14
- */
15
- const findEmojis = (text) => {
16
- return text.match(EMOJI_REGEX);
17
- };
18
- /**
19
- * Get a preview of the emoji found
20
- * @param {string} text
21
- * @returns {string}
22
- */
23
- const getEmojiPreview = (text) => {
24
- const emojis = findEmojis(text);
25
- if (!emojis || emojis.length === 0) return "";
26
- const uniqueEmojis = [...new Set(emojis)];
27
- const preview = uniqueEmojis.slice(0, 3).join(" ");
28
- return uniqueEmojis.length > 3 ? `${preview} ...` : preview;
29
- };
30
- const rule = defineRule({
31
- meta: {
32
- type: "problem",
33
- docs: {
34
- description: "Disallow the use of emojis in code. Use icons from a component library instead.",
35
- recommended: true
36
- },
37
- schema: []
38
- },
39
- createOnce(context) {
40
- return {
41
- StringLiteral(node) {
42
- if (node.type !== "StringLiteral") return;
43
- const emojis = findEmojis(node.value);
44
- if (emojis && emojis.length > 0) {
45
- const preview = getEmojiPreview(node.value);
46
- context.report({
47
- node,
48
- message: `Emojis are not allowed in code. Found: ${preview}. Use icons from a component library instead.`
49
- });
50
- }
51
- },
52
- TemplateLiteral(node) {
53
- if (node.type !== "TemplateLiteral") return;
54
- for (const quasi of node.quasis) {
55
- if (quasi.type !== "TemplateElement") continue;
56
- const text = quasi.value.raw;
57
- const emojis = findEmojis(text);
58
- if (emojis && emojis.length > 0) {
59
- const preview = getEmojiPreview(text);
60
- context.report({
61
- node: quasi,
62
- message: `Emojis are not allowed in code. Found: ${preview}. Use icons from a component library instead.`
63
- });
64
- }
65
- }
66
- },
67
- JSXText(node) {
68
- if (node.type !== "JSXText") return;
69
- const emojis = findEmojis(node.value);
70
- if (emojis && emojis.length > 0) {
71
- const preview = getEmojiPreview(node.value);
72
- context.report({
73
- node,
74
- message: `Emojis are not allowed in code. Found: ${preview}. Use icons from a component library instead.`
75
- });
76
- }
77
- }
78
- };
79
- }
80
- });
81
- const noEmojiRule = rule;
82
-
83
- //#endregion
84
- export { noEmojiRule };
85
- //# sourceMappingURL=no-emoji.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"no-emoji.mjs","names":[],"sources":["../../src/oxlint-plugins/no-emoji.js"],"sourcesContent":["import { defineRule } from \"oxlint\";\n\n/** @typedef {import(\"oxlint\").ESTree.Node} ESTNode */\n\n/**\n * Regex pattern to match emojis\n * Covers most common emoji ranges in Unicode\n */\nconst EMOJI_REGEX =\n /[\\u{1F300}-\\u{1F9FF}\\u{2600}-\\u{26FF}\\u{2700}-\\u{27BF}\\u{1F000}-\\u{1F02F}\\u{1F0A0}-\\u{1F0FF}\\u{1F100}-\\u{1F64F}\\u{1F680}-\\u{1F6FF}\\u{1F900}-\\u{1F9FF}\\u{1FA00}-\\u{1FA6F}\\u{1FA70}-\\u{1FAFF}\\u{FE00}-\\u{FE0F}\\u{203C}\\u{2049}\\u{20E3}\\u{2139}\\u{2194}-\\u{2199}\\u{21A9}-\\u{21AA}\\u{231A}-\\u{231B}\\u{2328}\\u{23CF}\\u{23E9}-\\u{23F3}\\u{23F8}-\\u{23FA}\\u{24C2}\\u{25AA}-\\u{25AB}\\u{25B6}\\u{25C0}\\u{25FB}-\\u{25FE}\\u{2600}-\\u{2604}\\u{260E}\\u{2611}\\u{2614}-\\u{2615}\\u{2618}\\u{261D}\\u{2620}\\u{2622}-\\u{2623}\\u{2626}\\u{262A}\\u{262E}-\\u{262F}\\u{2638}-\\u{263A}\\u{2640}\\u{2642}\\u{2648}-\\u{2653}\\u{265F}-\\u{2660}\\u{2663}\\u{2665}-\\u{2666}\\u{2668}\\u{267B}\\u{267E}-\\u{267F}\\u{2692}-\\u{2697}\\u{2699}\\u{269B}-\\u{269C}\\u{26A0}-\\u{26A1}\\u{26A7}\\u{26AA}-\\u{26AB}\\u{26B0}-\\u{26B1}\\u{26BD}-\\u{26BE}\\u{26C4}-\\u{26C5}\\u{26C8}\\u{26CE}\\u{26CF}\\u{26D1}\\u{26D3}-\\u{26D4}\\u{26E9}-\\u{26EA}\\u{26F0}-\\u{26F5}\\u{26F7}-\\u{26FA}\\u{26FD}\\u{2702}\\u{2705}\\u{2708}-\\u{270D}\\u{270F}\\u{2712}\\u{2714}\\u{2716}\\u{271D}\\u{2721}\\u{2728}\\u{2733}-\\u{2734}\\u{2744}\\u{2747}\\u{274C}\\u{274E}\\u{2753}-\\u{2755}\\u{2757}\\u{2763}-\\u{2764}\\u{2795}-\\u{2797}\\u{27A1}\\u{27B0}\\u{27BF}\\u{2934}-\\u{2935}\\u{2B05}-\\u{2B07}\\u{2B1B}-\\u{2B1C}\\u{2B50}\\u{2B55}\\u{3030}\\u{303D}\\u{3297}\\u{3299}]/gu;\n\n/**\n * Find emojis in a string\n * @param {string} text\n * @returns {RegExpMatchArray | null}\n */\nconst findEmojis = (text) => {\n return text.match(EMOJI_REGEX);\n};\n\n/**\n * Get a preview of the emoji found\n * @param {string} text\n * @returns {string}\n */\nconst getEmojiPreview = (text) => {\n const emojis = findEmojis(text);\n if (!emojis || emojis.length === 0) return \"\";\n\n const uniqueEmojis = [...new Set(emojis)];\n const preview = uniqueEmojis.slice(0, 3).join(\" \");\n\n return uniqueEmojis.length > 3 ? `${preview} ...` : preview;\n};\n\nconst rule = defineRule({\n meta: {\n type: \"problem\",\n docs: {\n description: \"Disallow the use of emojis in code. Use icons from a component library instead.\",\n recommended: true,\n },\n schema: [],\n },\n createOnce(context) {\n return /** @type {import(\"oxlint\").VisitorWithHooks} */ ({\n /**\n * Check string literals\n * @param {ESTNode} node\n */\n StringLiteral(node) {\n if (node.type !== \"StringLiteral\") return;\n\n const emojis = findEmojis(node.value);\n if (emojis && emojis.length > 0) {\n const preview = getEmojiPreview(node.value);\n context.report({\n node,\n message: `Emojis are not allowed in code. Found: ${preview}. Use icons from a component library instead.`,\n });\n }\n },\n\n /**\n * Check template literals\n * @param {ESTNode} node\n */\n TemplateLiteral(node) {\n if (node.type !== \"TemplateLiteral\") return;\n\n // Check each quasi (template string part)\n for (const quasi of node.quasis) {\n if (quasi.type !== \"TemplateElement\") continue;\n\n const text = quasi.value.raw;\n const emojis = findEmojis(text);\n\n if (emojis && emojis.length > 0) {\n const preview = getEmojiPreview(text);\n context.report({\n node: quasi,\n message: `Emojis are not allowed in code. Found: ${preview}. Use icons from a component library instead.`,\n });\n }\n }\n },\n\n /**\n * Check JSX text\n * @param {ESTNode} node\n */\n JSXText(node) {\n if (node.type !== \"JSXText\") return;\n\n const emojis = findEmojis(node.value);\n if (emojis && emojis.length > 0) {\n const preview = getEmojiPreview(node.value);\n context.report({\n node,\n message: `Emojis are not allowed in code. Found: ${preview}. Use icons from a component library instead.`,\n });\n }\n },\n });\n },\n});\n\nexport const noEmojiRule = rule;\n\n"],"mappings":";;;;;;;;AAQA,MAAM,cACJ;;;;;;AAOF,MAAM,cAAc,SAAS;AAC3B,QAAO,KAAK,MAAM,YAAY;;;;;;;AAQhC,MAAM,mBAAmB,SAAS;CAChC,MAAM,SAAS,WAAW,KAAK;AAC/B,KAAI,CAAC,UAAU,OAAO,WAAW,EAAG,QAAO;CAE3C,MAAM,eAAe,CAAC,GAAG,IAAI,IAAI,OAAO,CAAC;CACzC,MAAM,UAAU,aAAa,MAAM,GAAG,EAAE,CAAC,KAAK,IAAI;AAElD,QAAO,aAAa,SAAS,IAAI,GAAG,QAAQ,QAAQ;;AAGtD,MAAM,OAAO,WAAW;CACtB,MAAM;EACJ,MAAM;EACN,MAAM;GACJ,aAAa;GACb,aAAa;GACd;EACD,QAAQ,EAAE;EACX;CACD,WAAW,SAAS;AAClB,SAAyD;GAKvD,cAAc,MAAM;AAClB,QAAI,KAAK,SAAS,gBAAiB;IAEnC,MAAM,SAAS,WAAW,KAAK,MAAM;AACrC,QAAI,UAAU,OAAO,SAAS,GAAG;KAC/B,MAAM,UAAU,gBAAgB,KAAK,MAAM;AAC3C,aAAQ,OAAO;MACb;MACA,SAAS,0CAA0C,QAAQ;MAC5D,CAAC;;;GAQN,gBAAgB,MAAM;AACpB,QAAI,KAAK,SAAS,kBAAmB;AAGrC,SAAK,MAAM,SAAS,KAAK,QAAQ;AAC/B,SAAI,MAAM,SAAS,kBAAmB;KAEtC,MAAM,OAAO,MAAM,MAAM;KACzB,MAAM,SAAS,WAAW,KAAK;AAE/B,SAAI,UAAU,OAAO,SAAS,GAAG;MAC/B,MAAM,UAAU,gBAAgB,KAAK;AACrC,cAAQ,OAAO;OACb,MAAM;OACN,SAAS,0CAA0C,QAAQ;OAC5D,CAAC;;;;GASR,QAAQ,MAAM;AACZ,QAAI,KAAK,SAAS,UAAW;IAE7B,MAAM,SAAS,WAAW,KAAK,MAAM;AACrC,QAAI,UAAU,OAAO,SAAS,GAAG;KAC/B,MAAM,UAAU,gBAAgB,KAAK,MAAM;AAC3C,aAAQ,OAAO;MACb;MACA,SAAS,0CAA0C,QAAQ;MAC5D,CAAC;;;GAGP;;CAEJ,CAAC;AAEF,MAAa,cAAc"}
@@ -1,8 +0,0 @@
1
- import * as oxlint4 from "oxlint";
2
-
3
- //#region src/oxlint-plugins/no-finally.d.ts
4
- declare const noFinallyRule: oxlint4.Rule;
5
- type ESTNode = oxlint4.ESTree.Node;
6
- //#endregion
7
- export { ESTNode, noFinallyRule };
8
- //# sourceMappingURL=no-finally.d.mts.map
@@ -1,28 +0,0 @@
1
- import { defineRule } from "oxlint";
2
-
3
- //#region src/oxlint-plugins/no-finally.js
4
- /** @typedef {import("oxlint").ESTree.Node} ESTNode */
5
- const rule = defineRule({
6
- meta: {
7
- type: "problem",
8
- docs: {
9
- description: "Disallow 'finally' blocks in try/catch/finally statements",
10
- recommended: true
11
- },
12
- schema: []
13
- },
14
- createOnce(context) {
15
- return { TryStatement(node) {
16
- if (node.type !== "TryStatement") return;
17
- if (node.finalizer) context.report({
18
- node: node.finalizer,
19
- message: "Use of 'finally' blocks is disallowed. Handle cleanup explicitly in try/catch blocks instead."
20
- });
21
- } };
22
- }
23
- });
24
- const noFinallyRule = rule;
25
-
26
- //#endregion
27
- export { noFinallyRule };
28
- //# sourceMappingURL=no-finally.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"no-finally.mjs","names":[],"sources":["../../src/oxlint-plugins/no-finally.js"],"sourcesContent":["import { defineRule } from \"oxlint\";\n\n/** @typedef {import(\"oxlint\").ESTree.Node} ESTNode */\n\nconst rule = defineRule({\n meta: {\n type: \"problem\",\n docs: {\n description: \"Disallow 'finally' blocks in try/catch/finally statements\",\n recommended: true,\n },\n schema: [],\n },\n createOnce(context) {\n return /** @type {import(\"oxlint\").VisitorWithHooks} */ ({\n /**\n * @param {ESTNode} node\n */\n TryStatement(node) {\n if (node.type !== \"TryStatement\") return;\n\n if (node.finalizer) {\n context.report({\n node: node.finalizer,\n message: \"Use of 'finally' blocks is disallowed. Handle cleanup explicitly in try/catch blocks instead.\",\n });\n }\n },\n });\n },\n});\n\nexport const noFinallyRule = rule;\n\n"],"mappings":";;;;AAIA,MAAM,OAAO,WAAW;CACtB,MAAM;EACJ,MAAM;EACN,MAAM;GACJ,aAAa;GACb,aAAa;GACd;EACD,QAAQ,EAAE;EACX;CACD,WAAW,SAAS;AAClB,SAAyD,EAIvD,aAAa,MAAM;AACjB,OAAI,KAAK,SAAS,eAAgB;AAElC,OAAI,KAAK,UACP,SAAQ,OAAO;IACb,MAAM,KAAK;IACX,SAAS;IACV,CAAC;KAGP;;CAEJ,CAAC;AAEF,MAAa,gBAAgB"}
@@ -1,11 +0,0 @@
1
- import * as oxlint0 from "oxlint";
2
-
3
- //#region src/oxlint-plugins/no-function-call-in-jsx.d.ts
4
- declare const noFunctionCallInJsxRule: oxlint0.Rule;
5
- type RuleContext = oxlint0.Context;
6
- type ESTNode = oxlint0.ESTree.Node;
7
- type JSXExpressionContainer = oxlint0.ESTree.JSXExpressionContainer;
8
- type CallExpression = oxlint0.ESTree.CallExpression;
9
- //#endregion
10
- export { CallExpression, ESTNode, JSXExpressionContainer, RuleContext, noFunctionCallInJsxRule };
11
- //# sourceMappingURL=no-function-call-in-jsx.d.mts.map
@@ -1,70 +0,0 @@
1
- import { defineRule } from "oxlint";
2
-
3
- //#region src/oxlint-plugins/no-function-call-in-jsx.js
4
- /**
5
- * @typedef {import("oxlint").Context} RuleContext
6
- * @typedef {import("oxlint").ESTree.Node} ESTNode
7
- * @typedef {import("oxlint").ESTree.JSXExpressionContainer} JSXExpressionContainer
8
- * @typedef {import("oxlint").ESTree.CallExpression} CallExpression
9
- */
10
- /**
11
- * @param {unknown} node
12
- * @returns {node is ESTNode & { type: string }}
13
- */
14
- const isNode = (node) => Boolean(node && typeof node === "object" && "type" in node);
15
- /**
16
- * @param {ESTNode | null | undefined} node
17
- * @returns {boolean}
18
- */
19
- const isInJSXExpressionContainer = (node) => {
20
- const findJSXContainer = (current) => {
21
- if (!current) return false;
22
- if (current.type === "JSXExpressionContainer") return true;
23
- return findJSXContainer(isNode(current) ? current.parent ?? null : null);
24
- };
25
- return findJSXContainer(isNode(node) ? node.parent ?? null : null);
26
- };
27
- /**
28
- * @param {CallExpression} node
29
- * @returns {string}
30
- */
31
- const getCalleeName = (node) => {
32
- const callee = node.callee;
33
- if (!callee) return "function";
34
- if (callee.type === "Identifier") return callee.name;
35
- if (callee.type === "MemberExpression") {
36
- const property = callee.property;
37
- if (property && property.type === "Identifier") return property.name;
38
- }
39
- return "function";
40
- };
41
- const rule = defineRule({
42
- meta: {
43
- type: "problem",
44
- docs: {
45
- description: "Disallow function calls within JSX expression containers",
46
- recommended: false
47
- },
48
- schema: []
49
- },
50
- create(context) {
51
- /**
52
- * @param {CallExpression} node
53
- */
54
- const handleCallExpression = (node) => {
55
- if (node.type !== "CallExpression") return;
56
- if (!isInJSXExpressionContainer(node)) return;
57
- const calleeName = getCalleeName(node);
58
- context.report({
59
- node,
60
- message: `Avoid calling '${calleeName}()' directly in JSX. Store the result in a variable or use a component instead.`
61
- });
62
- };
63
- return { CallExpression: handleCallExpression };
64
- }
65
- });
66
- const noFunctionCallInJsxRule = rule;
67
-
68
- //#endregion
69
- export { noFunctionCallInJsxRule };
70
- //# sourceMappingURL=no-function-call-in-jsx.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"no-function-call-in-jsx.mjs","names":[],"sources":["../../src/oxlint-plugins/no-function-call-in-jsx.js"],"sourcesContent":["import { defineRule } from \"oxlint\";\n\n/**\n * @typedef {import(\"oxlint\").Context} RuleContext\n * @typedef {import(\"oxlint\").ESTree.Node} ESTNode\n * @typedef {import(\"oxlint\").ESTree.JSXExpressionContainer} JSXExpressionContainer\n * @typedef {import(\"oxlint\").ESTree.CallExpression} CallExpression\n */\n\n/**\n * @param {unknown} node\n * @returns {node is ESTNode & { type: string }}\n */\nconst isNode = (node) => Boolean(node && typeof node === \"object\" && \"type\" in node);\n\n/**\n * @param {ESTNode | null | undefined} node\n * @returns {boolean}\n */\nconst isInJSXExpressionContainer = (node) => {\n const findJSXContainer = (current) => {\n if (!current) return false;\n if (current.type === \"JSXExpressionContainer\") {\n return true;\n }\n return findJSXContainer(isNode(current) ? current.parent ?? null : null);\n };\n return findJSXContainer(isNode(node) ? node.parent ?? null : null);\n};\n\n/**\n * @param {CallExpression} node\n * @returns {string}\n */\nconst getCalleeName = (node) => {\n const callee = node.callee;\n if (!callee) return \"function\";\n\n if (callee.type === \"Identifier\") {\n return callee.name;\n }\n\n if (callee.type === \"MemberExpression\") {\n const property = callee.property;\n if (property && property.type === \"Identifier\") {\n return property.name;\n }\n }\n\n return \"function\";\n};\n\nconst rule = defineRule({\n meta: {\n type: \"problem\",\n docs: {\n description: \"Disallow function calls within JSX expression containers\",\n recommended: false,\n },\n schema: [],\n },\n\n create(context) {\n /**\n * @param {CallExpression} node\n */\n const handleCallExpression = (node) => {\n if (node.type !== \"CallExpression\") return;\n\n if (!isInJSXExpressionContainer(node)) return;\n\n const calleeName = getCalleeName(node);\n\n context.report({\n node: node,\n message: `Avoid calling '${calleeName}()' directly in JSX. Store the result in a variable or use a component instead.`,\n });\n };\n\n return {\n CallExpression: handleCallExpression,\n };\n },\n});\n\nexport const noFunctionCallInJsxRule = rule;\n\n"],"mappings":";;;;;;;;;;;;;AAaA,MAAM,UAAU,SAAS,QAAQ,QAAQ,OAAO,SAAS,YAAY,UAAU,KAAK;;;;;AAMpF,MAAM,8BAA8B,SAAS;CAC3C,MAAM,oBAAoB,YAAY;AACpC,MAAI,CAAC,QAAS,QAAO;AACrB,MAAI,QAAQ,SAAS,yBACnB,QAAO;AAET,SAAO,iBAAiB,OAAO,QAAQ,GAAG,QAAQ,UAAU,OAAO,KAAK;;AAE1E,QAAO,iBAAiB,OAAO,KAAK,GAAG,KAAK,UAAU,OAAO,KAAK;;;;;;AAOpE,MAAM,iBAAiB,SAAS;CAC9B,MAAM,SAAS,KAAK;AACpB,KAAI,CAAC,OAAQ,QAAO;AAEpB,KAAI,OAAO,SAAS,aAClB,QAAO,OAAO;AAGhB,KAAI,OAAO,SAAS,oBAAoB;EACtC,MAAM,WAAW,OAAO;AACxB,MAAI,YAAY,SAAS,SAAS,aAChC,QAAO,SAAS;;AAIpB,QAAO;;AAGT,MAAM,OAAO,WAAW;CACtB,MAAM;EACJ,MAAM;EACN,MAAM;GACJ,aAAa;GACb,aAAa;GACd;EACD,QAAQ,EAAE;EACX;CAED,OAAO,SAAS;;;;EAId,MAAM,wBAAwB,SAAS;AACrC,OAAI,KAAK,SAAS,iBAAkB;AAEpC,OAAI,CAAC,2BAA2B,KAAK,CAAE;GAEvC,MAAM,aAAa,cAAc,KAAK;AAEtC,WAAQ,OAAO;IACP;IACN,SAAS,kBAAkB,WAAW;IACvC,CAAC;;AAGJ,SAAO,EACL,gBAAgB,sBACjB;;CAEJ,CAAC;AAEF,MAAa,0BAA0B"}
@@ -1,36 +0,0 @@
1
- import * as oxlint26 from "oxlint";
2
-
3
- //#region src/oxlint-plugins/no-inline-components.d.ts
4
- declare function isComponentName(name: unknown): name is string;
5
- declare function isHookName(name: unknown): name is string;
6
- declare function getEnclosingFunction(node: ESTNode | null | undefined): FunctionLikeNode | null;
7
- declare function getFunctionName(node: FunctionLikeNode): string;
8
- declare const noInlineComponentsRule: oxlint26.Rule;
9
- type RuleContext = oxlint26.Context;
10
- type ESTNode = oxlint26.ESTree.Node;
11
- type ESTExpression = oxlint26.ESTree.Expression;
12
- type ESTPattern = oxlint26.ESTree.Pattern;
13
- type ReturnStatementNode = oxlint26.ESTree.ReturnStatement;
14
- type VariableDeclaratorNode = oxlint26.ESTree.VariableDeclarator;
15
- type AssignmentExpressionNode = oxlint26.ESTree.AssignmentExpression;
16
- type FunctionLikeNode = oxlint26.ESTree.Function | oxlint26.ESTree.ArrowFunctionExpression;
17
- type RecordedAssignment = {
18
- node: ESTExpression;
19
- names: string[];
20
- };
21
- type NestedFunctionRecord = {
22
- node: FunctionLikeNode;
23
- name: string;
24
- };
25
- type FunctionContext = {
26
- node: FunctionLikeNode;
27
- parent: FunctionContext | null;
28
- name: string;
29
- returnsJsx: boolean;
30
- jsxBindingNames: Set<string>;
31
- jsxAssignments: RecordedAssignment[];
32
- nestedJsxChildren: NestedFunctionRecord[];
33
- };
34
- //#endregion
35
- export { AssignmentExpressionNode, ESTExpression, ESTNode, ESTPattern, FunctionContext, FunctionLikeNode, NestedFunctionRecord, RecordedAssignment, ReturnStatementNode, RuleContext, VariableDeclaratorNode, getEnclosingFunction, getFunctionName, isComponentName, isHookName, noInlineComponentsRule };
36
- //# sourceMappingURL=no-inline-components.d.mts.map