diff --git a/.github/workflows/deploy-oxlint-java-script.yml b/.github/workflows/deploy-oxlint-java-script.yml new file mode 100644 index 00000000..eb96ba58 --- /dev/null +++ b/.github/workflows/deploy-oxlint-java-script.yml @@ -0,0 +1,14 @@ +name: Publish Oxlint JavaScript +on: + push: + branches: + - main + paths: + - libs/oxlint-java-script/package.json + +jobs: + deploy-java-script: + uses: ./.github/workflows/deploy.yml + with: + package: libs/oxlint-java-script + env: JS diff --git a/libs/oxlint-java-script/.oxlintrc.json b/libs/oxlint-java-script/.oxlintrc.json new file mode 100644 index 00000000..08af4f1b --- /dev/null +++ b/libs/oxlint-java-script/.oxlintrc.json @@ -0,0 +1,348 @@ +{ + "categories": { + "correctness": "error", + "suspicious": "warn" + }, + "ignorePatterns": [ + "dist/", + "node_modules/", + "*.min.js" + ], + "env": { + "browser": true, + "node": true, + "es2021": true + }, + "rules": { + "accessor-pairs": "error", + "arrow-body-style": "error", + "camelcase": "error", + "complexity": [ + "error", + 10 + ], + "curly": "error", + "default-case": "error", + "default-case-last": "error", + "default-param-last": "error", + "eqeqeq": [ + 2, + "allow-null" + ], + "guard-for-in": "error", + "max-classes-per-file": [ + "error", + { + "ignoreExpressions": true + } + ], + "max-lines": [ + "error", + { + "max": 400, + "skipComments": true, + "skipBlankLines": true + } + ], + "new-cap": "error", + "no-alert": "error", + "no-array-constructor": "error", + "no-await-in-loop": "error", + "no-bitwise": "error", + "no-caller": "error", + "no-console": [ + "error", + { + "allow": [ + "warn", + "dir", + "timeLog", + "assert", + "clear", + "count", + "countReset", + "group", + "groupEnd", + "table", + "dirxml", + "error", + "groupCollapsed", + "Console", + "profile", + "profileEnd", + "timeStamp" + ] + } + ], + "no-constructor-return": "error", + "no-duplicate-imports": "error", + "no-else-return": "error", + "no-empty-function": "error", + "no-empty-static-block": "error", + "no-eval": "error", + "no-extend-native": "error", + "no-extra-bind": "error", + "no-implicit-coercion": "error", + "no-implied-eval": "error", + "no-invalid-this": "off", + "no-iterator": "error", + "no-labels": "error", + "no-lonely-if": "error", + "no-loop-func": "error", + "no-magic-numbers": [ + "error", + { + "detectObjects": false, + "ignore": [ + -1, + 1, + 0 + ], + "ignoreArrayIndexes": false, + "ignoreDefaultValues": true + } + ], + "no-multi-assign": "error", + "no-multi-str": "error", + "no-nested-ternary": "error", + "no-new": "error", + "no-new-func": "error", + "no-new-wrappers": "error", + "no-object-constructor": "error", + "no-octal-escape": "error", + "no-param-reassign": "error", + "no-proto": "error", + "no-redeclare": "off", + "no-return-assign": "error", + "no-script-url": "error", + "no-self-compare": "error", + "no-sequences": "error", + "no-shadow": [ + "error", + { + "hoist": "all" + } + ], + "no-template-curly-in-string": "error", + "no-throw-literal": "error", + "no-undef-init": "error", + "no-underscore-dangle": "off", + "no-unneeded-ternary": "error", + "no-use-before-define": "off", + "no-useless-computed-key": "error", + "no-useless-concat": "error", + "no-useless-constructor": "error", + "no-useless-rename": "error", + "no-useless-return": "error", + "no-var": "error", + "no-void": "error", + "object-shorthand": [ + "error", + "properties" + ], + "one-var": [ + "error", + "never" + ], + "prefer-arrow-callback": [ + "error", + { + "allowNamedFunctions": true + } + ], + "prefer-const": "error", + "prefer-object-spread": "error", + "prefer-spread": "error", + "prefer-template": "error", + "radix": "error", + "sort-keys": "error", + "sort-vars": "error", + "symbol-description": "error", + "yoda": "error", + "jsdoc/check-alignment": "error", + "jsdoc/check-indentation": "error", + "jsdoc/tag-lines": [ + "error", + "any", + { + "startLines": 1 + } + ], + "jsdoc/require-returns-type": "off", + "jsdoc/require-param-type": "off", + "jsdoc/require-param": "off", + "jsdoc/require-returns": "off", + "jsdoc/require-property-type": "off", + "jsdoc/require-jsdoc": "off" + }, + "overrides": [ + { + "files": [ + "**/*.js", + "**/*.mjs" + ], + "rules": { + "accessor-pairs": "error", + "arrow-body-style": "error", + "camelcase": "error", + "complexity": [ + "error", + 10 + ], + "curly": "error", + "default-case": "error", + "default-case-last": "error", + "default-param-last": "error", + "eqeqeq": [ + 2, + "allow-null" + ], + "guard-for-in": "error", + "max-classes-per-file": [ + "error", + { + "ignoreExpressions": true + } + ], + "max-lines": [ + "error", + { + "max": 400, + "skipComments": true, + "skipBlankLines": true + } + ], + "new-cap": "error", + "no-alert": "error", + "no-array-constructor": "error", + "no-await-in-loop": "error", + "no-bitwise": "error", + "no-caller": "error", + "no-console": [ + "error", + { + "allow": [ + "warn", + "dir", + "timeLog", + "assert", + "clear", + "count", + "countReset", + "group", + "groupEnd", + "table", + "dirxml", + "error", + "groupCollapsed", + "Console", + "profile", + "profileEnd", + "timeStamp" + ] + } + ], + "no-constructor-return": "error", + "no-duplicate-imports": "error", + "no-else-return": "error", + "no-empty-function": "error", + "no-empty-static-block": "error", + "no-eval": "error", + "no-extend-native": "error", + "no-extra-bind": "error", + "no-implicit-coercion": "error", + "no-implied-eval": "error", + "no-invalid-this": "off", + "no-iterator": "error", + "no-labels": "error", + "no-lonely-if": "error", + "no-loop-func": "error", + "no-magic-numbers": [ + "error", + { + "detectObjects": false, + "ignore": [ + -1, + 1, + 0 + ], + "ignoreArrayIndexes": false, + "ignoreDefaultValues": true + } + ], + "no-multi-assign": "error", + "no-multi-str": "error", + "no-nested-ternary": "error", + "no-new": "error", + "no-new-func": "error", + "no-new-wrappers": "error", + "no-object-constructor": "error", + "no-octal-escape": "error", + "no-param-reassign": "error", + "no-proto": "error", + "no-redeclare": "off", + "no-return-assign": "error", + "no-script-url": "error", + "no-self-compare": "error", + "no-sequences": "error", + "no-shadow": [ + "error", + { + "hoist": "all" + } + ], + "no-template-curly-in-string": "error", + "no-throw-literal": "error", + "no-undef-init": "error", + "no-underscore-dangle": "off", + "no-unneeded-ternary": "error", + "no-use-before-define": "off", + "no-useless-computed-key": "error", + "no-useless-concat": "error", + "no-useless-constructor": "error", + "no-useless-rename": "error", + "no-useless-return": "error", + "no-var": "error", + "no-void": "error", + "object-shorthand": [ + "error", + "properties" + ], + "one-var": [ + "error", + "never" + ], + "prefer-arrow-callback": [ + "error", + { + "allowNamedFunctions": true + } + ], + "prefer-const": "error", + "prefer-object-spread": "error", + "prefer-spread": "error", + "prefer-template": "error", + "radix": "error", + "sort-keys": "error", + "sort-vars": "error", + "symbol-description": "error", + "yoda": "error", + "jsdoc/check-alignment": "error", + "jsdoc/check-indentation": "error", + "jsdoc/tag-lines": [ + "error", + "any", + { + "startLines": 1 + } + ], + "jsdoc/require-returns-type": "off", + "jsdoc/require-param-type": "off", + "jsdoc/require-param": "off", + "jsdoc/require-returns": "off", + "jsdoc/require-property-type": "off", + "jsdoc/require-jsdoc": "off" + } + } + ] +} \ No newline at end of file diff --git a/libs/oxlint-java-script/CHANGELOG.md b/libs/oxlint-java-script/CHANGELOG.md new file mode 100644 index 00000000..cab9254b --- /dev/null +++ b/libs/oxlint-java-script/CHANGELOG.md @@ -0,0 +1,27 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [1.0.0] - 2025-10-27 + +### Added + +- Initial release of oxlint configuration for JavaScript projects +- Migrated ESLint rules from @team23/eslint-config-team23-standard to oxlint format +- Core JavaScript rules for code quality and correctness +- Stylistic rules for code formatting (optional) +- JSDoc validation rules (optional) +- TypeScript-based configuration generation +- Programmatic API for creating oxlint configurations +- Comprehensive documentation and usage examples + +### Features + +- `createJSOxlintConfig()` - Generate oxlint configuration object +- `createJSOxlintConfigFile()` - Generate .oxlintrc.json file content +- Support for custom file patterns +- Optional stylistic and JSDoc rule sets +- Environment configuration for browser, Node.js, and ES2021 diff --git a/libs/oxlint-java-script/LICENSE b/libs/oxlint-java-script/LICENSE new file mode 100644 index 00000000..6435389e --- /dev/null +++ b/libs/oxlint-java-script/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2024 TEAM23 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/libs/oxlint-java-script/README.md b/libs/oxlint-java-script/README.md new file mode 100644 index 00000000..c6436eb3 --- /dev/null +++ b/libs/oxlint-java-script/README.md @@ -0,0 +1,182 @@ +# @team23/oxlint-config-team23-standard + +A set of oxlint rules used by TEAM23 for standard JavaScript projects. + +## About + +This package provides an oxlint configuration that mirrors the ESLint rules from `@team23/eslint-config-team23-standard`. Oxlint is a high-performance JavaScript linter built with Rust that offers significantly faster linting compared to ESLint. + +## Installation + +```bash +npm install --save-dev @team23/oxlint-config-team23-standard oxlint +``` + +### Quick Start + +Generate your `.oxlintrc.json` configuration file: + +```bash +# After installing the package +npx jiti node_modules/@team23/oxlint-config-team23-standard/examples/generate-config.ts +``` + +Then run oxlint: + +```bash +npx oxlint +``` + +### Programmatic Configuration + +You can generate an oxlint configuration programmatically. There are several ways to run the script: + +#### Using npx with jiti (recommended for development) + +```bash +npx --yes nx build --excludeTaskDependencies +npx jiti generate-config.ts +``` + +#### Using tsx (TypeScript runner) + +```bash +npx --yes nx build --excludeTaskDependencies +npx tsx generate-config.ts +``` + +#### Example Script (generate-config.mjs) + +```javascript +import { writeFileSync } from 'fs'; +import { createJSOxlintConfigFile } from '@team23/oxlint-config-team23-standard'; + +// Generate configuration file content +const configFileContent = createJSOxlintConfigFile({ + files: ['**/*.js', '**/*.mjs'], + includeStylistic: true, + includeJsdoc: true, +}); + +// Write to .oxlintrc.json +writeFileSync('.oxlintrc.json', configFileContent); +console.log('✓ Configuration written to .oxlintrc.json'); +``` + +#### Example Scripts Included + +This package includes example scripts in the `examples/` directory: + +- `examples/generate-config.ts` - TypeScript version (use with tsx or jiti) + +Run them with: + +```bash +# After installing the package +npx jiti node_modules/@team23/oxlint-config-team23-standard/examples/generate-config.ts + +# Or from the package directory during development +npx jiti examples/generate-config.ts +``` + +### Manual Configuration + +Create an `.oxlintrc.json` file in your project root: + +```json +{ + "categories": { + "correctness": "error", + "suspicious": "warn" + }, + "ignorePatterns": [ + "dist/", + "node_modules/", + "*.min.js" + ], + "env": { + "browser": true, + "node": true, + "es2021": true + }, + "rules": { + "no-console": ["error", { + "allow": ["warn", "error", "dir", "timeLog", "assert", "clear", "count", "countReset", "group", "groupEnd", "table", "dirxml", "groupCollapsed", "Console", "profile", "profileEnd", "timeStamp"] + }], + "no-var": "error", + "prefer-const": "error", + "eqeqeq": [2, "allow-null"] + } +} +``` + +### Run Oxlint + +```bash +# Lint all JavaScript files +npx oxlint + +# Lint specific files +npx oxlint src/**/*.js + +# Lint with auto-fix +npx oxlint --fix +``` + +## Configuration Options + +The `createJSOxlintConfig` function accepts the following options: + +- `files` (Array): File glob patterns to lint. Default: `['**/*.js', '**/*.mjs']` +- `includeStylistic` (boolean): Include stylistic rules. Default: `true`. Note: Consider disabling if using a formatter like Prettier or Biome. +- `includeJsdoc` (boolean): Include JSDoc validation rules. Default: `true` + +## Features + +### Core JavaScript Rules + +All core JavaScript quality rules from the ESLint configuration are included: +- No magic numbers +- Prefer const over let +- No var declarations +- Proper equality checks +- And many more... + +### Stylistic Rules (Optional) + +Stylistic rules for code formatting are included but can be disabled if you're using a dedicated formatter like Prettier or Biome. + +### JSDoc Rules (Optional) + +JSDoc validation rules ensure your documentation comments are properly formatted. + +## Migration from ESLint + +This package is designed to be a drop-in replacement for `@team23/eslint-config-team23-standard`. The rules have been carefully mapped from ESLint to oxlint format. + +### Key Differences + +1. **Performance**: Oxlint is 50-100x faster than ESLint +2. **Configuration Format**: Uses `.oxlintrc.json` instead of `eslint.config.js` +3. **Stylistic Rules**: Consider using a formatter (Prettier/Biome) instead of linter rules for styling +4. **Plugin Support**: Oxlint has different plugin ecosystem; some ESLint plugins may not be available + +## Notes + +- **Stylistic Rules**: Oxlint focuses on correctness and performance. For styling, consider using Prettier or Biome formatter instead of relying on linter rules. +- **JSDoc Plugin**: Native JSDoc support in oxlint may differ from eslint-plugin-jsdoc. Some rules may need adjustment. +- **Rule Compatibility**: Not all ESLint rules have direct oxlint equivalents. This configuration includes the closest matches. + +## License + +MIT + +## Contributing + +See [CONTRIBUTING.md](../../CONTRIBUTING.md) for contribution guidelines. + +## Links + +- [GitHub Repository](https://github.com/team23/style-guide) +- [Oxlint Documentation](https://oxc.rs/docs/guide/usage/linter) +- [ESLint Config (Original)](https://github.com/team23/style-guide/tree/main/libs/java-script) diff --git a/libs/oxlint-java-script/examples/generate-config.ts b/libs/oxlint-java-script/examples/generate-config.ts new file mode 100644 index 00000000..52403493 --- /dev/null +++ b/libs/oxlint-java-script/examples/generate-config.ts @@ -0,0 +1,25 @@ +#!/usr/bin/env node +/** + * Example script demonstrating how to generate oxlint configuration + * + * Usage: + * npx tsx examples/generate-config.ts + * node --loader tsx examples/generate-config.ts + * npx jiti examples/generate-config.ts + */ + +import { writeFileSync } from 'fs'; +import { createJSOxlintConfigFile } from '../dist/index'; + +// Example: Generate configuration object +console.log('Generating oxlint configuration object...'); +const config = createJSOxlintConfigFile({ + files: ['**/*.js', '**/*.mjs'], + includeStylistic: true, + includeJsdoc: true, +}); + +// Write to .oxlintrc.json +const outputPath = '.oxlintrc.json'; +writeFileSync(outputPath, config); +console.log(`Configuration written to ${outputPath}`); diff --git a/libs/oxlint-java-script/package.json b/libs/oxlint-java-script/package.json new file mode 100644 index 00000000..226a9463 --- /dev/null +++ b/libs/oxlint-java-script/package.json @@ -0,0 +1,44 @@ +{ + "name": "@team23/oxlint-config-team23-standard", + "version": "0.0.2", + "description": "A set of oxlint rules used by TEAM23 for standard JavaScript projects", + "keywords": [ + "oxlint", + "oxlintconfig", + "TEAM23", + "js", + "javascript", + "linter" + ], + "author": "TEAM23 GmbH", + "license": "MIT", + "homepage": "https://github.com/team23/style-guide/tree/main/libs/oxlint-java-script", + "repository": { + "type": "git", + "url": "git+https://github.com/team23/style-guide.git", + "directory": "libs/oxlint-java-script" + }, + "files": [ + "./dist/**/*", + "./examples/**/*", + "./*.md", + "./package.json", + "./LICENSE" + ], + "type": "module", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "exports": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "default": "./dist/index.js" + }, + "dependencies": {}, + "devDependencies": { + "jiti": "^2.5.1", + "oxlint": "^0.20.0" + }, + "peerDependencies": { + "oxlint": "^0.20.0" + } +} diff --git a/libs/oxlint-java-script/project.json b/libs/oxlint-java-script/project.json new file mode 100644 index 00000000..2ccd234d --- /dev/null +++ b/libs/oxlint-java-script/project.json @@ -0,0 +1,34 @@ +{ + "name": "oxlint-java-script", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/oxlint-java-script/src", + "projectType": "library", + "release": { + "version": { + "generatorOptions": { + "packageRoot": "dist/{projectRoot}", + "currentVersionResolver": "git-tag" + } + } + }, + "tags": [], + "targets": { + "build": { + "executor": "@nx/js:tsc", + "outputs": [ + "{options.outputPath}" + ], + "options": { + "rootDir": "{projectRoot}/src", + "outputPath": "{projectRoot}/dist", + "main": "{projectRoot}/src/index.ts", + "tsConfig": "{projectRoot}/tsconfig.lib.json" + } + }, + "nx-release-publish": { + "options": { + "packageRoot": "{projectRoot}/dist" + } + } + } +} diff --git a/libs/oxlint-java-script/src/config/js-rules.ts b/libs/oxlint-java-script/src/config/js-rules.ts new file mode 100644 index 00000000..4b787364 --- /dev/null +++ b/libs/oxlint-java-script/src/config/js-rules.ts @@ -0,0 +1,135 @@ +import type { OxlintRules } from '../types'; + +/** + * JavaScript core rules configuration for oxlint + * Migrated from ESLint configuration + */ +const complexity = 10; +const eqeqeq = 2; + +export const jsRulesConfig: OxlintRules = { + 'accessor-pairs': 'error', + 'arrow-body-style': 'error', + 'camelcase': 'error', + 'complexity': ['error', complexity], + 'curly': 'error', + 'default-case': 'error', + 'default-case-last': 'error', + 'default-param-last': 'error', + 'eqeqeq': [eqeqeq, 'allow-null'], + 'guard-for-in': 'error', + 'max-classes-per-file': ['error', { ignoreExpressions: true }], + 'max-lines': [ + 'error', + { + max: 400, + skipComments: true, + skipBlankLines: true, + }, + ], + 'new-cap': 'error', + 'no-alert': 'error', + 'no-array-constructor': 'error', + 'no-await-in-loop': 'error', + 'no-bitwise': 'error', + 'no-caller': 'error', + 'no-console': [ + 'error', + { + allow: [ + 'warn', + 'dir', + 'timeLog', + 'assert', + 'clear', + 'count', + 'countReset', + 'group', + 'groupEnd', + 'table', + 'dirxml', + 'error', + 'groupCollapsed', + 'Console', + 'profile', + 'profileEnd', + 'timeStamp', + ], + }, + ], + 'no-constructor-return': 'error', + 'no-duplicate-imports': 'error', + 'no-else-return': 'error', + 'no-empty-function': 'error', + 'no-empty-static-block': 'error', + 'no-eval': 'error', + 'no-extend-native': 'error', + 'no-extra-bind': 'error', + 'no-implicit-coercion': 'error', + 'no-implied-eval': 'error', + 'no-invalid-this': 'off', + 'no-iterator': 'error', + 'no-labels': 'error', + 'no-lonely-if': 'error', + 'no-loop-func': 'error', + 'no-magic-numbers': [ + 'error', + { + detectObjects: false, + ignore: [-1, 1, 0], + ignoreArrayIndexes: false, + ignoreDefaultValues: true, + }, + ], + 'no-multi-assign': 'error', + 'no-multi-str': 'error', + 'no-nested-ternary': 'error', + 'no-new': 'error', + 'no-new-func': 'error', + 'no-new-wrappers': 'error', + 'no-object-constructor': 'error', + 'no-octal-escape': 'error', + 'no-param-reassign': 'error', + 'no-proto': 'error', + 'no-redeclare': 'off', + 'no-return-assign': 'error', + 'no-script-url': 'error', + 'no-self-compare': 'error', + 'no-sequences': 'error', + 'no-shadow': [ + 'error', + { + hoist: 'all', + }, + ], + 'no-template-curly-in-string': 'error', + 'no-throw-literal': 'error', + 'no-undef-init': 'error', + 'no-underscore-dangle': 'off', + 'no-unneeded-ternary': 'error', + 'no-use-before-define': 'off', + 'no-useless-computed-key': 'error', + 'no-useless-concat': 'error', + 'no-useless-constructor': 'error', + 'no-useless-rename': 'error', + 'no-useless-return': 'error', + 'no-var': 'error', + 'no-void': 'error', + 'object-shorthand': ['error', 'properties'], + 'one-var': ['error', 'never'], + 'prefer-arrow-callback': [ + 'error', + { + allowNamedFunctions: true, + }, + ], + 'prefer-const': 'error', + 'prefer-object-spread': 'error', + 'prefer-spread': 'error', + 'prefer-template': 'error', + 'radix': 'error', + 'sort-keys': 'error', + 'sort-vars': 'error', + 'symbol-description': 'error', + 'yoda': 'error', +}; diff --git a/libs/oxlint-java-script/src/config/jsdoc-rules.ts b/libs/oxlint-java-script/src/config/jsdoc-rules.ts new file mode 100644 index 00000000..bc1848ee --- /dev/null +++ b/libs/oxlint-java-script/src/config/jsdoc-rules.ts @@ -0,0 +1,26 @@ +/** + * JSDoc rules configuration for oxlint + * Migrated from eslint-plugin-jsdoc + */ +import type { OxlintRules } from '../types'; + +export const jsdocRulesConfig: OxlintRules = { + // JSDoc validation rules + 'jsdoc/check-alignment': 'error', + 'jsdoc/check-indentation': 'error', + 'jsdoc/tag-lines': [ + 'error', + 'any', + { + startLines: 1, + }, + ], + + // Type requirements - turned off for JavaScript + 'jsdoc/require-returns-type': 'off', + 'jsdoc/require-param-type': 'off', + 'jsdoc/require-param': 'off', + 'jsdoc/require-returns': 'off', + 'jsdoc/require-property-type': 'off', + 'jsdoc/require-jsdoc': 'off', +}; diff --git a/libs/oxlint-java-script/src/config/stylistic-rules.ts b/libs/oxlint-java-script/src/config/stylistic-rules.ts new file mode 100644 index 00000000..d31e39f6 --- /dev/null +++ b/libs/oxlint-java-script/src/config/stylistic-rules.ts @@ -0,0 +1,125 @@ +/** + * Stylistic rules configuration for oxlint + * Note: Oxlint focuses on correctness and performance issues. + * Many stylistic rules are handled by formatters like Prettier or Biome. + * This file maintains the stylistic preferences from the original ESLint config. + */ +import type { OxlintRules } from '../types'; + +const maxLength = 140; + +export const stylisticRulesConfig: OxlintRules = { + // Note: Oxlint may not support all stylistic rules as it focuses on correctness. + // Consider using a formatter like Prettier or Biome for stylistic consistency. + // The following rules are included for reference and compatibility where supported. + + // Array formatting + 'array-bracket-newline': ['error', 'consistent'], + 'array-bracket-spacing': 'error', + 'array-element-newline': ['error', 'consistent'], + + // Arrow function formatting + 'arrow-parens': ['error', 'as-needed'], + 'arrow-spacing': 'error', + + // Block formatting + 'block-spacing': 'error', + 'brace-style': ['error', '1tbs', { allowSingleLine: true }], + + // Comma formatting + 'comma-dangle': ['error', 'always-multiline'], + 'comma-spacing': 'error', + 'comma-style': 'error', + + // Property and spacing + 'computed-property-spacing': ['error', 'never'], + 'eol-last': 'error', + + // Function formatting + 'function-call-argument-newline': ['error', 'consistent'], + 'function-call-spacing': 'error', + 'generator-star-spacing': 'error', + + // Arrow linebreak + 'implicit-arrow-linebreak': 'error', + + // JSX + 'jsx-quotes': 'error', + + // Spacing + 'key-spacing': 'error', + 'keyword-spacing': 'error', + + // Comments + 'line-comment-position': 'error', + 'linebreak-style': 'error', + 'lines-around-comment': 'error', + + // Line length + 'max-len': ['error', maxLength], + 'max-statements-per-line': 'error', + + // Ternary + 'multiline-ternary': ['error', 'always-multiline'], + + // Parens and chaining + 'new-parens': 'error', + 'newline-per-chained-call': 'error', + + // Arrow confusion + 'no-confusing-arrow': 'error', + + // Extra syntax + 'no-extra-parens': 'error', + 'no-extra-semi': 'error', + 'no-floating-decimal': 'error', + + // Spacing + 'no-multi-spaces': 'error', + 'no-multiple-empty-lines': 'error', + 'no-tabs': 'error', + 'no-trailing-spaces': 'error', + 'no-whitespace-before-property': 'error', + + // Object formatting + 'object-curly-newline': 'error', + 'object-curly-spacing': ['error', 'always'], + 'object-property-newline': ['error', { allowAllPropertiesOnSameLine: true }], + + // Operators + 'operator-linebreak': 'error', + 'padding-line-between-statements': 'error', + + // Quotes + 'quote-props': ['error', 'as-needed'], + 'quotes': ['error', 'single'], + + // Semicolons + 'rest-spread-spacing': 'error', + 'semi': ['error', 'always'], + 'semi-spacing': 'error', + 'semi-style': 'error', + + // Blocks and functions + 'space-before-blocks': 'error', + 'space-before-function-paren': [ + 'error', + { + anonymous: 'never', + named: 'never', + asyncArrow: 'always', + }, + ], + 'space-in-parens': 'error', + 'space-infix-ops': ['error', { int32Hint: true }], + 'space-unary-ops': 'error', + + // Comments and templates + 'spaced-comment': 'error', + 'switch-colon-spacing': 'error', + 'template-curly-spacing': ['error', 'always'], + + // Regex + 'wrap-regex': 'error', + 'yield-star-spacing': 'error', +}; diff --git a/libs/oxlint-java-script/src/index.ts b/libs/oxlint-java-script/src/index.ts new file mode 100644 index 00000000..09d0212c --- /dev/null +++ b/libs/oxlint-java-script/src/index.ts @@ -0,0 +1,103 @@ +import { jsRulesConfig } from './config/js-rules.js'; +import { stylisticRulesConfig } from './config/stylistic-rules.js'; +import { jsdocRulesConfig } from './config/jsdoc-rules.js'; +import type { OxlintConfig } from './types.js'; + +export interface ConfigOptions { + /** + * File glob patterns indicating the files that the configuration should be applied to. + * + * @default ['**\/*.js', '**\/*.mjs'] + */ + files?: Array; + + /** + * Include stylistic rules (not recommended with formatters like Prettier) + * + * @default true + */ + includeStylistic?: boolean; + + /** + * Include JSDoc rules + * + * @default true + */ + includeJsdoc?: boolean; +} + +/** + * Creates an oxlint configuration tailored for JavaScript projects with optional settings. + * + * @param [options] - Optional configuration settings. + * + * @returns Oxlint configuration object for JavaScript. + */ +function createJSOxlintConfig(options?: ConfigOptions): OxlintConfig { + const { + files = ['**/*.js', '**/*.mjs'], + includeStylistic = true, + includeJsdoc = true, + } = options ?? {}; + + const rules = { + ...jsRulesConfig, + ...(includeStylistic ? stylisticRulesConfig : {}), + ...(includeJsdoc ? jsdocRulesConfig : {}), + }; + + const config: OxlintConfig = { + // Enable recommended categories + categories: { + correctness: 'error', + suspicious: 'warn', + }, + + // Ignore common directories + ignorePatterns: [ + 'dist/', + 'node_modules/', + '*.min.js', + ], + + // Environment configuration + env: { + browser: true, + node: true, + es2021: true, + }, + + // Rule overrides + rules, + + // File-specific overrides + overrides: [ + { + files, + rules, + }, + ], + }; + + return config; +} + +/** + * Creates an oxlint configuration file content as JSON string + * + * @param [options] - Optional configuration settings. + * + * @returns JSON string of oxlint configuration + */ +function createJSOxlintConfigFile(options?: ConfigOptions): string { + const config = createJSOxlintConfig(options); + return JSON.stringify(config, null, 2); +} + +export { + type OxlintConfig, + createJSOxlintConfig, + createJSOxlintConfigFile, +}; + +export * from './types.js'; diff --git a/libs/oxlint-java-script/src/types.ts b/libs/oxlint-java-script/src/types.ts new file mode 100644 index 00000000..f03b8de0 --- /dev/null +++ b/libs/oxlint-java-script/src/types.ts @@ -0,0 +1,64 @@ +/** + * Type definitions for oxlint configuration + */ + +export type RuleSeverity = 'off' | 'warn' | 'error' | 0 | 1 | 2 | 'allow' | 'deny'; + +export type RuleConfig = RuleSeverity | [RuleSeverity, ...Array]; + +export interface OxlintRules { + [rule: string]: RuleConfig; +} + +export interface OxlintCategory { + correctness?: RuleSeverity; + suspicious?: RuleSeverity; + pedantic?: RuleSeverity; + perf?: RuleSeverity; + restriction?: RuleSeverity; + style?: RuleSeverity; + nursery?: RuleSeverity; +} + +export interface OxlintOverride { + files: Array; + rules?: OxlintRules; + plugins?: Array; +} + +export interface OxlintConfig { + /** + * Lint rule configurations + */ + rules?: OxlintRules; + + /** + * Plugins to extend available rules + */ + plugins?: Array; + + /** + * Rule categories with severity levels + */ + categories?: OxlintCategory; + + /** + * Patterns for files to ignore + */ + ignorePatterns?: Array; + + /** + * Override configurations for specific file patterns + */ + overrides?: Array; + + /** + * Environment globals + */ + env?: { + browser?: boolean; + node?: boolean; + es2021?: boolean; + [key: string]: boolean | undefined; + }; +} diff --git a/libs/oxlint-java-script/tsconfig.json b/libs/oxlint-java-script/tsconfig.json new file mode 100644 index 00000000..aff0b1fd --- /dev/null +++ b/libs/oxlint-java-script/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "allowSyntheticDefaultImports": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + } + ] +} diff --git a/libs/oxlint-java-script/tsconfig.lib.json b/libs/oxlint-java-script/tsconfig.lib.json new file mode 100644 index 00000000..d3aa5515 --- /dev/null +++ b/libs/oxlint-java-script/tsconfig.lib.json @@ -0,0 +1,12 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "rootDir": "./src", + "outDir": "./dist", + "declaration": true, + "declarationMap": true + }, + "include": [ + "src/**/*.ts" + ] +}