Upgrade to ESLint 9
This commit is contained in:
@ -1,31 +0,0 @@
|
||||
#!/usr/bin/env tsx
|
||||
import { promises as fs } from 'node:fs';
|
||||
|
||||
import { camelCase } from 'lodash';
|
||||
|
||||
export async function buildLocalRules() {
|
||||
const files = (await fs.readdir('./src/custom'))
|
||||
.filter(file => file.endsWith('.ts'))
|
||||
.filter(file => file !== 'index.ts')
|
||||
.map(file => file.slice(0, -3));
|
||||
|
||||
const entryFile = /* js */ `
|
||||
import type { ESLintUtils } from '@typescript-eslint/utils';
|
||||
import type { Rule } from 'eslint';
|
||||
|
||||
${files.map(file => `import ${camelCase(file)} from './${file}';`).join('\n')}
|
||||
|
||||
export const rules: Record<
|
||||
string,
|
||||
Rule.RuleModule | ESLintUtils.RuleModule<string, unknown[]>
|
||||
> = {
|
||||
${files.map(file => `'${file}': ${camelCase(file)},`).join('\n ')}
|
||||
};
|
||||
`.trim();
|
||||
|
||||
await fs.writeFile('./src/custom/index.ts', entryFile + '\n');
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
void buildLocalRules();
|
||||
}
|
@ -5,19 +5,20 @@ import { relative, resolve } from 'node:path';
|
||||
|
||||
import esbuild from 'esbuild';
|
||||
import type { Plugin } from 'esbuild';
|
||||
import { memoize } from 'lodash';
|
||||
import { gray, green } from 'picocolors';
|
||||
import { memoize } from 'lodash-es';
|
||||
import c from 'picocolors';
|
||||
import { minify_sync } from 'terser';
|
||||
|
||||
import { dependencies } from '../dist/package.json';
|
||||
|
||||
import { buildLocalRules } from './build-local-rules';
|
||||
import { dts } from './dts';
|
||||
import { babelPlugin } from './modifier';
|
||||
|
||||
const ENV = (process.env.NODE_ENV ??= 'production');
|
||||
const PROD = ENV === 'production';
|
||||
|
||||
const { gray, green } = c;
|
||||
|
||||
declare global {
|
||||
interface Array<T> {
|
||||
filter(
|
||||
@ -71,10 +72,7 @@ if (process.env.DEBUG) {
|
||||
|
||||
async function bundle(
|
||||
entry: string,
|
||||
outfile = entry
|
||||
.replace('./packages/', './dist/')
|
||||
.replace('src/', '')
|
||||
.replace('.ts', '.js'),
|
||||
outfile: string,
|
||||
options?: esbuild.BuildOptions & { treeShaking?: boolean },
|
||||
) {
|
||||
const output = await esbuild.build({
|
||||
@ -140,25 +138,31 @@ async function editPackageJson() {
|
||||
}
|
||||
|
||||
async function useText(path: string) {
|
||||
const state = await fs.readFile(path, 'utf-8');
|
||||
const state = await fs.readFile(path, 'utf8');
|
||||
const setState = (text: string) => fs.writeFile(path, text);
|
||||
return [state, setState] as const;
|
||||
}
|
||||
|
||||
function bundleType(source: string, output: string) {
|
||||
return dts({
|
||||
source,
|
||||
dist: output,
|
||||
project: './tsconfig.build.json',
|
||||
});
|
||||
try {
|
||||
return dts({
|
||||
source,
|
||||
dist: output,
|
||||
project: './tsconfig.build.json',
|
||||
});
|
||||
} catch {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('Building local rules…');
|
||||
await buildLocalRules();
|
||||
|
||||
console.log('Building type definitions…');
|
||||
bundleType('./src/index.ts', './dist/index.d.ts');
|
||||
try {
|
||||
await fs.rm('dist/config', { recursive: true });
|
||||
} catch {
|
||||
// noop
|
||||
}
|
||||
|
||||
bundleType('./src/prettier.ts', './dist/prettier.d.ts');
|
||||
bundleType('./src/types.ts', './dist/types.d.ts');
|
||||
|
||||
@ -166,13 +170,12 @@ async function main() {
|
||||
|
||||
console.log('Building packages…');
|
||||
await Promise.all([
|
||||
bundle('./packages/eslint-plugin-jsx-a11y/src/index.js'),
|
||||
bundle('./packages/eslint-plugin-react-hooks/index.ts'),
|
||||
bundle('./packages/eslint-plugin-n/lib/index.js', './dist/eslint-plugin-n/index.js'),
|
||||
bundle('./packages/eslint-import-resolver-typescript/src/index.ts'),
|
||||
bundle('./src/custom/index.ts', './dist/eslint-plugin-custom/index.js'),
|
||||
bundle('./src/local/index.ts', './dist/eslint-plugin-local/index.js'),
|
||||
bundle('./src/index.ts', './dist/index.js', unminify),
|
||||
bundle('./src/index.ts', undefined!, {
|
||||
format: 'esm',
|
||||
splitting: true,
|
||||
outdir: './dist/config',
|
||||
...unminify,
|
||||
}),
|
||||
bundle('./src/types.ts', './dist/types.js', unminify),
|
||||
bundle('./src/prettier.ts', './dist/prettier.js', unminify),
|
||||
bundle('./src/install.ts', './dist/install.js', {
|
||||
@ -185,9 +188,8 @@ async function main() {
|
||||
editPackageJson(),
|
||||
]);
|
||||
|
||||
console.log('Removing redirect…');
|
||||
const [distIndex, setDistIndex] = await useText('./dist/index.js');
|
||||
await setDistIndex(distIndex.replace(/import.*redirect.*;/g, ''));
|
||||
// bundleType('./src/index.ts', './dist/config/index.d.ts');
|
||||
await fs.copyFile('./src/config.d.ts', './dist/config/index.d.ts');
|
||||
}
|
||||
|
||||
void main();
|
||||
|
@ -3,8 +3,7 @@ import fs from 'node:fs';
|
||||
import { builtinModules } from 'node:module';
|
||||
|
||||
import glob from 'fast-glob';
|
||||
|
||||
import { uniq } from 'lodash';
|
||||
import { uniq } from 'lodash-es';
|
||||
|
||||
import { dependencies, peerDependencies } from '../dist/package.json';
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
#!/usr/bin/env node
|
||||
import * as ts from 'typescript';
|
||||
import {
|
||||
type EntryPointConfig,
|
||||
generateDtsBundle,
|
||||
} from 'dts-bundle-generator/dist/bundle-generator';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
export function dts({
|
||||
source,
|
||||
|
@ -1,11 +1,14 @@
|
||||
#!/usr/bin/env tsx
|
||||
import assert from 'node:assert';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { resolve, extname } from 'node:path';
|
||||
import type { Loader, Plugin } from 'esbuild';
|
||||
import { extname, resolve } from 'node:path';
|
||||
|
||||
import * as babel from '@babel/core';
|
||||
import type { types as t, types } from '@babel/core';
|
||||
import { createMacro, type MacroHandler } from 'babel-plugin-macros';
|
||||
import babelMacros, { type MacroHandler } from 'babel-plugin-macros';
|
||||
import type { Loader, Plugin } from 'esbuild';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import * as polyfill from '../src/polyfill';
|
||||
|
||||
const polyfills = Object.keys(polyfill);
|
||||
@ -15,7 +18,7 @@ class HandlerMap {
|
||||
|
||||
set(names: string | string[], handler: MacroHandler) {
|
||||
names = Array.isArray(names) ? names : [names];
|
||||
const macro = createMacro(handler);
|
||||
const macro = babelMacros.createMacro(handler);
|
||||
for (const name of names) {
|
||||
this.map.set(name, macro);
|
||||
}
|
||||
@ -23,7 +26,7 @@ class HandlerMap {
|
||||
}
|
||||
|
||||
get keys() {
|
||||
return Array.from(this.map.keys());
|
||||
return [...this.map.keys()];
|
||||
}
|
||||
|
||||
resolvePath = (module: string) => module;
|
||||
@ -96,14 +99,14 @@ const map = new HandlerMap()
|
||||
'object.groupby',
|
||||
replace(t =>
|
||||
t.memberExpression(
|
||||
t.callExpression(t.identifier('require'), [t.stringLiteral('lodash')]),
|
||||
t.callExpression(t.identifier('require'), [t.stringLiteral('lodash-es')]),
|
||||
t.identifier('groupBy'),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// es-iterator-helpers/Iterator.prototype.*
|
||||
const polyfillPath = resolve(__dirname, '../src/polyfill.ts');
|
||||
const polyfillPath = resolve(import.meta.dirname, '../src/polyfill.ts');
|
||||
const requirePolyfill = (t: typeof types, name: string) =>
|
||||
t.memberExpression(
|
||||
t.callExpression(t.identifier('require'), [t.stringLiteral(polyfillPath)]),
|
||||
@ -127,15 +130,15 @@ map.set(
|
||||
|
||||
function replace(getReplacement: (types: typeof t) => t.Expression): MacroHandler {
|
||||
return ({ references, babel: { types: t } }) => {
|
||||
references.default.forEach(referencePath => {
|
||||
for (const referencePath of references.default) {
|
||||
referencePath.replaceWith(getReplacement(t));
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function proto(getProperty: (types: typeof t) => t.Expression): MacroHandler {
|
||||
return ({ references, babel: { types: t } }) => {
|
||||
references.default.forEach(referencePath => {
|
||||
for (const referencePath of references.default) {
|
||||
const { parent, parentPath } = referencePath;
|
||||
assert(t.isCallExpression(parent));
|
||||
const [callee, ...rest] = parent.arguments;
|
||||
@ -145,7 +148,7 @@ function proto(getProperty: (types: typeof t) => t.Expression): MacroHandler {
|
||||
rest,
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -160,21 +163,14 @@ export const babelPlugin: Plugin = {
|
||||
return null;
|
||||
}
|
||||
|
||||
let source = readFileSync(path, 'utf-8')
|
||||
const source = readFileSync(path, 'utf8')
|
||||
.replaceAll("require('object.hasown/polyfill')()", 'Object.hasOwn')
|
||||
.replaceAll("require('object.fromentries/polyfill')()", 'Object.fromEntries')
|
||||
.replaceAll(
|
||||
"Object.keys(require('prop-types'))",
|
||||
JSON.stringify(Object.keys(require('prop-types'))),
|
||||
JSON.stringify(Object.keys(PropTypes)),
|
||||
);
|
||||
|
||||
if (
|
||||
path.includes('packages/eslint-plugin-import/src/rules/') ||
|
||||
path.includes('packages/eslint-plugin-import/config/')
|
||||
) {
|
||||
source = source.replace('\nmodule.exports = {', '\nexport default {');
|
||||
}
|
||||
|
||||
const isFlow = source.includes('@flow');
|
||||
const loader = extname(path).slice(1) as Loader;
|
||||
|
||||
|
@ -3,7 +3,6 @@ sync() (
|
||||
cd "packages/$1" && git diff HEAD > "../../patch/$1.patch"
|
||||
)
|
||||
|
||||
sync eslint-import-resolver-typescript
|
||||
sync eslint-plugin-jsx-a11y
|
||||
sync eslint-plugin-n
|
||||
sync jsx-ast-utils
|
||||
|
Reference in New Issue
Block a user