diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 10cda26..147ba91 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,6 +39,9 @@ jobs: - name: Check formatting run: pnpm run format --check + - name: Lint + run: pnpm run lint + - name: Build Prettier Plugin run: pnpm run build diff --git a/.oxlintrc.json b/.oxlintrc.json new file mode 100644 index 0000000..fe6e24f --- /dev/null +++ b/.oxlintrc.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://raw.githubusercontent.com/oxc-project/oxc/main/npm/oxlint/configuration_schema.json", + "rules": { + "typescript/unbound-method": "off" + } +} diff --git a/package.json b/package.json index 2fb62fd..c962dda 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "test": "vitest", "prepublishOnly": "npm run build && node scripts/copy-licenses.js", "format": "prettier \"src/**/*.ts\" \"scripts/**/*.js\" \"tests/*.ts\" --write --print-width 100 --single-quote --no-semi", - "lint": "knip", + "lint": "knip && oxlint --type-aware src tests/*.ts", "release-channel": "node ./scripts/release-channel.js", "release-notes": "node ./scripts/release-notes.js" }, @@ -62,6 +62,8 @@ "license-checker": "^25.0.1", "line-column": "^1.0.2", "marko": "^5.37.46", + "oxlint": "^1.43.0", + "oxlint-tsgolint": "^0.11.4", "postcss": "^8.5.6", "postcss-import": "^16.1.1", "prettier": "^3.7.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 351bd9c..1fb6a2d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -71,6 +71,12 @@ importers: marko: specifier: ^5.37.46 version: 5.38.18 + oxlint: + specifier: ^1.43.0 + version: 1.43.0(oxlint-tsgolint@0.11.4) + oxlint-tsgolint: + specifier: ^0.11.4 + version: 0.11.4 postcss: specifier: ^8.5.6 version: 8.5.6 @@ -728,6 +734,80 @@ packages: cpu: [x64] os: [win32] + '@oxlint-tsgolint/darwin-arm64@0.11.4': + resolution: {integrity: sha512-IhdhiC183s5wdFDZSQC8PaFFq1QROiVT5ahz7ysgEKVnkNDjy82ieM7ZKiUfm2ncXNX2RcFGSSZrQO6plR+VAQ==} + cpu: [arm64] + os: [darwin] + + '@oxlint-tsgolint/darwin-x64@0.11.4': + resolution: {integrity: sha512-KJmBg10Z1uGpJqxDzETXOytYyeVrKUepo8rCXeVkRlZ2QzZqMElgalFN4BI3ccgIPkQpzzu4SVzWNFz7yiKavQ==} + cpu: [x64] + os: [darwin] + + '@oxlint-tsgolint/linux-arm64@0.11.4': + resolution: {integrity: sha512-P6I3dSSpoEnjFzTMlrbcBHNbErSxceZmcVUslBxrrIUH1NSVS1XfSz6S75vT2Gay7Jv6LI7zTTVAk4cSqkfe+w==} + cpu: [arm64] + os: [linux] + + '@oxlint-tsgolint/linux-x64@0.11.4': + resolution: {integrity: sha512-G0eAW3S7cp/vP7Kx6e7+Ze7WfNgSt1tc/rOexfLKnnIi+9BelyOa2wF9bWFPpxk3n3AdkBwKttU1/adDZlD87Q==} + cpu: [x64] + os: [linux] + + '@oxlint-tsgolint/win32-arm64@0.11.4': + resolution: {integrity: sha512-prgQEBiwp4TAxarh6dYbVOKw6riRJ6hB49vDD6DxQlOZQky7xHQ9qTec5/rf0JTUZ16YaJ9YfHycbJS3QVpTYw==} + cpu: [arm64] + os: [win32] + + '@oxlint-tsgolint/win32-x64@0.11.4': + resolution: {integrity: sha512-5xXTzZIT/1meWMmS60Q+FYWvWncc6iTfC8tyQt7GDfPUoqQvE5WVgHm1QjDSJvxTD+6AHphpCqdhXq/KtxagRw==} + cpu: [x64] + os: [win32] + + '@oxlint/darwin-arm64@1.43.0': + resolution: {integrity: sha512-C/GhObv/pQZg34NOzB6Mk8x0wc9AKj8fXzJF8ZRKTsBPyHusC6AZ6bba0QG0TUufw1KWuD0j++oebQfWeiFXNw==} + cpu: [arm64] + os: [darwin] + + '@oxlint/darwin-x64@1.43.0': + resolution: {integrity: sha512-4NjfUtEEH8ewRQ2KlZGmm6DyrvypMdHwBnQT92vD0dLScNOQzr0V9O8Ua4IWXdeCNl/XMVhAV3h4/3YEYern5A==} + cpu: [x64] + os: [darwin] + + '@oxlint/linux-arm64-gnu@1.43.0': + resolution: {integrity: sha512-75tf1HvwdZ3ebk83yMbSB+moAEWK98mYqpXiaFAi6Zshie7r+Cx5PLXZFUEqkscenoZ+fcNXakHxfn94V6nf1g==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@oxlint/linux-arm64-musl@1.43.0': + resolution: {integrity: sha512-BHV4fb36T2p/7bpA9fiJ5ayt7oJbiYX10nklW5arYp4l9/9yG/FQC5J4G1evzbJ/YbipF9UH0vYBAm5xbqGrvw==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@oxlint/linux-x64-gnu@1.43.0': + resolution: {integrity: sha512-1l3nvnzWWse1YHibzZ4HQXdF/ibfbKZhp9IguElni3bBqEyPEyurzZ0ikWynDxKGXqZa+UNXTFuU1NRVX1RJ3g==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@oxlint/linux-x64-musl@1.43.0': + resolution: {integrity: sha512-+jNYgLGRFTJxJuaSOZJBwlYo5M0TWRw0+3y5MHOL4ArrIdHyCthg6r4RbVWrsR1qUfUE1VSSHQ2bfbC99RXqMg==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@oxlint/win32-arm64@1.43.0': + resolution: {integrity: sha512-dvs1C/HCjCyGTURMagiHprsOvVTT3omDiSzi5Qw0D4QFJ1pEaNlfBhVnOUYgUfS6O7Mcmj4+G+sidRsQcWQ/kA==} + cpu: [arm64] + os: [win32] + + '@oxlint/win32-x64@1.43.0': + resolution: {integrity: sha512-bSuItSU8mTSDsvmmLTepTdCL2FkJI6dwt9tot/k0EmiYF+ArRzmsl4lXVLssJNRV5lJEc5IViyTrh7oiwrjUqA==} + cpu: [x64] + os: [win32] + '@prettier/plugin-hermes@0.1.3': resolution: {integrity: sha512-ok9xBeAKSBo5r5+wRkn+IRG8eGX1EcjsTmTn0VfKdRiSLE1OhyUSXQdXOEUs8a/VdpctGJ9GHTHyLVFcIMkccQ==} engines: {node: '>=14'} @@ -1822,6 +1902,20 @@ packages: oxc-resolver@11.17.0: resolution: {integrity: sha512-R5P2Tw6th+nQJdNcZGfuppBS/sM0x1EukqYffmlfX2xXLgLGCCPwu4ruEr9Sx29mrpkHgITc130Qps2JR90NdQ==} + oxlint-tsgolint@0.11.4: + resolution: {integrity: sha512-VyQc+69TxQwUdsEPiVFN7vNZdDVO/FHaEcHltnWs3O6rvwxv67uADlknQQO714sbRdEahOjgO5dFf+K9ili0gg==} + hasBin: true + + oxlint@1.43.0: + resolution: {integrity: sha512-xiqTCsKZch+R61DPCjyqUVP2MhkQlRRYxLRBeBDi+dtQJ90MOgdcjIktvDCgXz0bgtx94EQzHEndsizZjMX2OA==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + oxlint-tsgolint: '>=0.11.2' + peerDependenciesMeta: + oxlint-tsgolint: + optional: true + parent-module@2.0.0: resolution: {integrity: sha512-uo0Z9JJeWzv8BG+tRcapBKNJ0dro9cLyczGzulS6EfeyAdeC9sbojtW6XwvYxJkEne9En+J2XEl4zyglVeIwFg==} engines: {node: '>=8'} @@ -2957,6 +3051,48 @@ snapshots: '@oxc-resolver/binding-win32-x64-msvc@11.17.0': optional: true + '@oxlint-tsgolint/darwin-arm64@0.11.4': + optional: true + + '@oxlint-tsgolint/darwin-x64@0.11.4': + optional: true + + '@oxlint-tsgolint/linux-arm64@0.11.4': + optional: true + + '@oxlint-tsgolint/linux-x64@0.11.4': + optional: true + + '@oxlint-tsgolint/win32-arm64@0.11.4': + optional: true + + '@oxlint-tsgolint/win32-x64@0.11.4': + optional: true + + '@oxlint/darwin-arm64@1.43.0': + optional: true + + '@oxlint/darwin-x64@1.43.0': + optional: true + + '@oxlint/linux-arm64-gnu@1.43.0': + optional: true + + '@oxlint/linux-arm64-musl@1.43.0': + optional: true + + '@oxlint/linux-x64-gnu@1.43.0': + optional: true + + '@oxlint/linux-x64-musl@1.43.0': + optional: true + + '@oxlint/win32-arm64@1.43.0': + optional: true + + '@oxlint/win32-x64@1.43.0': + optional: true + '@prettier/plugin-hermes@0.1.3': {} '@prettier/plugin-oxc@0.1.3': @@ -4040,6 +4176,27 @@ snapshots: '@oxc-resolver/binding-win32-ia32-msvc': 11.17.0 '@oxc-resolver/binding-win32-x64-msvc': 11.17.0 + oxlint-tsgolint@0.11.4: + optionalDependencies: + '@oxlint-tsgolint/darwin-arm64': 0.11.4 + '@oxlint-tsgolint/darwin-x64': 0.11.4 + '@oxlint-tsgolint/linux-arm64': 0.11.4 + '@oxlint-tsgolint/linux-x64': 0.11.4 + '@oxlint-tsgolint/win32-arm64': 0.11.4 + '@oxlint-tsgolint/win32-x64': 0.11.4 + + oxlint@1.43.0(oxlint-tsgolint@0.11.4): + optionalDependencies: + '@oxlint/darwin-arm64': 1.43.0 + '@oxlint/darwin-x64': 1.43.0 + '@oxlint/linux-arm64-gnu': 1.43.0 + '@oxlint/linux-arm64-musl': 1.43.0 + '@oxlint/linux-x64-gnu': 1.43.0 + '@oxlint/linux-x64-musl': 1.43.0 + '@oxlint/win32-arm64': 1.43.0 + '@oxlint/win32-x64': 1.43.0 + oxlint-tsgolint: 0.11.4 + parent-module@2.0.0: dependencies: callsites: 3.1.0 diff --git a/src/create-plugin.ts b/src/create-plugin.ts index 0f60f9a..2dac6d4 100644 --- a/src/create-plugin.ts +++ b/src/create-plugin.ts @@ -33,7 +33,7 @@ export function createPlugin(transforms: TransformOptions[]) { } } - for (let [name, meta] of Object.entries(opts.printers ?? {})) { + for (let [name, _meta] of Object.entries(opts.printers ?? {})) { printers[name] = async () => { let plugin = await loadPlugins(opts.load ?? []) let original = plugin.printers?.[name] @@ -154,17 +154,13 @@ async function loadPlugins(fns: PluginLoad[]) { } for (let moduleName of fns) { - try { - let loaded = typeof moduleName === 'string' ? await loadIfExistsESM(moduleName) : moduleName - Object.assign(plugin.parsers!, loaded.parsers ?? {}) - Object.assign(plugin.printers!, loaded.printers ?? {}) - Object.assign(plugin.options!, loaded.options ?? {}) - Object.assign(plugin.defaultOptions!, loaded.defaultOptions ?? {}) - - plugin.languages = [...(plugin.languages ?? []), ...(loaded.languages ?? [])] - } catch (err) { - throw err - } + let loaded = typeof moduleName === 'string' ? await loadIfExistsESM(moduleName) : moduleName + Object.assign(plugin.parsers!, loaded.parsers ?? {}) + Object.assign(plugin.printers!, loaded.printers ?? {}) + Object.assign(plugin.options!, loaded.options ?? {}) + Object.assign(plugin.defaultOptions!, loaded.defaultOptions ?? {}) + + plugin.languages = [...(plugin.languages ?? []), ...(loaded.languages ?? [])] } return plugin diff --git a/src/index.ts b/src/index.ts index 8d0470f..6803466 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,7 +9,7 @@ import * as prettierParserCss from 'prettier/plugins/postcss' import { createPlugin } from './create-plugin.js' import type { Matcher } from './options.js' import { sortClasses, sortClassList } from './sorting.js' -import { defineTransform, type TransformOptions } from './transform.js' +import { defineTransform } from './transform.js' import type { StringChange, TransformerEnv } from './types' import { spliceChangesIntoString, visit, type Path } from './utils.js' diff --git a/src/resolve.ts b/src/resolve.ts index e106914..b8c2d16 100644 --- a/src/resolve.ts +++ b/src/resolve.ts @@ -43,7 +43,7 @@ export function maybeResolve(name: string) { try { modpath = resolveJsFrom(fileURLToPath(import.meta.url), name) resolveCache.set(name, modpath) - } catch (err) { + } catch { resolveCache.set(name, null) return null } @@ -66,7 +66,7 @@ export async function loadIfExists(name: string): Promise { export function resolveJsFrom(base: string, id: string): string { try { return esmResolver.resolveSync({}, base, id) || id - } catch (err) { + } catch { return cjsResolver.resolveSync({}, base, id) || id } } diff --git a/src/sorter.ts b/src/sorter.ts index 3a678bc..bb0ddd1 100644 --- a/src/sorter.ts +++ b/src/sorter.ts @@ -201,12 +201,12 @@ export async function getTailwindConfig(options: TailwindConfigOptions): Promise }) } -let resolvedModCache = expiringMap(10_000) +let resolvedModCache = expiringMap(10_000) async function resolveTailwindPath( options: { packageName?: string }, baseDir: string, -): Promise<[any | null, string | null]> { +): Promise<[any, string | null]> { let pkgName = options.packageName ?? 'tailwindcss' let makeKey = (dir: string) => `${pkgName}:${dir}` @@ -218,7 +218,7 @@ async function resolveTailwindPath( let resolve = async () => { let pkgDir: string | null = null - let mod: any | null = null + let mod: any = null try { let pkgPath = resolveJsFrom(baseDir, pkgName) @@ -228,7 +228,7 @@ async function resolveTailwindPath( pkgDir = path.dirname(pkgFile) } catch {} - return [mod, pkgDir] as [any | null, string | null] + return [mod, pkgDir] as [any, string | null] } let result = await resolve() diff --git a/src/transform.ts b/src/transform.ts index 42439f7..d0cf757 100644 --- a/src/transform.ts +++ b/src/transform.ts @@ -1,4 +1,4 @@ -import type { AstPath, ParserOptions, Plugin } from 'prettier' +import type { AstPath, Plugin } from 'prettier' import type { TransformerEnv } from './types' export function defineTransform(opts: TransformOptions) { diff --git a/src/utils.bench.ts b/src/utils.bench.ts index aef80fd..77f6740 100644 --- a/src/utils.bench.ts +++ b/src/utils.bench.ts @@ -13,7 +13,7 @@ describe('spliceChangesIntoString', () => { function buildFixture(repeatCount: number, changeCount: number) { // A large set of changes across random places in the string let indxes = new Set( - Array.from({ length: changeCount }, (_, i) => Math.ceil(Math.random() * repeatCount)), + Array.from({ length: changeCount }, () => Math.ceil(Math.random() * repeatCount)), ) let changes: StringChange[] = Array.from(indxes).flatMap((idx) => { diff --git a/src/utils.test.ts b/src/utils.test.ts index 5d89c48..d472671 100644 --- a/src/utils.test.ts +++ b/src/utils.test.ts @@ -1,4 +1,4 @@ -import { bench, describe, test } from 'vitest' +import { describe, test } from 'vitest' import type { StringChange } from './types' import { spliceChangesIntoString } from './utils' diff --git a/src/utils.ts b/src/utils.ts index 19ec319..bba1fc2 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -7,7 +7,7 @@ export function loadIfExists(name: string): any { if (require.resolve(name)) { return require(name) } - } catch (e) { + } catch { return null } } diff --git a/tests/plugins.test.ts b/tests/plugins.test.ts index cdaeb7f..9c15329 100644 --- a/tests/plugins.test.ts +++ b/tests/plugins.test.ts @@ -1,6 +1,5 @@ import { createRequire } from 'node:module' import dedent from 'dedent' -import * as prettier from 'prettier' import { test } from 'vitest' import { javascript } from './tests.js' import type { TestEntry } from './utils.js' diff --git a/tests/tests.ts b/tests/tests.ts index 8df7da4..5789949 100644 --- a/tests/tests.ts +++ b/tests/tests.ts @@ -280,6 +280,6 @@ export let tests: Record = { acorn: javascript, meriyah: javascript, mdx: javascript - .filter((test) => !/^\/\*/.test(test[0]) && !/^\/\*/.test(test[1])) + .filter((test) => !test[0].startsWith('/*') && !test[1].startsWith('/*')) .map((test) => [test[0].replace(/^;/, ''), test[1].replace(/^;/, ''), test[2]]), }