├── .commitlintrc ├── .cspell.json ├── .editorconfig ├── .github ├── actions │ ├── build-package │ │ └── action.yml │ ├── install-dependencies │ │ └── action.yml │ └── install-tools │ │ └── action.yml ├── code_of_conduct.md ├── security.md └── workflows │ ├── docs.yml │ ├── release.yml │ └── test.yml ├── .gitignore ├── .prettierrc ├── .simple-git-hooks.json ├── a11y └── index.ts ├── assets └── logo.png ├── astro └── index.ts ├── changelog.config.json ├── changelog.md ├── core └── index.ts ├── environment.d.ts ├── eslint.config.ts ├── index.ts ├── license.md ├── node └── index.ts ├── package-json └── index.ts ├── package.json ├── perfectionist └── index.ts ├── pnpm-lock.yaml ├── qwik └── index.ts ├── react └── index.ts ├── readme.md ├── svelte └── index.ts ├── tsconfig.json ├── typescript └── index.ts ├── utilities.ts ├── vite.config.ts ├── vitest └── index.ts └── vue └── index.ts /.commitlintrc: -------------------------------------------------------------------------------- 1 | { 2 | extends: ["@commitlint/config-conventional"] 3 | } -------------------------------------------------------------------------------- /.cspell.json: -------------------------------------------------------------------------------- 1 | { 2 | "dictionaries": ["css", "html", "node", "npm", "typescript"], 3 | "useGitignore": true, 4 | "language": "en", 5 | "ignorePaths": [ 6 | ".github", 7 | "changelog.md", 8 | "license", 9 | "pnpm-lock.yaml", 10 | "tsconfig.json" 11 | ], 12 | "words": [ 13 | "azat", 14 | "canonicalurl", 15 | "changelogithub", 16 | "curlies", 17 | "fetchcontent", 18 | "getentrybyslug", 19 | "lookarounds", 20 | "nanostores", 21 | "nonconstructor", 22 | "nonoctal", 23 | "nums", 24 | "proptypes", 25 | "scopedslots", 26 | "sonarjs", 27 | "subclassing", 28 | "namepaths", 29 | "nuxt", 30 | "qwik", 31 | "textnodes", 32 | "thenables" 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true -------------------------------------------------------------------------------- /.github/actions/build-package/action.yml: -------------------------------------------------------------------------------- 1 | name: Build Package 2 | 3 | runs: 4 | using: composite 5 | steps: 6 | - name: Build Package 7 | shell: bash 8 | run: pnpm run build 9 | -------------------------------------------------------------------------------- /.github/actions/install-dependencies/action.yml: -------------------------------------------------------------------------------- 1 | name: Install Dependencies 2 | 3 | runs: 4 | using: composite 5 | steps: 6 | - name: Get pnpm store directory 7 | shell: bash 8 | run: | 9 | echo "PNPM_STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV 10 | 11 | - name: Setup pnpm cache 12 | uses: actions/cache@v4 13 | with: 14 | path: ${{ env.PNPM_STORE_PATH }} 15 | key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} 16 | restore-keys: | 17 | ${{ runner.os }}-pnpm-store- 18 | 19 | - name: Install dependencies 20 | shell: bash 21 | run: pnpm install --frozen-lockfile --ignore-scripts 22 | -------------------------------------------------------------------------------- /.github/actions/install-tools/action.yml: -------------------------------------------------------------------------------- 1 | name: Install Tools 2 | 3 | runs: 4 | using: composite 5 | steps: 6 | - name: Install Node 7 | uses: actions/setup-node@v4 8 | with: 9 | node-version: 24 10 | 11 | - name: Install pnpm 12 | uses: pnpm/action-setup@v4 13 | with: 14 | version: 10 15 | run_install: false 16 | -------------------------------------------------------------------------------- /.github/code_of_conduct.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. 4 | 5 | We are committed to making participation in this project a harassment-free experience for everyone, regardless of the level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion. 6 | 7 | Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct. 8 | 9 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team. 10 | 11 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers. 12 | 13 | This Code of Conduct is adapted from the [Contributor Covenant](https://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/) 14 | -------------------------------------------------------------------------------- /.github/security.md: -------------------------------------------------------------------------------- 1 | # Security 2 | 3 | To report a vulnerability, please open a private vulnerability report at . 4 | 5 | While the discovery of new vulnerabilities is rare, we also recommend always using the latest version of Azat's ESLint Config extension to ensure your application remains as secure as possible. 6 | -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: Docs 2 | 3 | on: 4 | push: 5 | branches: 6 | - 'main' 7 | 8 | jobs: 9 | deploy: 10 | name: Deploy 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v4 16 | with: 17 | fetch-depth: 0 18 | 19 | - name: Install Tools 20 | uses: ./.github/actions/install-tools 21 | 22 | - name: Install Dependencies 23 | uses: ./.github/actions/install-dependencies 24 | 25 | - name: Build Package 26 | uses: ./.github/actions/build-package 27 | 28 | - name: Build Docs 29 | run: pnpm run docs:build 30 | 31 | - name: Change Folder 32 | run: mv .eslint-config-inspector docs 33 | 34 | - name: Deploy to Netlify 35 | uses: nwtgck/actions-netlify@v3 36 | with: 37 | publish-dir: './docs' 38 | production-branch: main 39 | deploy-message: 'deploy from github actions' 40 | enable-pull-request-comment: false 41 | enable-commit-comment: true 42 | overwrites-pull-request-comment: true 43 | env: 44 | NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} 45 | NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} 46 | timeout-minutes: 1 47 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*' 7 | workflow_dispatch: 8 | 9 | permissions: 10 | id-token: write 11 | contents: write 12 | packages: write 13 | 14 | jobs: 15 | release: 16 | name: Release 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | - name: Checkout 21 | uses: actions/checkout@v4 22 | with: 23 | fetch-depth: 0 24 | 25 | - name: Install Tools 26 | uses: ./.github/actions/install-tools 27 | 28 | - name: Install Dependencies 29 | uses: ./.github/actions/install-dependencies 30 | 31 | - name: Build Package 32 | uses: ./.github/actions/build-package 33 | 34 | - name: Create GitHub Release 35 | run: pnpm run ci:changelog 36 | env: 37 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 38 | 39 | - name: Configure NPM Auth 40 | run: echo "//registry.npmjs.org/:_authToken=${{ secrets.NODE_AUTH_TOKEN }}" > ~/.npmrc 41 | 42 | - name: Clear Package JSON 43 | run: pnpm run ci:clear 44 | 45 | - name: Publish Root Package to NPM 46 | run: npm publish --access public --no-git-checks --provenance 47 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | push: 5 | branches: 6 | - 'main' 7 | pull_request: 8 | 9 | jobs: 10 | format: 11 | name: Format 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v4 17 | 18 | - name: Install Tools 19 | uses: ./.github/actions/install-tools 20 | 21 | - name: Install Dependencies 22 | uses: ./.github/actions/install-dependencies 23 | 24 | - name: Test 25 | run: pnpm test:format 26 | 27 | js: 28 | name: JS 29 | runs-on: ubuntu-latest 30 | 31 | steps: 32 | - name: Checkout 33 | uses: actions/checkout@v4 34 | 35 | - name: Install Tools 36 | uses: ./.github/actions/install-tools 37 | 38 | - name: Install Dependencies 39 | uses: ./.github/actions/install-dependencies 40 | 41 | - name: Build Package 42 | uses: ./.github/actions/build-package 43 | 44 | - name: Test 45 | run: pnpm test:js 46 | 47 | packages: 48 | name: Packages 49 | runs-on: ubuntu-latest 50 | 51 | steps: 52 | - name: Checkout 53 | uses: actions/checkout@v4 54 | 55 | - name: Install Tools 56 | uses: ./.github/actions/install-tools 57 | 58 | - name: Install Dependencies 59 | uses: ./.github/actions/install-dependencies 60 | 61 | - name: Test 62 | run: pnpm test:packages 63 | 64 | spelling: 65 | name: Spelling 66 | runs-on: ubuntu-latest 67 | 68 | steps: 69 | - name: Checkout 70 | uses: actions/checkout@v4 71 | 72 | - name: Install Tools 73 | uses: ./.github/actions/install-tools 74 | 75 | - name: Install Dependencies 76 | uses: ./.github/actions/install-dependencies 77 | 78 | - name: Test 79 | run: pnpm test:spelling 80 | 81 | types: 82 | name: Types 83 | runs-on: ubuntu-latest 84 | 85 | steps: 86 | - name: Checkout 87 | uses: actions/checkout@v4 88 | 89 | - name: Install Tools 90 | uses: ./.github/actions/install-tools 91 | 92 | - name: Install Dependencies 93 | uses: ./.github/actions/install-dependencies 94 | 95 | - name: Test 96 | run: pnpm test:types 97 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Node.js 2 | node_modules/ 3 | .nvmrc 4 | 5 | # Build 6 | .eslint-config-inspector/ 7 | dist/ 8 | 9 | # Editor 10 | .vscode/ 11 | .vim/ 12 | .idea/ 13 | 14 | # Misc 15 | .DS_Store 16 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "avoid", 3 | "bracketSpacing": true, 4 | "endOfLine": "lf", 5 | "printWidth": 80, 6 | "quoteProps": "as-needed", 7 | "semi": false, 8 | "singleQuote": true, 9 | "tabWidth": 2, 10 | "trailingComma": "all", 11 | "useTabs": false 12 | } 13 | -------------------------------------------------------------------------------- /.simple-git-hooks.json: -------------------------------------------------------------------------------- 1 | { 2 | "commit-msg": "pnpm exec commitlint -e \"$@\"" 3 | } 4 | -------------------------------------------------------------------------------- /a11y/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | eslint perfectionist/sort-objects: [ 3 | 'error', 4 | { 5 | type: 'alphabetical', 6 | order: 'asc', 7 | partitionByNewLine: true 8 | } 9 | ] 10 | */ 11 | 12 | import type { Linter } from 'eslint' 13 | 14 | import jsxA11y from 'eslint-plugin-jsx-a11y' 15 | 16 | import type { ConfigOptions } from '..' 17 | 18 | export let a11y = (config: ConfigOptions): Linter.Config => { 19 | if (!config.react && !config.qwik) { 20 | return {} 21 | } 22 | 23 | let files = ['**/*.jsx'] 24 | 25 | if (config.typescript) { 26 | files.push('**/*.tsx') 27 | } 28 | 29 | return { 30 | name: 'azat-io/a11y/rules', 31 | 32 | files, 33 | 34 | plugins: { 35 | 'jsx-a11y': jsxA11y, 36 | }, 37 | 38 | rules: { 39 | /** 40 | * Check if ``, ``, ``, and `` has 41 | * alt attribute. 42 | */ 43 | 'jsx-a11y/alt-text': 'error', 44 | /** 45 | * Enforce that anchors have content. 46 | */ 47 | 'jsx-a11y/anchor-has-content': 'error', 48 | /** 49 | * Check if anchor has `href` attribute. 50 | */ 51 | 'jsx-a11y/anchor-is-valid': 'error', 52 | /** 53 | * Check if elements with `aria-activedescendant` are tabbable. 54 | */ 55 | 'jsx-a11y/aria-activedescendant-has-tabindex': 'error', 56 | /** 57 | * Validate that aria-* property is listed in WAI-ARIA States and 58 | * Properties spec. 59 | */ 60 | 'jsx-a11y/aria-props': 'error', 61 | /** 62 | * Validate aria state and property values. 63 | */ 64 | 'jsx-a11y/aria-proptypes': 'error', 65 | /** 66 | * Validate aria roles. 67 | */ 68 | 'jsx-a11y/aria-role': 'error', 69 | /** 70 | * Check if `meta`, `html`, `script`, `style`, etc. has no `aria-*` 71 | * attributes. 72 | */ 73 | 'jsx-a11y/aria-unsupported-elements': 'error', 74 | /** 75 | * Ensure the autocomplete attribute is correct and suitable for the form 76 | * field it is used with. 77 | */ 78 | 'jsx-a11y/autocomplete-valid': 'error', 79 | /** 80 | * Enforce that heading elements have content. 81 | */ 82 | 'jsx-a11y/heading-has-content': 'error', 83 | /** 84 | * Enforce that `` element has `lang` attribute. 85 | */ 86 | 'jsx-a11y/html-has-lang': 'error', 87 | /** 88 | * Enforce that `