diff --git a/bin/cli.js b/bin/cli.js index c8f27937..bccbd653 100755 --- a/bin/cli.js +++ b/bin/cli.js @@ -23,7 +23,7 @@ if (arg === 'chat') { console.log(packageJson.version) } else if (!arg) { serve(process.cwd(), undefined) // current directory -} else if (arg.match(/^https?:\/\//)) { +} else if (/^https?:\/\//.exec(arg)) { serve(undefined, arg) // url } else { // resolve file or directory diff --git a/bin/serve.js b/bin/serve.js index b9688b19..2c7e947d 100644 --- a/bin/serve.js +++ b/bin/serve.js @@ -123,7 +123,7 @@ function handleRequest(req, serveDirectory) { */ async function handleStatic(filePath, range) { const stats = await fs.stat(filePath).catch(() => undefined) - if (!stats || !stats.isFile()) { + if (!stats?.isFile()) { return { status: 404, content: 'not found' } } const contentLength = stats.size @@ -164,7 +164,7 @@ async function handleStatic(filePath, range) { */ async function handleHead(filePath) { const stats = await fs.stat(filePath).catch(() => undefined) - if (!stats || !stats.isFile()) { + if (!stats?.isFile()) { console.error(`file not found ${filePath}`) return { status: 404, content: 'not found' } } @@ -271,7 +271,7 @@ function startServer(port, path) { if (result.contentType) headers['Content-Type'] = result.contentType if (status === 301 && typeof content === 'string') { // handle redirect - headers['Location'] = content + headers.Location = content content = '' } // compress content diff --git a/bin/streamConverters.js b/bin/streamConverters.js index af392b67..474aeb8c 100644 --- a/bin/streamConverters.js +++ b/bin/streamConverters.js @@ -26,9 +26,9 @@ export async function pipe(input, output) { export function readStreamToReadableStream(fsStream) { return new ReadableStream({ start(/** @type {ReadableStreamDefaultController} */ controller) { - fsStream.on('data', (chunk) => controller.enqueue(chunk)) - fsStream.on('end', () => controller.close()) - fsStream.on('error', (error) => controller.error(error)) + fsStream.on('data', (chunk) => { controller.enqueue(chunk) }) + fsStream.on('end', () => { controller.close() }) + fsStream.on('error', (error) => { controller.error(error) }) }, cancel() { fsStream.destroy() diff --git a/eslint.config.js b/eslint.config.js index bb1ba40b..90cc3d25 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -3,63 +3,14 @@ import react from 'eslint-plugin-react' import reactHooks from 'eslint-plugin-react-hooks' import reactRefresh from 'eslint-plugin-react-refresh' import globals from 'globals' -import tseslint from 'typescript-eslint' +import typescript from 'typescript-eslint' -/** @type {import('eslint').Linter.Config.RulesRecord} */ -const sharedJsRules = { - 'arrow-spacing': 'error', - camelcase: 'off', - 'comma-spacing': 'error', - 'comma-dangle': ['error', 'always-multiline'], - 'eol-last': 'error', - eqeqeq: 'error', - 'func-style': ['error', 'declaration'], - indent: ['error', 2], - 'no-constant-condition': 'off', - 'no-extra-parens': 'error', - 'no-multi-spaces': 'error', - 'no-multiple-empty-lines': ['error', { max: 1, maxEOF: 0 }], - 'no-trailing-spaces': 'error', - 'no-unused-vars': 'off', - 'no-useless-concat': 'error', - 'no-useless-rename': 'error', - 'no-useless-return': 'error', - 'no-var': 'error', - 'object-curly-spacing': ['error', 'always'], - 'prefer-const': 'warn', - 'prefer-destructuring': ['warn', { - object: true, - array: false, - }], - 'prefer-promise-reject-errors': 'error', - quotes: ['error', 'single'], - 'require-await': 'warn', - semi: ['error', 'never'], - - 'sort-imports': ['error', { - ignoreDeclarationSort: true, - ignoreMemberSort: false, - memberSyntaxSortOrder: ['none', 'all', 'multiple', 'single'], - }], - - 'space-infix-ops': 'error', -} - -/** @type {import('eslint').Linter.Config.RulesRecord} */ -const sharedTsRules = { - '@typescript-eslint/restrict-template-expressions': 'off', - '@typescript-eslint/no-unused-vars': 'warn', - '@typescript-eslint/require-await': 'warn', -} - -export default tseslint.config( - { ignores: ['coverage/', 'dist/', 'lib/', 'packages/'] }, +export default typescript.config( + { ignores: ['coverage/', 'dist/', 'lib/'] }, { - settings: { react: { version: '18.3' } }, - extends: [javascript.configs.recommended, ...tseslint.configs.strictTypeChecked, ...tseslint.configs.stylisticTypeChecked], + extends: [javascript.configs.recommended, ...typescript.configs.strictTypeChecked, ...typescript.configs.stylisticTypeChecked], files: ['**/*.{ts,tsx,js}'], languageOptions: { - ecmaVersion: 2020, globals: globals.browser, parserOptions: { project: ['./tsconfig.json', './tsconfig.eslint.json'], @@ -67,7 +18,7 @@ export default tseslint.config( }, }, plugins: { - 'react': react, + react, 'react-hooks': reactHooks, 'react-refresh': reactRefresh, }, @@ -80,11 +31,55 @@ export default tseslint.config( { allowConstantExport: true }, ], ...javascript.configs.recommended.rules, - ...tseslint.configs.recommended.rules, - ...sharedJsRules, - ...sharedTsRules, - 'no-extra-parens': 'warn', + ...typescript.configs.recommended.rules, + // javascript + 'arrow-spacing': 'error', + camelcase: 'off', + 'comma-spacing': 'error', + 'comma-dangle': ['error', { + arrays: 'always-multiline', + objects: 'always-multiline', + imports: 'always-multiline', + exports: 'always-multiline', + functions: 'never', + }], + 'eol-last': 'error', + eqeqeq: 'error', + 'func-style': ['error', 'declaration'], + indent: ['error', 2], + 'no-constant-condition': 'off', + 'no-extra-parens': 'error', + 'no-multi-spaces': 'error', + 'no-multiple-empty-lines': ['error', { max: 1, maxEOF: 0 }], + 'no-trailing-spaces': 'error', + 'no-undef': 'error', + 'no-unused-vars': 'off', + 'no-useless-concat': 'error', + 'no-useless-rename': 'error', + 'no-useless-return': 'error', + 'no-var': 'error', + 'object-curly-spacing': ['error', 'always'], + 'prefer-const': 'warn', + 'prefer-destructuring': ['warn', { + object: true, + array: false, + }], + 'prefer-promise-reject-errors': 'error', + quotes: ['error', 'single'], + 'require-await': 'warn', + semi: ['error', 'never'], + 'sort-imports': ['error', { + ignoreDeclarationSort: true, + ignoreMemberSort: false, + memberSyntaxSortOrder: ['none', 'all', 'multiple', 'single'], + }], + 'space-infix-ops': 'error', + // typescript + '@typescript-eslint/restrict-template-expressions': 'off', + '@typescript-eslint/no-unused-vars': 'warn', + '@typescript-eslint/require-await': 'warn', }, + settings: { react: { version: 'detect' } }, }, { files: ['test/**/*.{ts,tsx}', '*.{js,ts}'], @@ -98,7 +93,7 @@ export default tseslint.config( }, { files: ['**/*.js'], - ...tseslint.configs.disableTypeChecked, + ...typescript.configs.disableTypeChecked, }, { files: ['bin/**/*.js', 'test/bin/**/*.js'], @@ -107,5 +102,5 @@ export default tseslint.config( ...globals.node, }, }, - }, + } ) diff --git a/package.json b/package.json index 09aea226..211f8b8c 100644 --- a/package.json +++ b/package.json @@ -28,16 +28,16 @@ ], "scripts": { "build:types": "tsc -b", - "build:lib": "vite build -c vite.lib.config.ts", - "build:app": "vite build -c vite.app.config.ts", + "build:lib": "vite build -c vite.lib.config.js", + "build:app": "vite build -c vite.app.config.js", "build": "run-s build:lib build:types build:app", - "coverage": "vitest run -c vite.lib.config.ts --coverage --coverage.include=src --coverage.include=bin", + "coverage": "vitest run -c vite.lib.config.js --coverage --coverage.include=src --coverage.include=bin", "dev": "run-p -l watch:ts watch:vite watch:serve", "lint": "eslint .", "prepublishOnly": "npm run build", "serve": "node bin/cli.js", "preserve": "npm run build", - "test": "vitest run -c vite.lib.config.ts", + "test": "vitest run -c vite.lib.config.js", "typecheck": "tsc --noEmit", "url": "run-p -l watch:ts watch:vite watch:url", "watch:ts": "tsc --watch", diff --git a/src/app.tsx b/src/app.tsx index 836348fc..40aba716 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -9,5 +9,5 @@ if (!root) throw new Error('missing root element') createRoot(root).render( - , + ) diff --git a/src/components/Breadcrumb.tsx b/src/components/Breadcrumb.tsx index 1bca9195..4702c7c0 100644 --- a/src/components/Breadcrumb.tsx +++ b/src/components/Breadcrumb.tsx @@ -16,7 +16,7 @@ export default function Breadcrumb({ source, config, children }: BreadcrumbProps return