diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b176d83..5ff50f3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,8 +15,11 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - - name: Lint JS - run: npx oxlint@latest -D perf + - uses: actions/setup-node@v5 + with: + node-version: 22 + - run: npm ci --ignore-scripts --no-audit --no-fund + - run: npm run lint test: name: Unit tests @@ -56,5 +59,4 @@ jobs: - run: npm run build env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - - name: Lint package - run: npx publint + - run: npm run lint-package diff --git a/.oxlintrc.json b/.oxlintrc.json new file mode 100644 index 0000000..22c91c1 --- /dev/null +++ b/.oxlintrc.json @@ -0,0 +1,59 @@ +{ + "$schema": "./node_modules/oxlint/configuration_schema.json", + "plugins": [ + "import", + "typescript", + "oxc", + "unicorn" + ], + "env": { + "node": true, + "browser": true, + "es2024": true + }, + "categories": { + "perf": "error", + "correctness": "error", + "pedantic": "error" + }, + "rules": { + "unicorn/no-null": "error", + "unicorn/prefer-set-has": "off", + "prefer-string-slice": "off", + "prefer-code-point": "off", + "no-lonely-if": "off", + "unicorn/no-lonely-if": "off", + "no-unused-vars": "off", + "no-await-in-loop": "off", + "prefer-query-selector": "off", + "max-dependencies": "off", + "ban-types": "off", + "no-undefined": "off", + "no-useless-undefined": "off", + "max-classes-per-file": "off", + "max-lines-per-function": "off", + "prefer-math-trunc": "off", + "max-lines": "off", + "max-depth": [ + "warn", + { + "max": 5 + } + ], + "explicit-function-return-type": "off", + "no-console": "off", + "no-optional-chaining": "off", + "no-commonjs": "off", + "unambiguous": "off", + "no-default-export": "off", + "no-async-await": "off", + "no-non-null-assertion": "off", + "no-plusplus": "off", + "no-bitwise": "off", + "default-case": "off", + "no-rest-spread-properties": "off", + "require-await": "warn", + "no-null": "off", + "no-warning-comments": "off" + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 6babfb8..7548631 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,9 @@ "@codecov/vite-plugin": "^1.9.1", "@types/css-tree": "^2.3.11", "c8": "^10.1.3", + "oxlint": "^1.26.0", "prettier": "^3.6.2", + "publint": "^0.3.15", "typescript": "^5.9.3", "vite": "^6.3.4", "vite-plugin-dts": "^4.5.4", @@ -1075,6 +1077,118 @@ "@octokit/openapi-types": "^24.2.0" } }, + "node_modules/@oxlint/darwin-arm64": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@oxlint/darwin-arm64/-/darwin-arm64-1.26.0.tgz", + "integrity": "sha512-kTmm1opqyn7iZopWHO3Ml4D/44pA5eknZBepgxCnTaPrW8XgCEUI85Q5AvOOvoNve8NziTYb8ax+CyuGJIgn/Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@oxlint/darwin-x64": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@oxlint/darwin-x64/-/darwin-x64-1.26.0.tgz", + "integrity": "sha512-/hMfZ9j7ZzVPRmMm02PHNc6MIMk0QYv5VowZJRIp40YLqLPvFfGNGZBj8e1fDVgZMFEGWDQK3yrt1uBKxXAK4Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@oxlint/linux-arm64-gnu": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@oxlint/linux-arm64-gnu/-/linux-arm64-gnu-1.26.0.tgz", + "integrity": "sha512-iv4wdrwdCa8bhJxOpKlvfxqTs0LgW5tKBUMvH9B13zREHm1xT9JRZ8cQbbKiyC6LNdggwu5S6TSvODgAu7/DlA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxlint/linux-arm64-musl": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@oxlint/linux-arm64-musl/-/linux-arm64-musl-1.26.0.tgz", + "integrity": "sha512-a3gTbnN1JzedxqYeGTkg38BAs/r3Krd2DPNs/MF7nnHthT3RzkPUk47isMePLuNc4e/Weljn7m2m/Onx22tiNg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxlint/linux-x64-gnu": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@oxlint/linux-x64-gnu/-/linux-x64-gnu-1.26.0.tgz", + "integrity": "sha512-cCAyqyuKpFImjlgiBuuwSF+aDBW2h19/aCmHMTMSp6KXwhoQK7/Xx7/EhZKP5wiQJzVUYq5fXr0D8WmpLGsjRg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxlint/linux-x64-musl": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@oxlint/linux-x64-musl/-/linux-x64-musl-1.26.0.tgz", + "integrity": "sha512-8VOJ4vQo0G1tNdaghxrWKjKZGg73tv+FoMDrtNYuUesqBHZN68FkYCsgPwEsacLhCmtoZrkF3ePDWDuWEpDyAg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxlint/win32-arm64": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@oxlint/win32-arm64/-/win32-arm64-1.26.0.tgz", + "integrity": "sha512-N8KUtzP6gfEHKvaIBZCS9g8wRfqV5v55a/B8iJjIEhtMehcEM+UX+aYRsQ4dy5oBCrK3FEp4Yy/jHgb0moLm3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@oxlint/win32-x64": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@oxlint/win32-x64/-/win32-x64-1.26.0.tgz", + "integrity": "sha512-7tCyG0laduNQ45vzB9blVEGq/6DOvh7AFmiUAana8mTp0zIKQQmwJ21RqhazH0Rk7O6lL7JYzKcu+zaJHGpRLA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -1086,6 +1200,19 @@ "node": ">=14" } }, + "node_modules/@publint/pack": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@publint/pack/-/pack-0.1.2.tgz", + "integrity": "sha512-S+9ANAvUmjutrshV4jZjaiG8XQyuJIZ8a4utWmN/vW1sgQ9IfBnPndwkmQYw53QmouOIytT874u65HEmu6H5jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://bjornlu.com/sponsor" + } + }, "node_modules/@rollup/pluginutils": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz", @@ -2710,6 +2837,16 @@ "pathe": "^2.0.1" } }, + "node_modules/mri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -2753,6 +2890,41 @@ "wrappy": "1" } }, + "node_modules/oxlint": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.26.0.tgz", + "integrity": "sha512-KRpL+SMi07JQyggv5ldIF+wt2pnrKm8NLW0B+8bK+0HZsLmH9/qGA+qMWie5Vf7lnlMBllJmsuzHaKFEGY3rIA==", + "dev": true, + "license": "MIT", + "bin": { + "oxc_language_server": "bin/oxc_language_server", + "oxlint": "bin/oxlint" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/sponsors/Boshen" + }, + "optionalDependencies": { + "@oxlint/darwin-arm64": "1.26.0", + "@oxlint/darwin-x64": "1.26.0", + "@oxlint/linux-arm64-gnu": "1.26.0", + "@oxlint/linux-arm64-musl": "1.26.0", + "@oxlint/linux-x64-gnu": "1.26.0", + "@oxlint/linux-x64-musl": "1.26.0", + "@oxlint/win32-arm64": "1.26.0", + "@oxlint/win32-x64": "1.26.0" + }, + "peerDependencies": { + "oxlint-tsgolint": ">=0.4.0" + }, + "peerDependenciesMeta": { + "oxlint-tsgolint": { + "optional": true + } + } + }, "node_modules/package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", @@ -2760,6 +2932,13 @@ "dev": true, "license": "BlueOak-1.0.0" }, + "node_modules/package-manager-detector": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.5.0.tgz", + "integrity": "sha512-uBj69dVlYe/+wxj8JOpr97XfsxH/eumMt6HqjNTmJDf/6NO9s+0uxeOneIz3AsPt2m6y9PqzDzd3ATcU17MNfw==", + "dev": true, + "license": "MIT" + }, "node_modules/path-browserify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", @@ -2894,6 +3073,28 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/publint": { + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/publint/-/publint-0.3.15.tgz", + "integrity": "sha512-xPbRAPW+vqdiaKy5sVVY0uFAu3LaviaPO3pZ9FaRx59l9+U/RKR1OEbLhkug87cwiVKxPXyB4txsv5cad67u+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@publint/pack": "^0.1.2", + "package-manager-detector": "^1.3.0", + "picocolors": "^1.1.1", + "sade": "^1.8.1" + }, + "bin": { + "publint": "src/cli.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://bjornlu.com/sponsor" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -3002,6 +3203,19 @@ "fsevents": "~2.3.2" } }, + "node_modules/sade": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", + "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "mri": "^1.1.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/semver": { "version": "7.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", @@ -4335,6 +4549,62 @@ "@octokit/openapi-types": "^24.2.0" } }, + "@oxlint/darwin-arm64": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@oxlint/darwin-arm64/-/darwin-arm64-1.26.0.tgz", + "integrity": "sha512-kTmm1opqyn7iZopWHO3Ml4D/44pA5eknZBepgxCnTaPrW8XgCEUI85Q5AvOOvoNve8NziTYb8ax+CyuGJIgn/Q==", + "dev": true, + "optional": true + }, + "@oxlint/darwin-x64": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@oxlint/darwin-x64/-/darwin-x64-1.26.0.tgz", + "integrity": "sha512-/hMfZ9j7ZzVPRmMm02PHNc6MIMk0QYv5VowZJRIp40YLqLPvFfGNGZBj8e1fDVgZMFEGWDQK3yrt1uBKxXAK4Q==", + "dev": true, + "optional": true + }, + "@oxlint/linux-arm64-gnu": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@oxlint/linux-arm64-gnu/-/linux-arm64-gnu-1.26.0.tgz", + "integrity": "sha512-iv4wdrwdCa8bhJxOpKlvfxqTs0LgW5tKBUMvH9B13zREHm1xT9JRZ8cQbbKiyC6LNdggwu5S6TSvODgAu7/DlA==", + "dev": true, + "optional": true + }, + "@oxlint/linux-arm64-musl": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@oxlint/linux-arm64-musl/-/linux-arm64-musl-1.26.0.tgz", + "integrity": "sha512-a3gTbnN1JzedxqYeGTkg38BAs/r3Krd2DPNs/MF7nnHthT3RzkPUk47isMePLuNc4e/Weljn7m2m/Onx22tiNg==", + "dev": true, + "optional": true + }, + "@oxlint/linux-x64-gnu": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@oxlint/linux-x64-gnu/-/linux-x64-gnu-1.26.0.tgz", + "integrity": "sha512-cCAyqyuKpFImjlgiBuuwSF+aDBW2h19/aCmHMTMSp6KXwhoQK7/Xx7/EhZKP5wiQJzVUYq5fXr0D8WmpLGsjRg==", + "dev": true, + "optional": true + }, + "@oxlint/linux-x64-musl": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@oxlint/linux-x64-musl/-/linux-x64-musl-1.26.0.tgz", + "integrity": "sha512-8VOJ4vQo0G1tNdaghxrWKjKZGg73tv+FoMDrtNYuUesqBHZN68FkYCsgPwEsacLhCmtoZrkF3ePDWDuWEpDyAg==", + "dev": true, + "optional": true + }, + "@oxlint/win32-arm64": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@oxlint/win32-arm64/-/win32-arm64-1.26.0.tgz", + "integrity": "sha512-N8KUtzP6gfEHKvaIBZCS9g8wRfqV5v55a/B8iJjIEhtMehcEM+UX+aYRsQ4dy5oBCrK3FEp4Yy/jHgb0moLm3Q==", + "dev": true, + "optional": true + }, + "@oxlint/win32-x64": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@oxlint/win32-x64/-/win32-x64-1.26.0.tgz", + "integrity": "sha512-7tCyG0laduNQ45vzB9blVEGq/6DOvh7AFmiUAana8mTp0zIKQQmwJ21RqhazH0Rk7O6lL7JYzKcu+zaJHGpRLA==", + "dev": true, + "optional": true + }, "@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -4342,6 +4612,12 @@ "dev": true, "optional": true }, + "@publint/pack": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@publint/pack/-/pack-0.1.2.tgz", + "integrity": "sha512-S+9ANAvUmjutrshV4jZjaiG8XQyuJIZ8a4utWmN/vW1sgQ9IfBnPndwkmQYw53QmouOIytT874u65HEmu6H5jw==", + "dev": true + }, "@rollup/pluginutils": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz", @@ -5416,6 +5692,12 @@ } } }, + "mri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "dev": true + }, "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -5443,12 +5725,34 @@ "wrappy": "1" } }, + "oxlint": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.26.0.tgz", + "integrity": "sha512-KRpL+SMi07JQyggv5ldIF+wt2pnrKm8NLW0B+8bK+0HZsLmH9/qGA+qMWie5Vf7lnlMBllJmsuzHaKFEGY3rIA==", + "dev": true, + "requires": { + "@oxlint/darwin-arm64": "1.26.0", + "@oxlint/darwin-x64": "1.26.0", + "@oxlint/linux-arm64-gnu": "1.26.0", + "@oxlint/linux-arm64-musl": "1.26.0", + "@oxlint/linux-x64-gnu": "1.26.0", + "@oxlint/linux-x64-musl": "1.26.0", + "@oxlint/win32-arm64": "1.26.0", + "@oxlint/win32-x64": "1.26.0" + } + }, "package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "dev": true }, + "package-manager-detector": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.5.0.tgz", + "integrity": "sha512-uBj69dVlYe/+wxj8JOpr97XfsxH/eumMt6HqjNTmJDf/6NO9s+0uxeOneIz3AsPt2m6y9PqzDzd3ATcU17MNfw==", + "dev": true + }, "path-browserify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", @@ -5529,6 +5833,18 @@ "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "dev": true }, + "publint": { + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/publint/-/publint-0.3.15.tgz", + "integrity": "sha512-xPbRAPW+vqdiaKy5sVVY0uFAu3LaviaPO3pZ9FaRx59l9+U/RKR1OEbLhkug87cwiVKxPXyB4txsv5cad67u+A==", + "dev": true, + "requires": { + "@publint/pack": "^0.1.2", + "package-manager-detector": "^1.3.0", + "picocolors": "^1.1.1", + "sade": "^1.8.1" + } + }, "punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -5595,6 +5911,15 @@ "fsevents": "~2.3.2" } }, + "sade": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", + "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", + "dev": true, + "requires": { + "mri": "^1.1.0" + } + }, "semver": { "version": "7.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", diff --git a/package.json b/package.json index 6f7ff86..3443eb3 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,8 @@ "node": ">=18.0.0" }, "scripts": { + "lint": "oxlint --config .oxlintrc.json", + "lint-package": "publint", "test": "vitest", "check": "tsc --noEmit", "build": "vite build" @@ -53,7 +55,9 @@ "@codecov/vite-plugin": "^1.9.1", "@types/css-tree": "^2.3.11", "c8": "^10.1.3", + "oxlint": "^1.26.0", "prettier": "^3.6.2", + "publint": "^0.3.15", "typescript": "^5.9.3", "vite": "^6.3.4", "vite-plugin-dts": "^4.5.4", diff --git a/src/index.ts b/src/index.ts index a6b6770..ca99699 100644 --- a/src/index.ts +++ b/src/index.ts @@ -230,6 +230,7 @@ function analyzeInternal(css: string, options: Options, useLo let complexity = 1 // All the AtRules in here MUST have a prelude, so we can count their names + // oxlint-disable-next-line no-negated-condition if (node.prelude !== null) { let prelude = node.prelude let preludeStr = prelude && stringifyNode(node.prelude)