@imranbarbhuiya/oxc-config 0.0.1

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 (69) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +190 -0
  3. package/dist/api-error.d.ts +6 -0
  4. package/dist/api-error.js +12 -0
  5. package/dist/api-error.js.map +1 -0
  6. package/dist/central-icons.d.ts +6 -0
  7. package/dist/central-icons.js +12 -0
  8. package/dist/central-icons.js.map +1 -0
  9. package/dist/common.d.ts +6 -0
  10. package/dist/common.js +296 -0
  11. package/dist/common.js.map +1 -0
  12. package/dist/edge.d.ts +6 -0
  13. package/dist/edge.js +18 -0
  14. package/dist/edge.js.map +1 -0
  15. package/dist/i18n.d.ts +6 -0
  16. package/dist/i18n.js +15 -0
  17. package/dist/i18n.js.map +1 -0
  18. package/dist/jsdoc.d.ts +6 -0
  19. package/dist/jsdoc.js +43 -0
  20. package/dist/jsdoc.js.map +1 -0
  21. package/dist/jsx.d.ts +6 -0
  22. package/dist/jsx.js +78 -0
  23. package/dist/jsx.js.map +1 -0
  24. package/dist/mdx.d.ts +6 -0
  25. package/dist/mdx.js +25 -0
  26. package/dist/mdx.js.map +1 -0
  27. package/dist/module.d.ts +6 -0
  28. package/dist/module.js +12 -0
  29. package/dist/module.js.map +1 -0
  30. package/dist/native-tailwind.d.ts +6 -0
  31. package/dist/native-tailwind.js +12 -0
  32. package/dist/native-tailwind.js.map +1 -0
  33. package/dist/native.d.ts +6 -0
  34. package/dist/native.js +51 -0
  35. package/dist/native.js.map +1 -0
  36. package/dist/nest.d.ts +6 -0
  37. package/dist/nest.js +13 -0
  38. package/dist/nest.js.map +1 -0
  39. package/dist/next.d.ts +6 -0
  40. package/dist/next.js +33 -0
  41. package/dist/next.js.map +1 -0
  42. package/dist/node.d.ts +6 -0
  43. package/dist/node.js +80 -0
  44. package/dist/node.js.map +1 -0
  45. package/dist/plugins/api-error.d.ts +6 -0
  46. package/dist/plugins/api-error.js +169 -0
  47. package/dist/plugins/api-error.js.map +1 -0
  48. package/dist/plugins/central-icons.d.ts +6 -0
  49. package/dist/plugins/central-icons.js +61 -0
  50. package/dist/plugins/central-icons.js.map +1 -0
  51. package/dist/plugins/i18n.d.ts +6 -0
  52. package/dist/plugins/i18n.js +58 -0
  53. package/dist/plugins/i18n.js.map +1 -0
  54. package/dist/plugins/native-tailwind.d.ts +6 -0
  55. package/dist/plugins/native-tailwind.js +110 -0
  56. package/dist/plugins/native-tailwind.js.map +1 -0
  57. package/dist/react.d.ts +6 -0
  58. package/dist/react.js +65 -0
  59. package/dist/react.js.map +1 -0
  60. package/dist/tailwind.d.ts +6 -0
  61. package/dist/tailwind.js +18 -0
  62. package/dist/tailwind.js.map +1 -0
  63. package/dist/tsdoc.d.ts +6 -0
  64. package/dist/tsdoc.js +21 -0
  65. package/dist/tsdoc.js.map +1 -0
  66. package/dist/typescript.d.ts +6 -0
  67. package/dist/typescript.js +200 -0
  68. package/dist/typescript.js.map +1 -0
  69. package/package.json +180 -0
@@ -0,0 +1,169 @@
1
+ //#region src/plugins/api-error.ts
2
+ const DEFAULT_ALLOWED_ERRORS = ["ApiError", "FormValidationError"];
3
+ const plugin = {
4
+ meta: {
5
+ name: "eslint-plugin-mahir-api-error",
6
+ version: "1.0.0"
7
+ },
8
+ rules: { "require-api-error": {
9
+ meta: {
10
+ type: "problem",
11
+ docs: { description: "Require an allowed API error instead of Error inside queryFn/mutationFn so status codes propagate to QueryCache error handling" },
12
+ schema: [{
13
+ type: "object",
14
+ additionalProperties: false,
15
+ properties: { allowedErrors: {
16
+ type: "array",
17
+ items: {
18
+ type: "string",
19
+ minLength: 1
20
+ },
21
+ minItems: 1,
22
+ uniqueItems: true
23
+ } }
24
+ }],
25
+ messages: {
26
+ useApiError: "Use `new {{allowed}}(...)` or `{{allowed}}.from(...)` instead of `new {{thrown}}(...)` inside {{fnType}}. This ensures the HTTP status code is available in QueryCache/retry/error reporting.",
27
+ useApiErrorCall: "Use `new {{allowed}}(...)` or `{{allowed}}.from(...)` instead of `{{thrown}}(...)` inside {{fnType}}. This ensures the HTTP status code is available in QueryCache/retry/error reporting.",
28
+ useApiErrorMember: "Throw `new {{allowed}}(...)` or `{{allowed}}.from(...)` instead of re-throwing `{{thrown}}` directly inside {{fnType}}. The client error object may lose its HTTP status code in QueryCache/retry/error reporting."
29
+ }
30
+ },
31
+ defaultOptions: [{ allowedErrors: [...DEFAULT_ALLOWED_ERRORS] }],
32
+ create(context) {
33
+ const sourceCode = context.sourceCode;
34
+ const allowedList = context.options[0]?.allowedErrors ?? DEFAULT_ALLOWED_ERRORS;
35
+ const allowedErrors = new Set(allowedList);
36
+ const allowedExample = allowedList[0] ?? DEFAULT_ALLOWED_ERRORS[0];
37
+ const fnStack = [];
38
+ const extractedRefs = [];
39
+ const moduleFns = /* @__PURE__ */ new Map();
40
+ function recordModuleFn(name, body) {
41
+ if (!name || !body) return;
42
+ if (!moduleFns.has(name)) moduleFns.set(name, body);
43
+ }
44
+ function getStaticFactoryCallee(arg) {
45
+ if (arg.type !== "CallExpression") return void 0;
46
+ const { callee } = arg;
47
+ if (callee.type !== "MemberExpression" || callee.computed) return void 0;
48
+ const { object, property } = callee;
49
+ if (object.type !== "Identifier" || property.type !== "Identifier") return void 0;
50
+ return {
51
+ callee,
52
+ name: object.name
53
+ };
54
+ }
55
+ function isAllowedThrow(arg) {
56
+ if (arg.type === "NewExpression" && arg.callee.type === "Identifier") return allowedErrors.has(arg.callee.name);
57
+ const factory = getStaticFactoryCallee(arg);
58
+ return factory !== void 0 && allowedErrors.has(factory.name);
59
+ }
60
+ function checkThrowNode(node, fnType) {
61
+ const arg = node.argument;
62
+ if (isAllowedThrow(arg)) return;
63
+ if (arg.type === "NewExpression" && arg.callee.type === "Identifier") {
64
+ context.report({
65
+ node: arg,
66
+ messageId: "useApiError",
67
+ data: {
68
+ thrown: arg.callee.name,
69
+ fnType,
70
+ allowed: allowedExample
71
+ }
72
+ });
73
+ return;
74
+ }
75
+ const factory = getStaticFactoryCallee(arg);
76
+ if (factory) {
77
+ context.report({
78
+ node: arg,
79
+ messageId: "useApiErrorCall",
80
+ data: {
81
+ thrown: sourceCode.getText(factory.callee),
82
+ fnType,
83
+ allowed: allowedExample
84
+ }
85
+ });
86
+ return;
87
+ }
88
+ if (arg.type === "MemberExpression") context.report({
89
+ node: arg,
90
+ messageId: "useApiErrorMember",
91
+ data: {
92
+ thrown: sourceCode.getText(arg),
93
+ fnType,
94
+ allowed: allowedExample
95
+ }
96
+ });
97
+ }
98
+ function isAstNode(value) {
99
+ return typeof value === "object" && value !== null && "type" in value && typeof value.type === "string";
100
+ }
101
+ function walkThrows(node, fnType, visited = /* @__PURE__ */ new Set()) {
102
+ if (!node || visited.has(node)) return;
103
+ visited.add(node);
104
+ if (node.type === "ThrowStatement") {
105
+ checkThrowNode(node, fnType);
106
+ return;
107
+ }
108
+ if (node.type === "FunctionDeclaration" || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression") {
109
+ walkThrows(node.body, fnType, visited);
110
+ return;
111
+ }
112
+ for (const key of Object.keys(node)) {
113
+ if (key === "parent" || key === "loc" || key === "range") continue;
114
+ const child = node[key];
115
+ if (Array.isArray(child)) {
116
+ for (const c of child) if (isAstNode(c)) walkThrows(c, fnType, visited);
117
+ } else if (isAstNode(child)) walkThrows(child, fnType, visited);
118
+ }
119
+ }
120
+ function enterQueryOrMutationFn(node) {
121
+ const parent = node.parent;
122
+ if (parent.type !== "Property" || parent.key.type !== "Identifier") return;
123
+ const name = parent.key.name;
124
+ if (name === "queryFn" || name === "mutationFn") fnStack.push(name);
125
+ }
126
+ function exitQueryOrMutationFn(node) {
127
+ const parent = node.parent;
128
+ if (parent.type !== "Property" || parent.key.type !== "Identifier") return;
129
+ const name = parent.key.name;
130
+ if (name === "queryFn" || name === "mutationFn") fnStack.pop();
131
+ }
132
+ function checkThrowStatement(node) {
133
+ if (fnStack.length === 0) return;
134
+ checkThrowNode(node, fnStack[fnStack.length - 1]);
135
+ }
136
+ function recordExtractedRef(prop) {
137
+ if (prop.key.type !== "Identifier" || prop.key.name !== "queryFn" && prop.key.name !== "mutationFn" || prop.value.type !== "Identifier") return;
138
+ extractedRefs.push({
139
+ name: prop.value.name,
140
+ fnType: prop.key.name
141
+ });
142
+ }
143
+ return {
144
+ "Program > FunctionDeclaration"(node) {
145
+ recordModuleFn(node.id?.name, node.body);
146
+ },
147
+ "Program > VariableDeclaration > VariableDeclarator"(node) {
148
+ if (node.id.type === "Identifier" && (node.init?.type === "ArrowFunctionExpression" || node.init?.type === "FunctionExpression")) recordModuleFn(node.id.name, node.init.body);
149
+ },
150
+ ArrowFunctionExpression: enterQueryOrMutationFn,
151
+ "ArrowFunctionExpression:exit": exitQueryOrMutationFn,
152
+ FunctionExpression: enterQueryOrMutationFn,
153
+ "FunctionExpression:exit": exitQueryOrMutationFn,
154
+ Property: recordExtractedRef,
155
+ ThrowStatement: checkThrowStatement,
156
+ "Program:exit"() {
157
+ for (const { name, fnType } of extractedRefs) {
158
+ const body = moduleFns.get(name);
159
+ if (body) walkThrows(body, fnType);
160
+ }
161
+ }
162
+ };
163
+ }
164
+ } }
165
+ };
166
+
167
+ //#endregion
168
+ export { plugin as default };
169
+ //# sourceMappingURL=api-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-error.js","names":[],"sources":["../../src/plugins/api-error.ts"],"sourcesContent":["import type { TSESLint, TSESTree } from '@typescript-eslint/utils';\n\nconst DEFAULT_ALLOWED_ERRORS = ['ApiError', 'FormValidationError'];\n\ntype Options = [\n\t{\n\t\tallowedErrors?: string[];\n\t},\n];\n\nconst requireApiError: TSESLint.RuleModule<'useApiError' | 'useApiErrorCall' | 'useApiErrorMember', Options> = {\n\tmeta: {\n\t\ttype: 'problem',\n\t\tdocs: {\n\t\t\tdescription:\n\t\t\t\t'Require an allowed API error instead of Error inside queryFn/mutationFn so status codes propagate to QueryCache error handling',\n\t\t},\n\t\tschema: [\n\t\t\t{\n\t\t\t\ttype: 'object',\n\t\t\t\tadditionalProperties: false,\n\t\t\t\tproperties: {\n\t\t\t\t\tallowedErrors: {\n\t\t\t\t\t\ttype: 'array',\n\t\t\t\t\t\titems: { type: 'string', minLength: 1 },\n\t\t\t\t\t\tminItems: 1,\n\t\t\t\t\t\tuniqueItems: true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t\tmessages: {\n\t\t\tuseApiError:\n\t\t\t\t'Use `new {{allowed}}(...)` or `{{allowed}}.from(...)` instead of `new {{thrown}}(...)` inside {{fnType}}. This ensures the HTTP status code is available in QueryCache/retry/error reporting.',\n\t\t\tuseApiErrorCall:\n\t\t\t\t'Use `new {{allowed}}(...)` or `{{allowed}}.from(...)` instead of `{{thrown}}(...)` inside {{fnType}}. This ensures the HTTP status code is available in QueryCache/retry/error reporting.',\n\t\t\tuseApiErrorMember:\n\t\t\t\t'Throw `new {{allowed}}(...)` or `{{allowed}}.from(...)` instead of re-throwing `{{thrown}}` directly inside {{fnType}}. The client error object may lose its HTTP status code in QueryCache/retry/error reporting.',\n\t\t},\n\t},\n\tdefaultOptions: [{ allowedErrors: [...DEFAULT_ALLOWED_ERRORS] }],\n\tcreate(context) {\n\t\tconst sourceCode = context.sourceCode;\n\t\t// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n\t\tconst allowedList = context.options[0]?.allowedErrors ?? DEFAULT_ALLOWED_ERRORS;\n\t\tconst allowedErrors = new Set(allowedList);\n\t\tconst allowedExample = allowedList[0] ?? DEFAULT_ALLOWED_ERRORS[0];\n\t\tconst fnStack: string[] = [];\n\t\tconst extractedRefs: { name: string; fnType: string }[] = [];\n\t\tconst moduleFns = new Map<string, TSESTree.Node>();\n\n\t\tfunction recordModuleFn(name: string | undefined, body: TSESTree.Node | null | undefined) {\n\t\t\tif (!name || !body) return;\n\t\t\tif (!moduleFns.has(name)) moduleFns.set(name, body);\n\t\t}\n\n\t\tfunction getStaticFactoryCallee(arg: TSESTree.ThrowStatement['argument']) {\n\t\t\tif (arg.type !== 'CallExpression') return undefined;\n\t\t\tconst { callee } = arg;\n\t\t\tif (callee.type !== 'MemberExpression' || callee.computed) return undefined;\n\t\t\tconst { object, property } = callee;\n\t\t\tif (object.type !== 'Identifier' || property.type !== 'Identifier') return undefined;\n\t\t\treturn { callee, name: object.name };\n\t\t}\n\n\t\tfunction isAllowedThrow(arg: TSESTree.ThrowStatement['argument']) {\n\t\t\tif (arg.type === 'NewExpression' && arg.callee.type === 'Identifier') return allowedErrors.has(arg.callee.name);\n\n\t\t\tconst factory = getStaticFactoryCallee(arg);\n\t\t\treturn factory !== undefined && allowedErrors.has(factory.name);\n\t\t}\n\n\t\tfunction checkThrowNode(node: TSESTree.ThrowStatement, fnType: string) {\n\t\t\tconst arg = node.argument;\n\t\t\tif (isAllowedThrow(arg)) return;\n\n\t\t\tif (arg.type === 'NewExpression' && arg.callee.type === 'Identifier') {\n\t\t\t\tcontext.report({\n\t\t\t\t\tnode: arg,\n\t\t\t\t\tmessageId: 'useApiError',\n\t\t\t\t\tdata: { thrown: arg.callee.name, fnType, allowed: allowedExample },\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst factory = getStaticFactoryCallee(arg);\n\t\t\tif (factory) {\n\t\t\t\tcontext.report({\n\t\t\t\t\tnode: arg,\n\t\t\t\t\tmessageId: 'useApiErrorCall',\n\t\t\t\t\tdata: { thrown: sourceCode.getText(factory.callee), fnType, allowed: allowedExample },\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (arg.type === 'MemberExpression') {\n\t\t\t\tcontext.report({\n\t\t\t\t\tnode: arg,\n\t\t\t\t\tmessageId: 'useApiErrorMember',\n\t\t\t\t\tdata: { thrown: sourceCode.getText(arg), fnType, allowed: allowedExample },\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tfunction isAstNode(value: unknown): value is TSESTree.Node {\n\t\t\treturn typeof value === 'object' && value !== null && 'type' in value && typeof value.type === 'string';\n\t\t}\n\n\t\tfunction walkThrows(node: TSESTree.Node | null | undefined, fnType: string, visited = new Set<TSESTree.Node>()) {\n\t\t\tif (!node || visited.has(node)) return;\n\t\t\tvisited.add(node);\n\n\t\t\tif (node.type === 'ThrowStatement') {\n\t\t\t\tcheckThrowNode(node, fnType);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tnode.type === 'FunctionDeclaration' ||\n\t\t\t\tnode.type === 'FunctionExpression' ||\n\t\t\t\tnode.type === 'ArrowFunctionExpression'\n\t\t\t) {\n\t\t\t\twalkThrows(node.body, fnType, visited);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tfor (const key of Object.keys(node)) {\n\t\t\t\tif (key === 'parent' || key === 'loc' || key === 'range') continue;\n\t\t\t\tconst child = (node as unknown as Record<string, unknown>)[key];\n\t\t\t\tif (Array.isArray(child)) {\n\t\t\t\t\tfor (const c of child) if (isAstNode(c)) walkThrows(c, fnType, visited);\n\t\t\t\t} else if (isAstNode(child)) walkThrows(child, fnType, visited);\n\t\t\t}\n\t\t}\n\n\t\tfunction enterQueryOrMutationFn(node: TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression) {\n\t\t\tconst parent = node.parent;\n\t\t\tif (parent.type !== 'Property' || parent.key.type !== 'Identifier') return;\n\t\t\tconst name = parent.key.name;\n\t\t\tif (name === 'queryFn' || name === 'mutationFn') fnStack.push(name);\n\t\t}\n\n\t\tfunction exitQueryOrMutationFn(node: TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression) {\n\t\t\tconst parent = node.parent;\n\t\t\tif (parent.type !== 'Property' || parent.key.type !== 'Identifier') return;\n\t\t\tconst name = parent.key.name;\n\t\t\tif (name === 'queryFn' || name === 'mutationFn') fnStack.pop();\n\t\t}\n\n\t\tfunction checkThrowStatement(node: TSESTree.ThrowStatement) {\n\t\t\tif (fnStack.length === 0) return;\n\t\t\tcheckThrowNode(node, fnStack[fnStack.length - 1]);\n\t\t}\n\n\t\tfunction recordExtractedRef(prop: TSESTree.Property) {\n\t\t\tif (\n\t\t\t\tprop.key.type !== 'Identifier' ||\n\t\t\t\t(prop.key.name !== 'queryFn' && prop.key.name !== 'mutationFn') ||\n\t\t\t\tprop.value.type !== 'Identifier'\n\t\t\t)\n\t\t\t\treturn;\n\t\t\textractedRefs.push({ name: prop.value.name, fnType: prop.key.name });\n\t\t}\n\n\t\treturn {\n\t\t\t'Program > FunctionDeclaration'(node: TSESTree.FunctionDeclaration) {\n\t\t\t\trecordModuleFn(node.id?.name, node.body);\n\t\t\t},\n\t\t\t'Program > VariableDeclaration > VariableDeclarator'(node: TSESTree.VariableDeclarator) {\n\t\t\t\tif (\n\t\t\t\t\tnode.id.type === 'Identifier' &&\n\t\t\t\t\t(node.init?.type === 'ArrowFunctionExpression' || node.init?.type === 'FunctionExpression')\n\t\t\t\t)\n\t\t\t\t\trecordModuleFn(node.id.name, node.init.body);\n\t\t\t},\n\t\t\tArrowFunctionExpression: enterQueryOrMutationFn,\n\t\t\t'ArrowFunctionExpression:exit': exitQueryOrMutationFn,\n\t\t\tFunctionExpression: enterQueryOrMutationFn,\n\t\t\t'FunctionExpression:exit': exitQueryOrMutationFn,\n\t\t\tProperty: recordExtractedRef,\n\t\t\tThrowStatement: checkThrowStatement,\n\t\t\t'Program:exit'() {\n\t\t\t\tfor (const { name, fnType } of extractedRefs) {\n\t\t\t\t\tconst body = moduleFns.get(name);\n\t\t\t\t\tif (body) walkThrows(body, fnType);\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t},\n};\n\nconst plugin: TSESLint.FlatConfig.Plugin = {\n\tmeta: {\n\t\tname: 'eslint-plugin-mahir-api-error',\n\t\tversion: '1.0.0',\n\t},\n\trules: {\n\t\t'require-api-error': requireApiError,\n\t},\n};\n\nexport default plugin;\n"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { TSESLint } from "@typescript-eslint/utils";
2
+ //#region src/plugins/central-icons.d.ts
3
+ declare const plugin: TSESLint.FlatConfig.Plugin;
4
+ //#endregion
5
+ export { plugin as default };
6
+ //# sourceMappingURL=central-icons.d.ts.map
@@ -0,0 +1,61 @@
1
+ //#region src/plugins/central-icons.ts
2
+ const CENTRAL_ICONS_PACKAGE_RE = /^@central-icons-react(?:-native)?\/[^/]+$/;
3
+ function centralIconSubpath(iconName) {
4
+ if (iconName.endsWith("Default")) return iconName.slice(0, -7);
5
+ return iconName;
6
+ }
7
+ const plugin = {
8
+ meta: {
9
+ name: "eslint-plugin-mahir-central-icons",
10
+ version: "1.0.0"
11
+ },
12
+ rules: { "no-central-icons-barrel-import": {
13
+ meta: {
14
+ type: "problem",
15
+ docs: { description: "Disallow barrel imports from @central-icons-react and @central-icons-react-native packages; use direct subpath imports instead" },
16
+ fixable: "code",
17
+ schema: [],
18
+ messages: {
19
+ barrelImport: "Avoid barrel imports from `{{source}}`. Import icons directly from `{{source}}/<IconName>` to keep the bundler from opening thousands of icon files.",
20
+ unsupportedImport: "Only named icon imports can be autofixed. Use direct subpath default imports from `{{source}}/<IconName>`."
21
+ }
22
+ },
23
+ defaultOptions: [],
24
+ create(context) {
25
+ return { ImportDeclaration(node) {
26
+ const source = node.source.value;
27
+ if (typeof source !== "string" || !CENTRAL_ICONS_PACKAGE_RE.test(source)) return;
28
+ const namedSpecifiers = node.specifiers.filter((specifier) => specifier.type === "ImportSpecifier");
29
+ if (namedSpecifiers.length === 0 || namedSpecifiers.length !== node.specifiers.length) {
30
+ context.report({
31
+ node,
32
+ messageId: "unsupportedImport",
33
+ data: { source }
34
+ });
35
+ return;
36
+ }
37
+ context.report({
38
+ node,
39
+ messageId: "barrelImport",
40
+ data: { source },
41
+ fix(fixer) {
42
+ const quote = node.source.raw.startsWith("'") ? "'" : "\"";
43
+ const fixedImports = namedSpecifiers.map((specifier) => {
44
+ const imported = specifier.imported;
45
+ const importedName = imported.type === "Identifier" ? imported.name : imported.value;
46
+ const localName = specifier.local.name;
47
+ const typePrefix = node.importKind === "type" || specifier.importKind === "type" ? "type " : "";
48
+ const subpath = centralIconSubpath(importedName);
49
+ return `import ${typePrefix}${localName} from ${quote}${source}/${subpath}${quote};`;
50
+ });
51
+ return fixer.replaceText(node, fixedImports.join("\n"));
52
+ }
53
+ });
54
+ } };
55
+ }
56
+ } }
57
+ };
58
+
59
+ //#endregion
60
+ export { plugin as default };
61
+ //# sourceMappingURL=central-icons.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"central-icons.js","names":[],"sources":["../../src/plugins/central-icons.ts"],"sourcesContent":["import type { TSESLint } from '@typescript-eslint/utils';\n\nconst CENTRAL_ICONS_PACKAGE_RE = /^@central-icons-react(?:-native)?\\/[^/]+$/;\n\nfunction centralIconSubpath(iconName: string) {\n\tif (iconName.endsWith('Default')) return iconName.slice(0, -'Default'.length);\n\treturn iconName;\n}\n\nconst noCentralIconsBarrelImport: TSESLint.RuleModule<'barrelImport' | 'unsupportedImport', []> = {\n\tmeta: {\n\t\ttype: 'problem',\n\t\tdocs: {\n\t\t\tdescription:\n\t\t\t\t'Disallow barrel imports from @central-icons-react and @central-icons-react-native packages; use direct subpath imports instead',\n\t\t},\n\t\tfixable: 'code',\n\t\tschema: [],\n\t\tmessages: {\n\t\t\tbarrelImport:\n\t\t\t\t'Avoid barrel imports from `{{source}}`. Import icons directly from `{{source}}/<IconName>` to keep the bundler from opening thousands of icon files.',\n\t\t\tunsupportedImport:\n\t\t\t\t'Only named icon imports can be autofixed. Use direct subpath default imports from `{{source}}/<IconName>`.',\n\t\t},\n\t},\n\tdefaultOptions: [],\n\tcreate(context) {\n\t\treturn {\n\t\t\tImportDeclaration(node) {\n\t\t\t\tconst source = node.source.value;\n\t\t\t\tif (typeof source !== 'string' || !CENTRAL_ICONS_PACKAGE_RE.test(source)) return;\n\n\t\t\t\tconst namedSpecifiers = node.specifiers.filter((specifier) => specifier.type === 'ImportSpecifier');\n\t\t\t\tif (namedSpecifiers.length === 0 || namedSpecifiers.length !== node.specifiers.length) {\n\t\t\t\t\tcontext.report({\n\t\t\t\t\t\tnode,\n\t\t\t\t\t\tmessageId: 'unsupportedImport',\n\t\t\t\t\t\tdata: { source },\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tcontext.report({\n\t\t\t\t\tnode,\n\t\t\t\t\tmessageId: 'barrelImport',\n\t\t\t\t\tdata: { source },\n\t\t\t\t\tfix(fixer) {\n\t\t\t\t\t\tconst quote = node.source.raw.startsWith(\"'\") ? \"'\" : '\"';\n\t\t\t\t\t\tconst fixedImports = namedSpecifiers.map((specifier) => {\n\t\t\t\t\t\t\tconst imported = specifier.imported;\n\t\t\t\t\t\t\tconst importedName = imported.type === 'Identifier' ? imported.name : imported.value;\n\t\t\t\t\t\t\tconst localName = specifier.local.name;\n\t\t\t\t\t\t\tconst typePrefix = node.importKind === 'type' || specifier.importKind === 'type' ? 'type ' : '';\n\t\t\t\t\t\t\tconst subpath = centralIconSubpath(importedName);\n\t\t\t\t\t\t\treturn `import ${typePrefix}${localName} from ${quote}${source}/${subpath}${quote};`;\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn fixer.replaceText(node, fixedImports.join('\\n'));\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t},\n\t\t};\n\t},\n};\n\nconst plugin: TSESLint.FlatConfig.Plugin = {\n\tmeta: {\n\t\tname: 'eslint-plugin-mahir-central-icons',\n\t\tversion: '1.0.0',\n\t},\n\trules: {\n\t\t'no-central-icons-barrel-import': noCentralIconsBarrelImport,\n\t},\n};\n\nexport default plugin;\n"],"mappings":";AAEA,MAAM,2BAA2B;AAEjC,SAAS,mBAAmB,UAAkB;CAC7C,IAAI,SAAS,SAAS,SAAS,GAAG,OAAO,SAAS,MAAM,GAAG,EAAiB;CAC5E,OAAO;AACR;AAyDA,MAAM,SAAqC;CAC1C,MAAM;EACL,MAAM;EACN,SAAS;CACV;CACA,OAAO,EACN,kCAAkC;EA5DnC,MAAM;GACL,MAAM;GACN,MAAM,EACL,aACC,iIACF;GACA,SAAS;GACT,QAAQ,CAAC;GACT,UAAU;IACT,cACC;IACD,mBACC;GACF;EACD;EACA,gBAAgB,CAAC;EACjB,OAAO,SAAS;GACf,OAAO,EACN,kBAAkB,MAAM;IACvB,MAAM,SAAS,KAAK,OAAO;IAC3B,IAAI,OAAO,WAAW,YAAY,CAAC,yBAAyB,KAAK,MAAM,GAAG;IAE1E,MAAM,kBAAkB,KAAK,WAAW,QAAQ,cAAc,UAAU,SAAS,iBAAiB;IAClG,IAAI,gBAAgB,WAAW,KAAK,gBAAgB,WAAW,KAAK,WAAW,QAAQ;KACtF,QAAQ,OAAO;MACd;MACA,WAAW;MACX,MAAM,EAAE,OAAO;KAChB,CAAC;KACD;IACD;IAEA,QAAQ,OAAO;KACd;KACA,WAAW;KACX,MAAM,EAAE,OAAO;KACf,IAAI,OAAO;MACV,MAAM,QAAQ,KAAK,OAAO,IAAI,WAAW,GAAG,IAAI,MAAM;MACtD,MAAM,eAAe,gBAAgB,KAAK,cAAc;OACvD,MAAM,WAAW,UAAU;OAC3B,MAAM,eAAe,SAAS,SAAS,eAAe,SAAS,OAAO,SAAS;OAC/E,MAAM,YAAY,UAAU,MAAM;OAClC,MAAM,aAAa,KAAK,eAAe,UAAU,UAAU,eAAe,SAAS,UAAU;OAC7F,MAAM,UAAU,mBAAmB,YAAY;OAC/C,OAAO,UAAU,aAAa,UAAU,QAAQ,QAAQ,OAAO,GAAG,UAAU,MAAM;MACnF,CAAC;MACD,OAAO,MAAM,YAAY,MAAM,aAAa,KAAK,IAAI,CAAC;KACvD;IACD,CAAC;GACF,EACD;EACD;CAS4D,EAC5D;AACD"}
@@ -0,0 +1,6 @@
1
+ import { TSESLint } from "@typescript-eslint/utils";
2
+ //#region src/plugins/i18n.d.ts
3
+ declare const plugin: TSESLint.FlatConfig.Plugin;
4
+ //#endregion
5
+ export { plugin as default };
6
+ //# sourceMappingURL=i18n.d.ts.map
@@ -0,0 +1,58 @@
1
+ //#region src/plugins/i18n.ts
2
+ const plugin = {
3
+ meta: {
4
+ name: "eslint-plugin-mahir-i18n",
5
+ version: "1.0.0"
6
+ },
7
+ rules: {
8
+ "static-t-arguments": {
9
+ meta: {
10
+ type: "problem",
11
+ docs: { description: "Require t() calls to use static string literals so next-intl can extract messages at build time" },
12
+ schema: [],
13
+ messages: { staticArgument: "`t()` must receive a static string literal. Dynamic expressions cannot be extracted by next-intl. Use separate `t(\"Key\")` calls instead." }
14
+ },
15
+ defaultOptions: [],
16
+ create(context) {
17
+ return { CallExpression(node) {
18
+ if (node.callee.type !== "Identifier" || node.callee.name !== "t") return;
19
+ if (node.arguments.length === 0) return;
20
+ const firstArg = node.arguments[0];
21
+ if (firstArg.type !== "Literal" || typeof firstArg.value !== "string") context.report({
22
+ node: firstArg,
23
+ messageId: "staticArgument"
24
+ });
25
+ } };
26
+ }
27
+ },
28
+ "no-t-as-parameter": {
29
+ meta: {
30
+ type: "problem",
31
+ docs: { description: "Disallow passing the `t` translation function as an argument to other functions or components" },
32
+ schema: [],
33
+ messages: { noTParam: "Do not pass `t` as an argument. Call `useExtracted()` or `getExtracted()` directly in the consuming component/function instead." }
34
+ },
35
+ defaultOptions: [],
36
+ create(context) {
37
+ return {
38
+ CallExpression(node) {
39
+ for (const arg of node.arguments) if (arg.type === "Identifier" && arg.name === "t") context.report({
40
+ node: arg,
41
+ messageId: "noTParam"
42
+ });
43
+ },
44
+ JSXAttribute(node) {
45
+ if (node.value?.type === "JSXExpressionContainer" && node.value.expression.type === "Identifier" && node.value.expression.name === "t") context.report({
46
+ node: node.value.expression,
47
+ messageId: "noTParam"
48
+ });
49
+ }
50
+ };
51
+ }
52
+ }
53
+ }
54
+ };
55
+
56
+ //#endregion
57
+ export { plugin as default };
58
+ //# sourceMappingURL=i18n.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i18n.js","names":[],"sources":["../../src/plugins/i18n.ts"],"sourcesContent":["import type { TSESLint } from '@typescript-eslint/utils';\n\nconst staticTArguments: TSESLint.RuleModule<'staticArgument', []> = {\n\tmeta: {\n\t\ttype: 'problem',\n\t\tdocs: {\n\t\t\tdescription: 'Require t() calls to use static string literals so next-intl can extract messages at build time',\n\t\t},\n\t\tschema: [],\n\t\tmessages: {\n\t\t\tstaticArgument:\n\t\t\t\t'`t()` must receive a static string literal. Dynamic expressions cannot be extracted by next-intl. Use separate `t(\"Key\")` calls instead.',\n\t\t},\n\t},\n\tdefaultOptions: [],\n\tcreate(context) {\n\t\treturn {\n\t\t\tCallExpression(node) {\n\t\t\t\tif (node.callee.type !== 'Identifier' || node.callee.name !== 't') return;\n\t\t\t\tif (node.arguments.length === 0) return;\n\t\t\t\tconst firstArg = node.arguments[0];\n\t\t\t\tif (firstArg.type !== 'Literal' || typeof firstArg.value !== 'string')\n\t\t\t\t\tcontext.report({ node: firstArg, messageId: 'staticArgument' });\n\t\t\t},\n\t\t};\n\t},\n};\n\nconst noTAsParameter: TSESLint.RuleModule<'noTParam', []> = {\n\tmeta: {\n\t\ttype: 'problem',\n\t\tdocs: {\n\t\t\tdescription: 'Disallow passing the `t` translation function as an argument to other functions or components',\n\t\t},\n\t\tschema: [],\n\t\tmessages: {\n\t\t\tnoTParam:\n\t\t\t\t'Do not pass `t` as an argument. Call `useExtracted()` or `getExtracted()` directly in the consuming component/function instead.',\n\t\t},\n\t},\n\tdefaultOptions: [],\n\tcreate(context) {\n\t\treturn {\n\t\t\tCallExpression(node) {\n\t\t\t\tfor (const arg of node.arguments)\n\t\t\t\t\tif (arg.type === 'Identifier' && arg.name === 't') context.report({ node: arg, messageId: 'noTParam' });\n\t\t\t},\n\t\t\tJSXAttribute(node) {\n\t\t\t\tif (\n\t\t\t\t\tnode.value?.type === 'JSXExpressionContainer' &&\n\t\t\t\t\tnode.value.expression.type === 'Identifier' &&\n\t\t\t\t\tnode.value.expression.name === 't'\n\t\t\t\t)\n\t\t\t\t\tcontext.report({ node: node.value.expression, messageId: 'noTParam' });\n\t\t\t},\n\t\t};\n\t},\n};\n\nconst plugin: TSESLint.FlatConfig.Plugin = {\n\tmeta: {\n\t\tname: 'eslint-plugin-mahir-i18n',\n\t\tversion: '1.0.0',\n\t},\n\trules: {\n\t\t'static-t-arguments': staticTArguments,\n\t\t'no-t-as-parameter': noTAsParameter,\n\t},\n};\n\nexport default plugin;\n"],"mappings":";AA2DA,MAAM,SAAqC;CAC1C,MAAM;EACL,MAAM;EACN,SAAS;CACV;CACA,OAAO;EACN,sBAAsB;GA9DvB,MAAM;IACL,MAAM;IACN,MAAM,EACL,aAAa,kGACd;IACA,QAAQ,CAAC;IACT,UAAU,EACT,gBACC,6IACF;GACD;GACA,gBAAgB,CAAC;GACjB,OAAO,SAAS;IACf,OAAO,EACN,eAAe,MAAM;KACpB,IAAI,KAAK,OAAO,SAAS,gBAAgB,KAAK,OAAO,SAAS,KAAK;KACnE,IAAI,KAAK,UAAU,WAAW,GAAG;KACjC,MAAM,WAAW,KAAK,UAAU;KAChC,IAAI,SAAS,SAAS,aAAa,OAAO,SAAS,UAAU,UAC5D,QAAQ,OAAO;MAAE,MAAM;MAAU,WAAW;KAAiB,CAAC;IAChE,EACD;GACD;EAwCsC;EACrC,qBAAqB;GArCtB,MAAM;IACL,MAAM;IACN,MAAM,EACL,aAAa,gGACd;IACA,QAAQ,CAAC;IACT,UAAU,EACT,UACC,kIACF;GACD;GACA,gBAAgB,CAAC;GACjB,OAAO,SAAS;IACf,OAAO;KACN,eAAe,MAAM;MACpB,KAAK,MAAM,OAAO,KAAK,WACtB,IAAI,IAAI,SAAS,gBAAgB,IAAI,SAAS,KAAK,QAAQ,OAAO;OAAE,MAAM;OAAK,WAAW;MAAW,CAAC;KACxG;KACA,aAAa,MAAM;MAClB,IACC,KAAK,OAAO,SAAS,4BACrB,KAAK,MAAM,WAAW,SAAS,gBAC/B,KAAK,MAAM,WAAW,SAAS,KAE/B,QAAQ,OAAO;OAAE,MAAM,KAAK,MAAM;OAAY,WAAW;MAAW,CAAC;KACvE;IACD;GACD;EAUmC;CACnC;AACD"}
@@ -0,0 +1,6 @@
1
+ import { TSESLint } from "@typescript-eslint/utils";
2
+ //#region src/plugins/native-tailwind.d.ts
3
+ declare const plugin: TSESLint.FlatConfig.Plugin;
4
+ //#endregion
5
+ export { plugin as default };
6
+ //# sourceMappingURL=native-tailwind.d.ts.map
@@ -0,0 +1,110 @@
1
+ //#region src/plugins/native-tailwind.ts
2
+ const plugin = {
3
+ meta: {
4
+ name: "eslint-plugin-mahir-native-tailwind",
5
+ version: "1.0.0"
6
+ },
7
+ rules: { "class-name-rules": {
8
+ meta: {
9
+ type: "problem",
10
+ docs: { description: "Disallow Tailwind flex-col, and standalone flex" },
11
+ fixable: "code",
12
+ schema: [],
13
+ messages: {
14
+ forbidden: "Class '{{cls}}' is the default in react-native, so no need to explicitly set it.",
15
+ flexOnly: "Class 'flex' should be removed or changed to 'flex-row' for explicit direction."
16
+ },
17
+ hasSuggestions: true
18
+ },
19
+ defaultOptions: [],
20
+ create(context) {
21
+ const FORBIDDEN = /* @__PURE__ */ new Set(["flex-col"]);
22
+ function reportAndFix(node, text, raw) {
23
+ const classes = text.trim().split(/\s+/);
24
+ const hasFlex = classes.includes("flex");
25
+ const hasFlexCol = classes.includes("flex-col");
26
+ const hasFlexRow = classes.includes("flex-row");
27
+ const offendingForbidden = classes.filter((cl) => FORBIDDEN.has(cl));
28
+ if (!hasFlex && offendingForbidden.length === 0) return;
29
+ if (hasFlex && hasFlexRow) {
30
+ context.report({
31
+ node,
32
+ messageId: "forbidden",
33
+ data: { cls: "flex, flex-row" },
34
+ fix(fixer) {
35
+ const finalClasses = classes.filter((cl) => cl !== "flex" && !FORBIDDEN.has(cl)).join(" ");
36
+ const quote = raw.startsWith("'") ? "'" : "\"";
37
+ return fixer.replaceText(node, `${quote}${finalClasses}${quote}`);
38
+ }
39
+ });
40
+ return;
41
+ }
42
+ if (hasFlex && hasFlexCol) {
43
+ context.report({
44
+ node,
45
+ messageId: "forbidden",
46
+ data: { cls: "flex, flex-col" },
47
+ fix(fixer) {
48
+ const finalClasses = classes.filter((cl) => cl !== "flex" && cl !== "flex-col" && !FORBIDDEN.has(cl)).join(" ");
49
+ const quote = raw.startsWith("'") ? "'" : "\"";
50
+ return fixer.replaceText(node, `${quote}${finalClasses}${quote}`);
51
+ }
52
+ });
53
+ return;
54
+ }
55
+ if (hasFlexCol && !hasFlex) {
56
+ context.report({
57
+ node,
58
+ messageId: "forbidden",
59
+ data: { cls: "flex-col" },
60
+ fix(fixer) {
61
+ const finalClasses = classes.filter((cl) => cl !== "flex-col" && !FORBIDDEN.has(cl)).join(" ");
62
+ const quote = raw.startsWith("'") ? "'" : "\"";
63
+ return fixer.replaceText(node, `${quote}${finalClasses}${quote}`);
64
+ }
65
+ });
66
+ return;
67
+ }
68
+ if (hasFlex && !hasFlexCol) {
69
+ context.report({
70
+ node,
71
+ messageId: "flexOnly",
72
+ data: { cls: "flex" },
73
+ suggest: [{
74
+ messageId: "flexOnly",
75
+ data: { cls: "flex" },
76
+ fix(fixer) {
77
+ const finalClasses = classes.map((cl) => cl === "flex" ? "flex-row" : cl).join(" ");
78
+ const quote = raw.startsWith("'") ? "'" : "\"";
79
+ return fixer.replaceText(node, `${quote}${finalClasses}${quote}`);
80
+ }
81
+ }]
82
+ });
83
+ return;
84
+ }
85
+ if (offendingForbidden.length > 0) context.report({
86
+ node,
87
+ messageId: "forbidden",
88
+ data: { cls: offendingForbidden.join(", ") },
89
+ fix(fixer) {
90
+ const finalClasses = classes.filter((cl) => !FORBIDDEN.has(cl)).join(" ");
91
+ const quote = raw.startsWith("'") ? "'" : "\"";
92
+ return fixer.replaceText(node, `${quote}${finalClasses}${quote}`);
93
+ }
94
+ });
95
+ }
96
+ return { JSXAttribute(attr) {
97
+ if (attr.name.type !== "JSXIdentifier" || attr.name.name !== "className") return;
98
+ if (attr.value?.type === "Literal" && typeof attr.value.value === "string") {
99
+ reportAndFix(attr.value, attr.value.value, attr.value.raw);
100
+ return;
101
+ }
102
+ if (attr.value?.type === "JSXExpressionContainer" && attr.value.expression.type === "Literal" && typeof attr.value.expression.value === "string") reportAndFix(attr.value.expression, attr.value.expression.value, attr.value.expression.raw);
103
+ } };
104
+ }
105
+ } }
106
+ };
107
+
108
+ //#endregion
109
+ export { plugin as default };
110
+ //# sourceMappingURL=native-tailwind.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-tailwind.js","names":[],"sources":["../../src/plugins/native-tailwind.ts"],"sourcesContent":["import type { TSESLint, TSESTree } from '@typescript-eslint/utils';\n\nconst classNameRules: TSESLint.RuleModule<'flexOnly' | 'forbidden', []> = {\n\tmeta: {\n\t\ttype: 'problem',\n\t\tdocs: {\n\t\t\tdescription: 'Disallow Tailwind flex-col, and standalone flex',\n\t\t},\n\t\tfixable: 'code',\n\t\tschema: [],\n\t\tmessages: {\n\t\t\tforbidden: \"Class '{{cls}}' is the default in react-native, so no need to explicitly set it.\",\n\t\t\tflexOnly: \"Class 'flex' should be removed or changed to 'flex-row' for explicit direction.\",\n\t\t},\n\t\thasSuggestions: true,\n\t},\n\tdefaultOptions: [],\n\tcreate(context) {\n\t\tconst FORBIDDEN = new Set(['flex-col']);\n\n\t\tfunction reportAndFix(node: TSESTree.Node, text: string, raw: string) {\n\t\t\tconst classes = text.trim().split(/\\s+/);\n\t\t\tconst hasFlex = classes.includes('flex');\n\t\t\tconst hasFlexCol = classes.includes('flex-col');\n\t\t\tconst hasFlexRow = classes.includes('flex-row');\n\t\t\tconst offendingForbidden = classes.filter((cl) => FORBIDDEN.has(cl));\n\n\t\t\tif (!hasFlex && offendingForbidden.length === 0) return;\n\n\t\t\tif (hasFlex && hasFlexRow) {\n\t\t\t\tcontext.report({\n\t\t\t\t\tnode,\n\t\t\t\t\tmessageId: 'forbidden',\n\t\t\t\t\tdata: { cls: 'flex, flex-row' },\n\t\t\t\t\tfix(fixer) {\n\t\t\t\t\t\tconst kept = classes.filter((cl) => cl !== 'flex' && !FORBIDDEN.has(cl));\n\t\t\t\t\t\tconst finalClasses = kept.join(' ');\n\t\t\t\t\t\tconst quote = raw.startsWith(\"'\") ? \"'\" : '\"';\n\t\t\t\t\t\treturn fixer.replaceText(node, `${quote}${finalClasses}${quote}`);\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (hasFlex && hasFlexCol) {\n\t\t\t\tcontext.report({\n\t\t\t\t\tnode,\n\t\t\t\t\tmessageId: 'forbidden',\n\t\t\t\t\tdata: { cls: 'flex, flex-col' },\n\t\t\t\t\tfix(fixer) {\n\t\t\t\t\t\tconst kept = classes.filter((cl) => cl !== 'flex' && cl !== 'flex-col' && !FORBIDDEN.has(cl));\n\t\t\t\t\t\tconst finalClasses = kept.join(' ');\n\t\t\t\t\t\tconst quote = raw.startsWith(\"'\") ? \"'\" : '\"';\n\t\t\t\t\t\treturn fixer.replaceText(node, `${quote}${finalClasses}${quote}`);\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (hasFlexCol && !hasFlex) {\n\t\t\t\tcontext.report({\n\t\t\t\t\tnode,\n\t\t\t\t\tmessageId: 'forbidden',\n\t\t\t\t\tdata: { cls: 'flex-col' },\n\t\t\t\t\tfix(fixer) {\n\t\t\t\t\t\tconst kept = classes.filter((cl) => cl !== 'flex-col' && !FORBIDDEN.has(cl));\n\t\t\t\t\t\tconst finalClasses = kept.join(' ');\n\t\t\t\t\t\tconst quote = raw.startsWith(\"'\") ? \"'\" : '\"';\n\t\t\t\t\t\treturn fixer.replaceText(node, `${quote}${finalClasses}${quote}`);\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (hasFlex && !hasFlexCol) {\n\t\t\t\tcontext.report({\n\t\t\t\t\tnode,\n\t\t\t\t\tmessageId: 'flexOnly',\n\t\t\t\t\tdata: { cls: 'flex' },\n\t\t\t\t\tsuggest: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmessageId: 'flexOnly',\n\t\t\t\t\t\t\tdata: { cls: 'flex' },\n\t\t\t\t\t\t\tfix(fixer) {\n\t\t\t\t\t\t\t\tconst replacedClasses = classes.map((cl) => (cl === 'flex' ? 'flex-row' : cl));\n\t\t\t\t\t\t\t\tconst finalClasses = replacedClasses.join(' ');\n\t\t\t\t\t\t\t\tconst quote = raw.startsWith(\"'\") ? \"'\" : '\"';\n\t\t\t\t\t\t\t\treturn fixer.replaceText(node, `${quote}${finalClasses}${quote}`);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (offendingForbidden.length > 0) {\n\t\t\t\tcontext.report({\n\t\t\t\t\tnode,\n\t\t\t\t\tmessageId: 'forbidden',\n\t\t\t\t\tdata: { cls: offendingForbidden.join(', ') },\n\t\t\t\t\tfix(fixer) {\n\t\t\t\t\t\tconst kept = classes.filter((cl) => !FORBIDDEN.has(cl));\n\t\t\t\t\t\tconst finalClasses = kept.join(' ');\n\t\t\t\t\t\tconst quote = raw.startsWith(\"'\") ? \"'\" : '\"';\n\t\t\t\t\t\treturn fixer.replaceText(node, `${quote}${finalClasses}${quote}`);\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tJSXAttribute(attr) {\n\t\t\t\tif (attr.name.type !== 'JSXIdentifier' || attr.name.name !== 'className') return;\n\n\t\t\t\tif (attr.value?.type === 'Literal' && typeof attr.value.value === 'string') {\n\t\t\t\t\treportAndFix(attr.value, attr.value.value, attr.value.raw);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\tattr.value?.type === 'JSXExpressionContainer' &&\n\t\t\t\t\tattr.value.expression.type === 'Literal' &&\n\t\t\t\t\ttypeof attr.value.expression.value === 'string'\n\t\t\t\t)\n\t\t\t\t\treportAndFix(attr.value.expression, attr.value.expression.value, attr.value.expression.raw);\n\t\t\t},\n\t\t};\n\t},\n};\n\nconst plugin: TSESLint.FlatConfig.Plugin = {\n\tmeta: {\n\t\tname: 'eslint-plugin-mahir-native-tailwind',\n\t\tversion: '1.0.0',\n\t},\n\trules: {\n\t\t'class-name-rules': classNameRules,\n\t},\n};\n\nexport default plugin;\n"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { TSESLint } from "@typescript-eslint/utils";
2
+ //#region src/react.d.ts
3
+ declare const config: TSESLint.FlatConfig.ConfigArray;
4
+ //#endregion
5
+ export { config as default };
6
+ //# sourceMappingURL=react.d.ts.map
package/dist/react.js ADDED
@@ -0,0 +1,65 @@
1
+ import config$1 from "./jsx.js";
2
+ import globals from "globals";
3
+ import eslintPluginReactHooks from "eslint-plugin-react-hooks";
4
+
5
+ //#region src/react.ts
6
+ const rules = {
7
+ "react-hooks/exhaustive-deps": 2,
8
+ "react-hooks/rules-of-hooks": 2,
9
+ "react-hooks/immutability": 2,
10
+ "react-hooks/purity": 2,
11
+ "react-hooks/refs": 2,
12
+ "react-hooks/set-state-in-render": 2,
13
+ "react/boolean-prop-naming": 2,
14
+ "react/button-has-type": 2,
15
+ "react/hook-use-state": 2,
16
+ "react/iframe-missing-sandbox": 2,
17
+ "react/no-access-state-in-setstate": 2,
18
+ "react/no-arrow-function-lifecycle": 2,
19
+ "react/no-children-prop": 2,
20
+ "react/no-danger": 2,
21
+ "react/no-danger-with-children": 2,
22
+ "react/no-deprecated": 2,
23
+ "react/no-did-mount-set-state": 2,
24
+ "react/no-did-update-set-state": 2,
25
+ "react/no-direct-mutation-state": 2,
26
+ "react/no-find-dom-node": 2,
27
+ "react/no-invalid-html-attribute": 2,
28
+ "react/no-is-mounted": 2,
29
+ "react/no-namespace": 2,
30
+ "react/no-redundant-should-component-update": 2,
31
+ "react/no-render-return-value": 2,
32
+ "react/no-set-state": 2,
33
+ "react/no-string-refs": 2,
34
+ "react/no-this-in-sfc": 2,
35
+ "react/no-typos": 2,
36
+ "react/no-unknown-property": 2,
37
+ "react/no-unsafe": 2,
38
+ "react/no-unstable-nested-components": 2,
39
+ "react/no-unused-class-component-methods": 2,
40
+ "react/no-unused-state": 2,
41
+ "react/no-will-update-set-state": 2,
42
+ "react/prefer-es6-class": 2,
43
+ "react/prefer-read-only-props": 2,
44
+ "react/prefer-stateless-function": [2, { ignorePureComponents: true }],
45
+ "react/require-render-return": 2,
46
+ "react/sort-comp": 2,
47
+ "react/state-in-constructor": [2, "always"],
48
+ "react/static-property-placement": 2,
49
+ "react/void-dom-elements-no-children": 2
50
+ };
51
+ const settings = { react: { version: "detect" } };
52
+ const config = [...config$1, {
53
+ name: "mahir/react",
54
+ languageOptions: { globals: {
55
+ ...globals.serviceworker,
56
+ ...globals.browser
57
+ } },
58
+ plugins: { "react-hooks": eslintPluginReactHooks },
59
+ rules,
60
+ settings
61
+ }];
62
+
63
+ //#endregion
64
+ export { config as default };
65
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.js","names":["jsx"],"sources":["../src/react.ts"],"sourcesContent":["import eslintPluginReactHooks from 'eslint-plugin-react-hooks';\nimport globals from 'globals';\n\nimport jsx from './jsx.js';\n\nimport type { TSESLint } from '@typescript-eslint/utils';\n\nconst rules: TSESLint.FlatConfig.Rules = {\n\t'react-hooks/exhaustive-deps': 2,\n\t'react-hooks/rules-of-hooks': 2,\n\t'react-hooks/immutability': 2,\n\t'react-hooks/purity': 2,\n\t'react-hooks/refs': 2,\n\t// 'react-hooks/set-state-in-effect': 2,\n\t'react-hooks/set-state-in-render': 2,\n\t'react/boolean-prop-naming': 2,\n\t'react/button-has-type': 2,\n\t'react/hook-use-state': 2,\n\t'react/iframe-missing-sandbox': 2,\n\t'react/no-access-state-in-setstate': 2,\n\t'react/no-arrow-function-lifecycle': 2,\n\t'react/no-children-prop': 2,\n\t'react/no-danger': 2,\n\t'react/no-danger-with-children': 2,\n\t'react/no-deprecated': 2,\n\t'react/no-did-mount-set-state': 2,\n\t'react/no-did-update-set-state': 2,\n\t'react/no-direct-mutation-state': 2,\n\t'react/no-find-dom-node': 2,\n\t'react/no-invalid-html-attribute': 2,\n\t'react/no-is-mounted': 2,\n\t'react/no-namespace': 2,\n\t'react/no-redundant-should-component-update': 2,\n\t'react/no-render-return-value': 2,\n\t'react/no-set-state': 2,\n\t'react/no-string-refs': 2,\n\t'react/no-this-in-sfc': 2,\n\t'react/no-typos': 2,\n\t'react/no-unknown-property': 2,\n\t'react/no-unsafe': 2,\n\t'react/no-unstable-nested-components': 2,\n\t'react/no-unused-class-component-methods': 2,\n\t'react/no-unused-state': 2,\n\t'react/no-will-update-set-state': 2,\n\t'react/prefer-es6-class': 2,\n\t'react/prefer-read-only-props': 2,\n\t'react/prefer-stateless-function': [\n\t\t2,\n\t\t{\n\t\t\tignorePureComponents: true,\n\t\t},\n\t],\n\t'react/require-render-return': 2,\n\t'react/sort-comp': 2,\n\t'react/state-in-constructor': [2, 'always'],\n\t'react/static-property-placement': 2,\n\t'react/void-dom-elements-no-children': 2,\n};\n\nconst settings: TSESLint.FlatConfig.Settings = {\n\treact: {\n\t\tversion: 'detect',\n\t},\n};\n\nconst config: TSESLint.FlatConfig.ConfigArray = [\n\t...jsx,\n\t{\n\t\tname: 'mahir/react',\n\t\tlanguageOptions: {\n\t\t\tglobals: {\n\t\t\t\t...globals.serviceworker,\n\t\t\t\t...globals.browser,\n\t\t\t},\n\t\t},\n\t\tplugins: {\n\t\t\t'react-hooks': eslintPluginReactHooks,\n\t\t},\n\t\trules,\n\t\tsettings,\n\t},\n];\n\nexport default config;\n"],"mappings":";;;;;AAOA,MAAM,QAAmC;CACxC,+BAA+B;CAC/B,8BAA8B;CAC9B,4BAA4B;CAC5B,sBAAsB;CACtB,oBAAoB;CAEpB,mCAAmC;CACnC,6BAA6B;CAC7B,yBAAyB;CACzB,wBAAwB;CACxB,gCAAgC;CAChC,qCAAqC;CACrC,qCAAqC;CACrC,0BAA0B;CAC1B,mBAAmB;CACnB,iCAAiC;CACjC,uBAAuB;CACvB,gCAAgC;CAChC,iCAAiC;CACjC,kCAAkC;CAClC,0BAA0B;CAC1B,mCAAmC;CACnC,uBAAuB;CACvB,sBAAsB;CACtB,8CAA8C;CAC9C,gCAAgC;CAChC,sBAAsB;CACtB,wBAAwB;CACxB,wBAAwB;CACxB,kBAAkB;CAClB,6BAA6B;CAC7B,mBAAmB;CACnB,uCAAuC;CACvC,2CAA2C;CAC3C,yBAAyB;CACzB,kCAAkC;CAClC,0BAA0B;CAC1B,gCAAgC;CAChC,mCAAmC,CAClC,GACA,EACC,sBAAsB,KACvB,CACD;CACA,+BAA+B;CAC/B,mBAAmB;CACnB,8BAA8B,CAAC,GAAG,QAAQ;CAC1C,mCAAmC;CACnC,uCAAuC;AACxC;AAEA,MAAM,WAAyC,EAC9C,OAAO,EACN,SAAS,SACV,EACD;AAEA,MAAM,SAA0C,CAC/C,GAAGA,UACH;CACC,MAAM;CACN,iBAAiB,EAChB,SAAS;EACR,GAAG,QAAQ;EACX,GAAG,QAAQ;CACZ,EACD;CACA,SAAS,EACR,eAAe,uBAChB;CACA;CACA;AACD,CACD"}
@@ -0,0 +1,6 @@
1
+ import { TSESLint } from "@typescript-eslint/utils";
2
+ //#region src/tailwind.d.ts
3
+ declare const config: TSESLint.FlatConfig.ConfigArray;
4
+ //#endregion
5
+ export { config as default };
6
+ //# sourceMappingURL=tailwind.d.ts.map
@@ -0,0 +1,18 @@
1
+ import eslintPluginBetterTailwindcss from "eslint-plugin-better-tailwindcss";
2
+
3
+ //#region src/tailwind.ts
4
+ const config = [{
5
+ name: "mahir/tailwind",
6
+ settings: { "better-tailwindcss": { entryPoint: "app/globals.css" } },
7
+ plugins: { "better-tailwindcss": eslintPluginBetterTailwindcss },
8
+ rules: {
9
+ "better-tailwindcss/enforce-consistent-class-order": "warn",
10
+ "better-tailwindcss/no-unnecessary-whitespace": "warn",
11
+ "better-tailwindcss/enforce-canonical-classes": "warn",
12
+ "better-tailwindcss/no-unknown-classes": "error"
13
+ }
14
+ }];
15
+
16
+ //#endregion
17
+ export { config as default };
18
+ //# sourceMappingURL=tailwind.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tailwind.js","names":[],"sources":["../src/tailwind.ts"],"sourcesContent":["import eslintPluginBetterTailwindcss from 'eslint-plugin-better-tailwindcss';\n\nimport type { TSESLint } from '@typescript-eslint/utils';\n\nconst config: TSESLint.FlatConfig.ConfigArray = [\n\t{\n\t\tname: 'mahir/tailwind',\n\t\tsettings: {\n\t\t\t'better-tailwindcss': {\n\t\t\t\tentryPoint: 'app/globals.css',\n\t\t\t},\n\t\t},\n\t\tplugins: {\n\t\t\t'better-tailwindcss': eslintPluginBetterTailwindcss,\n\t\t},\n\t\trules: {\n\t\t\t'better-tailwindcss/enforce-consistent-class-order': 'warn',\n\t\t\t'better-tailwindcss/no-unnecessary-whitespace': 'warn',\n\t\t\t'better-tailwindcss/enforce-canonical-classes': 'warn',\n\t\t\t'better-tailwindcss/no-unknown-classes': 'error',\n\t\t},\n\t},\n];\n\nexport default config;\n"],"mappings":";;;AAIA,MAAM,SAA0C,CAC/C;CACC,MAAM;CACN,UAAU,EACT,sBAAsB,EACrB,YAAY,kBACb,EACD;CACA,SAAS,EACR,sBAAsB,8BACvB;CACA,OAAO;EACN,qDAAqD;EACrD,gDAAgD;EAChD,gDAAgD;EAChD,yCAAyC;CAC1C;AACD,CACD"}
@@ -0,0 +1,6 @@
1
+ import { TSESLint } from "@typescript-eslint/utils";
2
+ //#region src/tsdoc.d.ts
3
+ declare const config: TSESLint.FlatConfig.ConfigArray;
4
+ //#endregion
5
+ export { config as default };
6
+ //# sourceMappingURL=tsdoc.d.ts.map
package/dist/tsdoc.js ADDED
@@ -0,0 +1,21 @@
1
+ import config$1 from "./jsdoc.js";
2
+ import eslintPluginTsdoc from "eslint-plugin-tsdoc";
3
+
4
+ //#region src/tsdoc.ts
5
+ const rules = {
6
+ "jsdoc/check-tag-names": 0,
7
+ "jsdoc/require-property-type": 0,
8
+ "jsdoc/no-undefined-types": 0,
9
+ "tsdoc/syntax": 1
10
+ };
11
+ const settings = { jsdoc: { mode: "typescript" } };
12
+ const config = [...config$1, {
13
+ name: "mahir/tsdoc",
14
+ plugins: { tsdoc: eslintPluginTsdoc },
15
+ rules,
16
+ settings
17
+ }];
18
+
19
+ //#endregion
20
+ export { config as default };
21
+ //# sourceMappingURL=tsdoc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tsdoc.js","names":["jsdoc"],"sources":["../src/tsdoc.ts"],"sourcesContent":["import eslintPluginTsdoc from 'eslint-plugin-tsdoc';\n\nimport jsdoc from './jsdoc.js';\n\nimport type { TSESLint } from '@typescript-eslint/utils';\n\nconst rules: TSESLint.FlatConfig.Rules = {\n\t'jsdoc/check-tag-names': 0,\n\t'jsdoc/require-property-type': 0,\n\t'jsdoc/no-undefined-types': 0,\n\t'tsdoc/syntax': 1,\n};\n\nconst settings: TSESLint.FlatConfig.Settings = {\n\tjsdoc: {\n\t\tmode: 'typescript',\n\t},\n};\n\nconst config: TSESLint.FlatConfig.ConfigArray = [\n\t...jsdoc,\n\t{\n\t\tname: 'mahir/tsdoc',\n\t\tplugins: {\n\t\t\ttsdoc: eslintPluginTsdoc,\n\t\t},\n\t\trules,\n\t\tsettings,\n\t},\n];\n\nexport default config;\n"],"mappings":";;;;AAMA,MAAM,QAAmC;CACxC,yBAAyB;CACzB,+BAA+B;CAC/B,4BAA4B;CAC5B,gBAAgB;AACjB;AAEA,MAAM,WAAyC,EAC9C,OAAO,EACN,MAAM,aACP,EACD;AAEA,MAAM,SAA0C,CAC/C,GAAGA,UACH;CACC,MAAM;CACN,SAAS,EACR,OAAO,kBACR;CACA;CACA;AACD,CACD"}
@@ -0,0 +1,6 @@
1
+ import { TSESLint } from "@typescript-eslint/utils";
2
+ //#region src/typescript.d.ts
3
+ declare const config: TSESLint.FlatConfig.ConfigArray;
4
+ //#endregion
5
+ export { config as default };
6
+ //# sourceMappingURL=typescript.d.ts.map