@santi020k/eslint-config-basic 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agent/rules/context.md +78 -0
- package/.agent/rules/guidelines.md +124 -0
- package/.editorconfig +13 -0
- package/.env.example +8 -0
- package/.github/CODEOWNERS +2 -0
- package/.github/DISCUSSION_TEMPLATE/rfcs.yml +21 -0
- package/.github/DISCUSSION_TEMPLATE/technical-discussions.yml +21 -0
- package/.github/FUNDING.yml +2 -0
- package/.github/ISSUE_TEMPLATE/README.md +13 -0
- package/.github/ISSUE_TEMPLATE/bug_report.yml +69 -0
- package/.github/ISSUE_TEMPLATE/config.yml +8 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +43 -0
- package/.github/ISSUE_TEMPLATE/question.yml +22 -0
- package/.github/SECURITY.md +12 -0
- package/.github/SPONSORSHIPS.md +27 -0
- package/.github/dependabot.yml +45 -0
- package/.github/labeler.yml +46 -0
- package/.github/pull_request_template.md +56 -0
- package/.github/workflows/assign-issues.yml +18 -0
- package/.github/workflows/audit.yml +22 -0
- package/.github/workflows/build.yml +29 -0
- package/.github/workflows/codeql.yml +40 -0
- package/.github/workflows/docs.yml +49 -0
- package/.github/workflows/labeler.yml +18 -0
- package/.github/workflows/publish.yml +24 -0
- package/.github/workflows/release.yml +35 -0
- package/.github/workflows/size-check.yml +23 -0
- package/.github/workflows/stale.yml +31 -0
- package/.nvmrc +1 -0
- package/.vscode/extensions.json +10 -0
- package/.vscode/settings.json +55 -0
- package/CHANGELOG.md +16 -0
- package/CONTRIBUTING.md +194 -0
- package/DEVELOPMENT.md +4 -0
- package/LICENSE +21 -0
- package/README.md +275 -0
- package/config/.husky/commit-msg +9 -0
- package/config/.husky/pre-commit +1 -0
- package/config/.husky/pre-push +1 -0
- package/config/.husky/prepare-commit-msg +1 -0
- package/cspell.config.yaml +2 -0
- package/eslint.config.js +21 -0
- package/llms.txt +72 -0
- package/package.json +61 -0
- package/packages/astro/README.md +13 -0
- package/packages/astro/package.json +45 -0
- package/packages/astro/src/ambient.d.ts +10 -0
- package/packages/astro/src/index.ts +18 -0
- package/packages/astro/src/rules.ts +29 -0
- package/packages/astro/tsconfig.json +9 -0
- package/packages/astro/tsup.config.ts +11 -0
- package/packages/basic/README.md +33 -0
- package/packages/basic/package.json +55 -0
- package/packages/basic/src/index.ts +110 -0
- package/packages/basic/tsconfig.json +9 -0
- package/packages/basic/tsup.config.ts +18 -0
- package/packages/core/README.md +14 -0
- package/packages/core/index.ts +14 -0
- package/packages/core/package.json +61 -0
- package/packages/core/src/ambient.d.ts +61 -0
- package/packages/core/src/index.ts +75 -0
- package/packages/core/src/rules.ts +157 -0
- package/packages/core/src/settings/gitignore.ts +10 -0
- package/packages/core/src/settings/index.ts +1 -0
- package/packages/core/src/types.ts +57 -0
- package/packages/core/src/utils/index.ts +28 -0
- package/packages/core/tsconfig.json +9 -0
- package/packages/core/tsup.config.ts +10 -0
- package/packages/expo/README.md +13 -0
- package/packages/expo/package.json +48 -0
- package/packages/expo/src/ambient.d.ts +3 -0
- package/packages/expo/src/index.ts +39 -0
- package/packages/expo/tsconfig.json +9 -0
- package/packages/expo/tsup.config.ts +11 -0
- package/packages/nest/package.json +45 -0
- package/packages/nest/src/ambient.d.ts +14 -0
- package/packages/nest/src/index.ts +20 -0
- package/packages/nest/src/rules.ts +15 -0
- package/packages/nest/tsconfig.json +9 -0
- package/packages/nest/tsup.config.ts +11 -0
- package/packages/next/README.md +13 -0
- package/packages/next/package.json +47 -0
- package/packages/next/src/index.ts +31 -0
- package/packages/next/src/rules.ts +16 -0
- package/packages/next/tsconfig.json +9 -0
- package/packages/next/tsup.config.ts +10 -0
- package/packages/optionals/README.md +18 -0
- package/packages/optionals/package.json +55 -0
- package/packages/optionals/src/ambient.d.ts +25 -0
- package/packages/optionals/src/cspell.ts +14 -0
- package/packages/optionals/src/i18next.ts +19 -0
- package/packages/optionals/src/index.ts +8 -0
- package/packages/optionals/src/markdown.ts +66 -0
- package/packages/optionals/src/mdx.ts +40 -0
- package/packages/optionals/src/stencil.ts +48 -0
- package/packages/optionals/src/tailwind.ts +11 -0
- package/packages/optionals/src/vitest.ts +61 -0
- package/packages/optionals/tsconfig.json +9 -0
- package/packages/optionals/tsup.config.ts +11 -0
- package/packages/playground/README.md +14 -0
- package/packages/playground/package.json +17 -0
- package/packages/playground/src/astro/eslint.config.js +4 -0
- package/packages/playground/src/js/eslint.config.js +4 -0
- package/packages/playground/src/js/index.test.js +63 -0
- package/packages/playground/src/mdx/eslint.config.js +4 -0
- package/packages/playground/src/mdx/index.mdx +115 -0
- package/packages/playground/src/react/eslint.config.js +4 -0
- package/packages/playground/src/react/index.test.jsx +130 -0
- package/packages/playground/src/ts/eslint.config.js +4 -0
- package/packages/playground/src/ts/index.test.ts +61 -0
- package/packages/playground/src/ts/tsconfig.json +3 -0
- package/packages/playground/tsconfig.json +9 -0
- package/packages/react/README.md +14 -0
- package/packages/react/index.ts +26 -0
- package/packages/react/package.json +49 -0
- package/packages/react/src/ambient.d.ts +23 -0
- package/packages/react/src/index.ts +52 -0
- package/packages/react/src/rules.ts +47 -0
- package/packages/react/tsconfig.json +9 -0
- package/packages/react/tsup.config.ts +10 -0
- package/packages/tests/README.md +17 -0
- package/packages/tests/package.json +21 -0
- package/packages/tests/src/__snapshots__/snapshots.test.ts.snap +654 -0
- package/packages/tests/src/composition.test.ts +171 -0
- package/packages/tests/src/configs.test.ts +118 -0
- package/packages/tests/src/rules.test.ts +60 -0
- package/packages/tests/src/snapshots.test.ts +126 -0
- package/packages/tests/tsconfig.json +10 -0
- package/packages/tests/vitest.config.ts +8 -0
- package/packages/typescript/README.md +14 -0
- package/packages/typescript/package.json +47 -0
- package/packages/typescript/src/index.ts +32 -0
- package/packages/typescript/src/rules.ts +36 -0
- package/packages/typescript/tsconfig.json +9 -0
- package/packages/typescript/tsup.config.ts +10 -0
- package/tsconfig.base.json +20 -0
- package/tsconfig.docs.json +18 -0
- package/turbo.json +19 -0
- package/typedoc.config.mjs +25 -0
- package/typedoc.markdown.mjs +26 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { fixupPluginRules } from '@eslint/compat'
|
|
2
|
+
import stencilPlugin from '@stencil-community/eslint-plugin'
|
|
3
|
+
import type { TSESLint } from '@typescript-eslint/utils'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Stencil ESLint configuration
|
|
7
|
+
* Enforces best practices for Stencil.js components
|
|
8
|
+
*/
|
|
9
|
+
export const stencil: TSESLint.FlatConfig.ConfigArray = [
|
|
10
|
+
{
|
|
11
|
+
name: 'optionals/stencil',
|
|
12
|
+
files: ['**/*.{tsx,ts}'],
|
|
13
|
+
plugins: {
|
|
14
|
+
'@stencil-community': fixupPluginRules({
|
|
15
|
+
rules: stencilPlugin.rules as Record<string, unknown>
|
|
16
|
+
} as Parameters<typeof fixupPluginRules>[0]) as unknown as TSESLint.FlatConfig.Plugin
|
|
17
|
+
},
|
|
18
|
+
rules: {
|
|
19
|
+
'@stencil-community/async-methods': 'error',
|
|
20
|
+
'@stencil-community/ban-prefix': ['error', ['stencil', 'stnl', 'st']],
|
|
21
|
+
'@stencil-community/decorators-context': 'error',
|
|
22
|
+
'@stencil-community/decorators-style': [
|
|
23
|
+
'error', {
|
|
24
|
+
prop: 'inline',
|
|
25
|
+
state: 'inline',
|
|
26
|
+
element: 'inline',
|
|
27
|
+
event: 'inline',
|
|
28
|
+
method: 'multiline',
|
|
29
|
+
watch: 'multiline',
|
|
30
|
+
listen: 'multiline'
|
|
31
|
+
}],
|
|
32
|
+
'@stencil-community/element-type': 'error',
|
|
33
|
+
'@stencil-community/host-data-deprecated': 'error',
|
|
34
|
+
'@stencil-community/methods-must-be-public': 'error',
|
|
35
|
+
'@stencil-community/no-unused-watch': 'error',
|
|
36
|
+
'@stencil-community/own-methods-must-be-private': 'error',
|
|
37
|
+
'@stencil-community/own-props-must-be-private': 'error',
|
|
38
|
+
'@stencil-community/prefer-vdom-listener': 'error',
|
|
39
|
+
'@stencil-community/props-must-be-public': 'error',
|
|
40
|
+
'@stencil-community/props-must-be-readonly': 'error',
|
|
41
|
+
'@stencil-community/render-returns-host': 'error',
|
|
42
|
+
'@stencil-community/required-jsdoc': 'error',
|
|
43
|
+
'@stencil-community/reserved-member-names': 'error',
|
|
44
|
+
'@stencil-community/single-export': 'error',
|
|
45
|
+
'@stencil-community/strict-mutable': 'error'
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
]
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import pluginTailwind from 'eslint-plugin-tailwindcss'
|
|
2
|
+
|
|
3
|
+
import type { TSESLint } from '@typescript-eslint/utils'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Tailwind CSS ESLint configuration
|
|
7
|
+
* Enforces Tailwind CSS best practices
|
|
8
|
+
*/
|
|
9
|
+
export const tailwind: TSESLint.FlatConfig.ConfigArray = [
|
|
10
|
+
...(pluginTailwind.configs['flat/recommended'] as TSESLint.FlatConfig.ConfigArray)
|
|
11
|
+
]
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import testingLibrary from 'eslint-plugin-testing-library'
|
|
2
|
+
import pluginVitest from 'eslint-plugin-vitest'
|
|
3
|
+
import globals from 'globals'
|
|
4
|
+
|
|
5
|
+
import { fixupPluginRules } from '@eslint/compat'
|
|
6
|
+
import type { TSESLint } from '@typescript-eslint/utils'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Vitest ESLint configuration
|
|
10
|
+
* Provides linting rules for Vitest test files with best practices
|
|
11
|
+
*/
|
|
12
|
+
export const vitest: TSESLint.FlatConfig.ConfigArray = [
|
|
13
|
+
{
|
|
14
|
+
name: 'optionals/vitest',
|
|
15
|
+
files: [
|
|
16
|
+
'tests/**/*.{js,ts,jsx,tsx}',
|
|
17
|
+
'**/__tests__/**/*.{js,ts,jsx,tsx}',
|
|
18
|
+
'**/__mocks__/**/*.{js,ts,jsx,tsx}',
|
|
19
|
+
'**/test/**/*.{js,ts,jsx,tsx}',
|
|
20
|
+
'**/spec/**/*.{js,ts,jsx,tsx}',
|
|
21
|
+
'**/__spec__/**/*.{js,ts,jsx,tsx}',
|
|
22
|
+
'**/*.test.{js,ts,jsx,tsx}',
|
|
23
|
+
'**/*.spec.{js,ts,jsx,tsx}',
|
|
24
|
+
'vitest.config.{js,ts}'
|
|
25
|
+
],
|
|
26
|
+
languageOptions: {
|
|
27
|
+
globals: {
|
|
28
|
+
...globals.node
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
plugins: {
|
|
32
|
+
vitest: pluginVitest,
|
|
33
|
+
'testing-library': fixupPluginRules({
|
|
34
|
+
rules: testingLibrary.rules
|
|
35
|
+
} as unknown as Parameters<typeof fixupPluginRules>[0]) as unknown as TSESLint.FlatConfig.Plugin
|
|
36
|
+
},
|
|
37
|
+
rules: {
|
|
38
|
+
// Vitest recommended rules
|
|
39
|
+
...pluginVitest.configs.recommended.rules,
|
|
40
|
+
|
|
41
|
+
// Best practice rules for testing
|
|
42
|
+
'vitest/max-nested-describe': ['error', { max: 3 }],
|
|
43
|
+
'vitest/expect-expect': [
|
|
44
|
+
'error',
|
|
45
|
+
{
|
|
46
|
+
assertFunctionNames: ['expect', 'assert', 'should']
|
|
47
|
+
}
|
|
48
|
+
],
|
|
49
|
+
'vitest/no-identical-title': 'error',
|
|
50
|
+
'vitest/no-focused-tests': 'error',
|
|
51
|
+
'vitest/no-disabled-tests': 'warn',
|
|
52
|
+
'vitest/prefer-to-be': 'warn',
|
|
53
|
+
'vitest/prefer-to-have-length': 'warn',
|
|
54
|
+
'vitest/valid-expect': 'error',
|
|
55
|
+
|
|
56
|
+
// Disable some rules that conflict with test patterns
|
|
57
|
+
'@typescript-eslint/no-explicit-any': 'off',
|
|
58
|
+
'@stylistic/padding-line-between-statements': 'off'
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
]
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# @santi020k/eslint-config-playground
|
|
2
|
+
|
|
3
|
+
Internal playground package for testing ESLint configurations against real files.
|
|
4
|
+
|
|
5
|
+
## Description
|
|
6
|
+
|
|
7
|
+
This package contains various file types (React, Astro, MDX, TS) to verify that the ESLint rules are applied correctly in a real-world project structure.
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
Run linting on this package:
|
|
12
|
+
```bash
|
|
13
|
+
npm run lint -w @santi020k/eslint-config-playground
|
|
14
|
+
```
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@santi020k/eslint-config-playground",
|
|
3
|
+
"private": false,
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"lint": "eslint .",
|
|
8
|
+
"lint:fix": "eslint . --fix"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@santi020k/eslint-config-basic": "*",
|
|
12
|
+
"eslint": "^9.39.2",
|
|
13
|
+
"react": "^19.2.4",
|
|
14
|
+
"react-dom": "^19.2.4",
|
|
15
|
+
"typescript": "^5.9.3"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// test.js
|
|
2
|
+
|
|
3
|
+
// Function definitions to test various stylistic rules
|
|
4
|
+
const myFunction1 = () => {
|
|
5
|
+
const value = 10
|
|
6
|
+
|
|
7
|
+
if (value > 5) {
|
|
8
|
+
console.log('Value is greater than 5')
|
|
9
|
+
} else {
|
|
10
|
+
console.log('Value is 5 or less')
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const result = value > 5 ? 'High' : 'Low'
|
|
14
|
+
const array = [1, 2, 3]
|
|
15
|
+
|
|
16
|
+
array.forEach(item => {
|
|
17
|
+
console.log(item)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
return result
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Testing object and array formatting rules
|
|
24
|
+
const myObject = { a: 1, b: 2, c: 3 }
|
|
25
|
+
const myArray = [1, 2, 3, 4, 5]
|
|
26
|
+
|
|
27
|
+
// Testing padding and spacing rules
|
|
28
|
+
if (myArray.length > 0) {
|
|
29
|
+
console.log('Array is not empty')
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const myFunction2 = param => !!param
|
|
33
|
+
// Testing invalid typeof comparison
|
|
34
|
+
const count = 0
|
|
35
|
+
|
|
36
|
+
if (typeof count === 'number') {
|
|
37
|
+
console.log('Count is a number')
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Testing unused variables
|
|
41
|
+
// eslint-disable-next-line no-unused-vars, unused-imports/no-unused-vars
|
|
42
|
+
const unusedVar = 'This is unused'
|
|
43
|
+
|
|
44
|
+
// Function with multiple return statements
|
|
45
|
+
// eslint-disable-next-line no-unused-vars, unused-imports/no-unused-vars
|
|
46
|
+
const complexFunction = () => {
|
|
47
|
+
if (count > 10) return 'High'
|
|
48
|
+
|
|
49
|
+
if (count < 0) return 'Low'
|
|
50
|
+
|
|
51
|
+
return 'Medium'
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Testing no-use-before-define
|
|
55
|
+
myDefinedFunction()
|
|
56
|
+
|
|
57
|
+
// eslint-disable-next-line func-style
|
|
58
|
+
function myDefinedFunction() {
|
|
59
|
+
console.log('Function called before definition')
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Export statement to test sorting
|
|
63
|
+
export { myFunction1, myFunction2, myObject, myArray }
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "The Ultimate MDX Example"
|
|
3
|
+
description: "A complete overview of MDX capabilities with lorem ipsum content"
|
|
4
|
+
author: "Santiago Ipsum"
|
|
5
|
+
tags: ["mdx", "example", "components"]
|
|
6
|
+
date: "2025-04-21"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
import { Button, Alert, FancyBox } from '../components/UI'
|
|
10
|
+
import Note from '../components/Note'
|
|
11
|
+
import Chart from '../components/Chart'
|
|
12
|
+
|
|
13
|
+
## 🎢 Welcome to the MDX Playground
|
|
14
|
+
|
|
15
|
+
# Welcome to the MDX Playground 🎢
|
|
16
|
+
|
|
17
|
+
This is an **MDX** file. It's like Markdown, but on _steroids_ — powered by **JSX**. Let's explore all the features using some _Lorem Ipsum_.
|
|
18
|
+
|
|
19
|
+
## 🧩 Embedded JSX Components
|
|
20
|
+
|
|
21
|
+
You can embed React components directly:
|
|
22
|
+
|
|
23
|
+
<Alert type="success">This is a success alert using a custom component!</Alert>
|
|
24
|
+
|
|
25
|
+
## 📦 Importing Components
|
|
26
|
+
|
|
27
|
+
You can import components like `Note`, `FancyBox`, or even charts.
|
|
28
|
+
|
|
29
|
+
<Note>
|
|
30
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque feugiat.
|
|
31
|
+
</Note>
|
|
32
|
+
|
|
33
|
+
<FancyBox>
|
|
34
|
+
<h3>Fancy Box Title</h3>
|
|
35
|
+
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
|
|
36
|
+
</FancyBox>
|
|
37
|
+
|
|
38
|
+
## 🖼️ Images
|
|
39
|
+
|
|
40
|
+

|
|
41
|
+
|
|
42
|
+
## 🧮 Code Blocks
|
|
43
|
+
|
|
44
|
+
### JavaScript
|
|
45
|
+
|
|
46
|
+
```js
|
|
47
|
+
const greet = name => `Hello, ${name}!`
|
|
48
|
+
|
|
49
|
+
greet('santi020k')
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Bash
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npm install @mdx-js/react
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## 📊 Embedded Dynamic Chart
|
|
59
|
+
|
|
60
|
+
<Chart
|
|
61
|
+
title="Sample Chart"
|
|
62
|
+
data={[{ label: 'A', value: 10 }, { label: 'B', value: 20 }]}
|
|
63
|
+
/>
|
|
64
|
+
|
|
65
|
+
## 🔗 Links
|
|
66
|
+
|
|
67
|
+
Check out the [official MDX docs](https://mdxjs.com).
|
|
68
|
+
|
|
69
|
+
## 🗒️ Lists and Tables
|
|
70
|
+
|
|
71
|
+
### Bullet List
|
|
72
|
+
|
|
73
|
+
- Lorem ipsum
|
|
74
|
+
- Dolor sit amet
|
|
75
|
+
- Consectetur adipiscing
|
|
76
|
+
|
|
77
|
+
### Numbered List
|
|
78
|
+
|
|
79
|
+
1. First item
|
|
80
|
+
2. Second item
|
|
81
|
+
3. Third item
|
|
82
|
+
|
|
83
|
+
### Table
|
|
84
|
+
|
|
85
|
+
| Feature | Supported |
|
|
86
|
+
|----------------|-----------|
|
|
87
|
+
| Markdown | ✅ |
|
|
88
|
+
| JSX | ✅ |
|
|
89
|
+
| Components | ✅ |
|
|
90
|
+
| Frontmatter | ✅ |
|
|
91
|
+
|
|
92
|
+
## 🎉 Inline JSX
|
|
93
|
+
|
|
94
|
+
Here’s some inline JSX: `<span style={{ color: 'tomato' }}>Hello inline JSX!</span>`
|
|
95
|
+
|
|
96
|
+
## 📌 Export Metadata
|
|
97
|
+
|
|
98
|
+
You can also export metadata if needed:
|
|
99
|
+
|
|
100
|
+
```js
|
|
101
|
+
export const meta = {
|
|
102
|
+
layout: 'docs',
|
|
103
|
+
requiresAuth: false
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## 🧠 Conclusion
|
|
110
|
+
|
|
111
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque in odio vitae nunc luctus aliquet. MDX is powerful, flexible, and fun. Try it out in your next documentation or blog project!
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
---
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import React, {
|
|
2
|
+
useCallback,
|
|
3
|
+
useEffect,
|
|
4
|
+
useMemo,
|
|
5
|
+
useRef,
|
|
6
|
+
useState
|
|
7
|
+
} from 'react'
|
|
8
|
+
|
|
9
|
+
// Helper function to simulate fetching data
|
|
10
|
+
const fetchTodos = () => new Promise(resolve => {
|
|
11
|
+
setTimeout(() => {
|
|
12
|
+
resolve([
|
|
13
|
+
{ id: 1, text: 'Learn React', completed: true },
|
|
14
|
+
{
|
|
15
|
+
id: 2,
|
|
16
|
+
text: 'Build a Todo App',
|
|
17
|
+
completed: false
|
|
18
|
+
},
|
|
19
|
+
{ id: 3, text: 'Profit!', completed: false }
|
|
20
|
+
])
|
|
21
|
+
}, 1000)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
const TodoApp = () => {
|
|
25
|
+
const [todos, setTodos] = useState([])
|
|
26
|
+
const [filter, setFilter] = useState('all')
|
|
27
|
+
const [sortOrder, setSortOrder] = useState('asc')
|
|
28
|
+
const inputRef = useRef()
|
|
29
|
+
|
|
30
|
+
// Fetch todos when the component mounts
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
const loadTodos = async () => {
|
|
33
|
+
const fetchedTodos = await fetchTodos()
|
|
34
|
+
|
|
35
|
+
setTodos(fetchedTodos)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
loadTodos()
|
|
39
|
+
}, [todos])
|
|
40
|
+
|
|
41
|
+
// Handle adding a new todo
|
|
42
|
+
const addTodo = useCallback(() => {
|
|
43
|
+
const text = inputRef.current.value.trim()
|
|
44
|
+
|
|
45
|
+
if (text) {
|
|
46
|
+
setTodos(prevTodos => [
|
|
47
|
+
...prevTodos,
|
|
48
|
+
{ id: Date.now(), text, completed: false }
|
|
49
|
+
])
|
|
50
|
+
|
|
51
|
+
inputRef.current.value = ''
|
|
52
|
+
}
|
|
53
|
+
}, [])
|
|
54
|
+
|
|
55
|
+
// Handle toggling the completion state of a todo
|
|
56
|
+
const toggleTodo = useCallback(id => {
|
|
57
|
+
setTodos(prevTodos => prevTodos.map(todo => todo.id === id ? { ...todo, completed: !todo.completed } : todo))
|
|
58
|
+
}, [])
|
|
59
|
+
|
|
60
|
+
// Handle changing the filter state
|
|
61
|
+
const handleFilterChange = useCallback(event => {
|
|
62
|
+
setFilter(event.target.value)
|
|
63
|
+
}, [])
|
|
64
|
+
|
|
65
|
+
// Handle changing the sort order
|
|
66
|
+
const handleSortChange = useCallback(event => {
|
|
67
|
+
setSortOrder(event.target.value)
|
|
68
|
+
}, [])
|
|
69
|
+
|
|
70
|
+
// Filter and sort todos based on current state
|
|
71
|
+
const filteredAndSortedTodos = useMemo(() => {
|
|
72
|
+
const filteredTodos = todos.filter(todo => {
|
|
73
|
+
if (filter === 'completed') return todo.completed
|
|
74
|
+
|
|
75
|
+
if (filter === 'incomplete') return !todo.completed
|
|
76
|
+
|
|
77
|
+
return true
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
return filteredTodos.sort((a, b) => {
|
|
81
|
+
if (sortOrder === 'asc') return a.text.localeCompare(b.text)
|
|
82
|
+
|
|
83
|
+
return b.text.localeCompare(a.text)
|
|
84
|
+
})
|
|
85
|
+
}, [todos, filter, sortOrder])
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<div>
|
|
89
|
+
<h1>Todo List</h1>
|
|
90
|
+
<div>
|
|
91
|
+
<input ref={inputRef} type="text" placeholder="New todo" />
|
|
92
|
+
<button type="button" onClick={addTodo}>
|
|
93
|
+
Add Todo
|
|
94
|
+
</button>
|
|
95
|
+
</div>
|
|
96
|
+
<div>
|
|
97
|
+
<label>
|
|
98
|
+
Filter:
|
|
99
|
+
<select value={filter} onChange={handleFilterChange}>
|
|
100
|
+
<option value="all">All</option>
|
|
101
|
+
<option value="completed">Completed</option>
|
|
102
|
+
<option value="incomplete">Incomplete</option>
|
|
103
|
+
</select>
|
|
104
|
+
</label>
|
|
105
|
+
<label>
|
|
106
|
+
Sort:
|
|
107
|
+
<select value={sortOrder} onChange={handleSortChange}>
|
|
108
|
+
<option value="asc">Ascending</option>
|
|
109
|
+
<option value="desc">Descending</option>
|
|
110
|
+
</select>
|
|
111
|
+
</label>
|
|
112
|
+
</div>
|
|
113
|
+
<ul>
|
|
114
|
+
{filteredAndSortedTodos.map(todo => (
|
|
115
|
+
<li
|
|
116
|
+
key={todo.id}
|
|
117
|
+
style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}
|
|
118
|
+
>
|
|
119
|
+
{todo.text}
|
|
120
|
+
<button type="button" onClick={() => toggleTodo(todo.id)}>
|
|
121
|
+
{todo.completed ? 'Undo' : 'Complete'}
|
|
122
|
+
</button>
|
|
123
|
+
</li>
|
|
124
|
+
))}
|
|
125
|
+
</ul>
|
|
126
|
+
</div>
|
|
127
|
+
)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export default TodoApp
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// Function definitions to test various stylistic rules
|
|
2
|
+
const myFunction1 = (): string => {
|
|
3
|
+
const value = 10
|
|
4
|
+
|
|
5
|
+
if (value > 5) {
|
|
6
|
+
console.log('Value is greater than 5')
|
|
7
|
+
} else {
|
|
8
|
+
console.log('Value is 5 or less')
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const result: string = value > 5 ? 'High' : 'Low'
|
|
12
|
+
const array: number[] = [1, 2, 3]
|
|
13
|
+
|
|
14
|
+
array.forEach(item => {
|
|
15
|
+
console.log(item)
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
return result
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Testing object and array formatting rules
|
|
22
|
+
const myObject: { a: number, b: number, c: number } = { a: 1, b: 2, c: 3 }
|
|
23
|
+
const myArray: number[] = [1, 2, 3, 4, 5]
|
|
24
|
+
|
|
25
|
+
// Testing padding and spacing rules
|
|
26
|
+
if (myArray.length > 0) {
|
|
27
|
+
console.log('Array is not empty')
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const myFunction2 = (param: boolean): boolean => !!param
|
|
31
|
+
// Testing invalid typeof comparison
|
|
32
|
+
const count = 0
|
|
33
|
+
|
|
34
|
+
if (typeof count === 'number') {
|
|
35
|
+
console.log('Count is a number')
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Testing unused variables
|
|
39
|
+
// eslint-disable-next-line unused-imports/no-unused-vars, @typescript-eslint/no-unused-vars
|
|
40
|
+
const unusedVar = 'This is unused'
|
|
41
|
+
|
|
42
|
+
// Function with multiple return statements
|
|
43
|
+
// eslint-disable-next-line unused-imports/no-unused-vars, @typescript-eslint/no-unused-vars
|
|
44
|
+
const complexFunction = (): string => {
|
|
45
|
+
if (count > 10) return 'High'
|
|
46
|
+
|
|
47
|
+
if (count < 0) return 'Low'
|
|
48
|
+
|
|
49
|
+
return 'Medium'
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Testing no-use-before-define
|
|
53
|
+
myDefinedFunction()
|
|
54
|
+
|
|
55
|
+
// eslint-disable-next-line func-style
|
|
56
|
+
function myDefinedFunction(): void {
|
|
57
|
+
console.log('Function called before definition')
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Export statement to test sorting
|
|
61
|
+
export { myFunction1, myFunction2, myObject, myArray }
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# @santi020k/eslint-config-react
|
|
2
|
+
|
|
3
|
+
React specific ESLint rules and configurations.
|
|
4
|
+
|
|
5
|
+
## Description
|
|
6
|
+
|
|
7
|
+
This package provides:
|
|
8
|
+
- `eslint-plugin-react` recommended rules.
|
|
9
|
+
- `eslint-plugin-react-hooks` recommended rules.
|
|
10
|
+
- JSX accessibility rules.
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
This package is used automatically when `ConfigOption.React` is selected in the main configuration.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import jsxA11y from 'eslint-plugin-jsx-a11y'
|
|
2
|
+
import react from 'eslint-plugin-react'
|
|
3
|
+
import reactHooks from 'eslint-plugin-react-hooks'
|
|
4
|
+
|
|
5
|
+
import core from '@santi020k/eslint-config-core'
|
|
6
|
+
|
|
7
|
+
export default [
|
|
8
|
+
...core,
|
|
9
|
+
{
|
|
10
|
+
plugins: {
|
|
11
|
+
react,
|
|
12
|
+
'react-hooks': reactHooks,
|
|
13
|
+
'jsx-a11y': jsxA11y
|
|
14
|
+
},
|
|
15
|
+
rules: {
|
|
16
|
+
...react.configs.recommended.rules,
|
|
17
|
+
...reactHooks.configs.recommended.rules,
|
|
18
|
+
...jsxA11y.configs.recommended.rules
|
|
19
|
+
},
|
|
20
|
+
settings: {
|
|
21
|
+
react: {
|
|
22
|
+
version: 'detect'
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
]
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@santi020k/eslint-config-react",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "React ESLint configuration with hooks and JSX rules",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsup",
|
|
20
|
+
"dev": "tsup --watch",
|
|
21
|
+
"clean": "rm -rf dist"
|
|
22
|
+
},
|
|
23
|
+
"peerDependencies": {
|
|
24
|
+
"eslint": "^9.0.0",
|
|
25
|
+
"react": ">=18.0.0"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@santi020k/eslint-config-core": "*",
|
|
29
|
+
"@eslint/compat": "^2.0.2",
|
|
30
|
+
"eslint-plugin-react": "^7.37.5",
|
|
31
|
+
"eslint-plugin-react-hooks": "^7.0.1",
|
|
32
|
+
"globals": "^17.3.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@typescript-eslint/utils": "^8.54.0",
|
|
36
|
+
"tsup": "^8.5.1",
|
|
37
|
+
"typescript": "^5.9.3"
|
|
38
|
+
},
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public"
|
|
41
|
+
},
|
|
42
|
+
"license": "MIT",
|
|
43
|
+
"author": "santi020k",
|
|
44
|
+
"repository": {
|
|
45
|
+
"type": "git",
|
|
46
|
+
"url": "git+https://github.com/santi020k/eslint-config.git",
|
|
47
|
+
"directory": "packages/react"
|
|
48
|
+
}
|
|
49
|
+
}
|