Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
50a9a3a
build: add eslint-plugin-oxlint dependency
EurFelux Sep 14, 2025
6a87d3c
build(eslint): add oxlint plugin to eslint config
EurFelux Sep 14, 2025
020d8c5
build: add oxlint v1.15.0 as a dependency
EurFelux Sep 14, 2025
26387fe
build: add oxlint to linting commands
EurFelux Sep 14, 2025
d4fd8fa
build: add oxlint configuration file
EurFelux Sep 14, 2025
786e797
chore: update oxlint configuration and related settings
EurFelux Sep 14, 2025
f29d31d
fix: lint warning
EurFelux Sep 14, 2025
e3f87f4
chore: update oxlintrc from eslint.recommended
EurFelux Sep 14, 2025
7f9cab4
refactor(lint): update eslint and oxlint configurations
EurFelux Sep 14, 2025
c6935a9
fix: lint error
EurFelux Sep 14, 2025
3a92040
fix(file): replace eslint-disable with oxlint-disable in sanitizeFile…
EurFelux Sep 14, 2025
cb81241
fix: enforce stricter linting by failing on warnings in test:lint script
EurFelux Sep 14, 2025
ef58b90
feat: add recommended ts-eslint rules into exlint
EurFelux Sep 14, 2025
fb89f2c
docs: remove outdated comment in oxlint config file
EurFelux Sep 14, 2025
bb8f802
style: disable typescript/no-require-imports rule in oxlint config
EurFelux Sep 14, 2025
89a1236
docs(utils): fix comment typo from NODE to NOTE
EurFelux Sep 14, 2025
0561a3a
fix(MessageErrorBoundary): correct error description display condition
EurFelux Sep 14, 2025
a4b0ad8
chore: add oxc-vscode extension to recommended list
EurFelux Sep 14, 2025
b6a353a
ci(workflows): reorder format check step in pr-ci.yml
EurFelux Sep 14, 2025
e821e04
chore: update yarn.lock
EurFelux Sep 15, 2025
c116c16
Merge branch 'main' of github.com:CherryHQ/cherry-studio into chore/o…
EurFelux Sep 15, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/pr-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ jobs:
- name: Install Dependencies
run: yarn install

- name: Format Check
run: yarn format:check

- name: Lint Check
run: yarn test:lint

- name: Format Check
run: yarn format:check

- name: Type Check
run: yarn typecheck

Expand Down
215 changes: 215 additions & 0 deletions .oxlintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"categories": {},
"env": {
"es2022": true
},
"globals": {},
"ignorePatterns": [
"node_modules/**",
"build/**",
"dist/**",
"out/**",
"local/**",
".yarn/**",
".gitignore",
"scripts/cloudflare-worker.js",
"src/main/integration/nutstore/sso/lib/**",
"src/main/integration/cherryin/index.js",
"src/main/integration/nutstore/sso/lib/**",
"src/renderer/src/ui/**",
"packages/**/dist",
"eslint.config.mjs"
],
"overrides": [
// set different env
{
"env": {
"node": true
},
"files": ["src/main/**", "resources/scripts/**", "scripts/**", "playwright.config.ts", "electron.vite.config.ts"]
},
{
"env": {
"browser": true
},
"files": [
"src/renderer/**/*.{ts,tsx}",
"packages/aiCore/**",
"packages/extension-table-plus/**",
"resources/js/**"
]
},
{
"env": {
"node": true,
"vitest": true
},
"files": ["**/__tests__/*.test.{ts,tsx}", "tests/**"]
},
{
"env": {
"browser": true,
"node": true
},
"files": ["src/preload/**"]
}
],
// We don't use the React plugin here because its behavior differs slightly from that of ESLint's React plugin.
"plugins": ["unicorn", "typescript", "oxc", "import"],
Comment on lines +58 to +59
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like 2x issue preventing you from using react plugin.

First being a bug which should be fixed in the next version here: oxc-project/oxc#13815

The second being:

  ⚠ eslint-plugin-react(no-children-prop): Avoid passing children using a prop.
     ╭─[src/renderer/src/components/DraggableList/virtual-list.tsx:188:23]
 187 │                       virtualizer={virtualizer}
 188 │                       children={children}
     ·                       ────────
 189 │                       disabled={disabled}
     ╰────
  help: The canonical way to pass children in React is to use JSX elements

Which i think you should just disable in your oxlint config as it's not enabled in your eslint config?

Thanks for using oxlint!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for following up on this issue! no-children-prop is not a big deal because just few errors here. Once the issue with exhaustive-deps is resolved, we can replace the eslint react plugin with the oxlint React plugin.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

awesome, going to try and do a release today 🤞

"rules": {
"constructor-super": "error",
"for-direction": "error",
"getter-return": "error",
"no-array-constructor": "off",
// "import/no-cycle": "error", // tons of error, bro
"no-async-promise-executor": "error",
"no-caller": "warn",
"no-case-declarations": "error",
"no-class-assign": "error",
"no-compare-neg-zero": "error",
"no-cond-assign": "error",
"no-const-assign": "error",
"no-constant-binary-expression": "error",
"no-constant-condition": "error",
"no-control-regex": "error",
"no-debugger": "error",
"no-delete-var": "error",
"no-dupe-args": "error",
"no-dupe-class-members": "error",
"no-dupe-else-if": "error",
"no-dupe-keys": "error",
"no-duplicate-case": "error",
"no-empty": "error",
"no-empty-character-class": "error",
"no-empty-pattern": "error",
"no-empty-static-block": "error",
"no-eval": "warn",
"no-ex-assign": "error",
"no-extra-boolean-cast": "error",
"no-fallthrough": "warn",
"no-func-assign": "error",
"no-global-assign": "error",
"no-import-assign": "error",
"no-invalid-regexp": "error",
"no-irregular-whitespace": "error",
"no-loss-of-precision": "error",
"no-misleading-character-class": "error",
"no-new-native-nonconstructor": "error",
"no-nonoctal-decimal-escape": "error",
"no-obj-calls": "error",
"no-octal": "error",
"no-prototype-builtins": "error",
"no-redeclare": "error",
"no-regex-spaces": "error",
"no-self-assign": "error",
"no-setter-return": "error",
"no-shadow-restricted-names": "error",
"no-sparse-arrays": "error",
"no-this-before-super": "error",
"no-unassigned-vars": "warn",
"no-undef": "error",
"no-unexpected-multiline": "error",
"no-unreachable": "error",
"no-unsafe-finally": "error",
"no-unsafe-negation": "error",
"no-unsafe-optional-chaining": "error",
"no-unused-expressions": "off", // this rule disallow us to use expression to call function, like `condition && fn()`
"no-unused-labels": "error",
"no-unused-private-class-members": "error",
"no-unused-vars": ["error", { "caughtErrors": "none" }],
"no-useless-backreference": "error",
"no-useless-catch": "error",
"no-useless-escape": "error",
"no-useless-rename": "warn",
"no-with": "error",
"oxc/bad-array-method-on-arguments": "warn",
"oxc/bad-char-at-comparison": "warn",
"oxc/bad-comparison-sequence": "warn",
"oxc/bad-min-max-func": "warn",
"oxc/bad-object-literal-comparison": "warn",
"oxc/bad-replace-all-arg": "warn",
"oxc/const-comparisons": "warn",
"oxc/double-comparisons": "warn",
"oxc/erasing-op": "warn",
"oxc/missing-throw": "warn",
"oxc/number-arg-out-of-range": "warn",
"oxc/only-used-in-recursion": "off", // manually off bacause of existing warning. may turn it on in the future
"oxc/uninvoked-array-callback": "warn",
"require-yield": "error",
"typescript/await-thenable": "warn",
// "typescript/ban-ts-comment": "error",
"typescript/no-array-constructor": "error",
// "typescript/consistent-type-imports": "error",
"typescript/no-array-delete": "warn",
"typescript/no-base-to-string": "warn",
"typescript/no-duplicate-enum-values": "error",
"typescript/no-duplicate-type-constituents": "warn",
"typescript/no-empty-object-type": "off",
"typescript/no-explicit-any": "off", // not safe but too many errors
"typescript/no-extra-non-null-assertion": "error",
"typescript/no-floating-promises": "warn",
"typescript/no-for-in-array": "warn",
"typescript/no-implied-eval": "warn",
"typescript/no-meaningless-void-operator": "warn",
"typescript/no-misused-new": "error",
"typescript/no-misused-spread": "warn",
"typescript/no-namespace": "error",
"typescript/no-non-null-asserted-optional-chain": "off", // it's off now. but may turn it on.
"typescript/no-redundant-type-constituents": "warn",
"typescript/no-require-imports": "off",
"typescript/no-this-alias": "error",
"typescript/no-unnecessary-parameter-property-assignment": "warn",
"typescript/no-unnecessary-type-constraint": "error",
"typescript/no-unsafe-declaration-merging": "error",
"typescript/no-unsafe-function-type": "error",
"typescript/no-unsafe-unary-minus": "warn",
"typescript/no-useless-empty-export": "warn",
"typescript/no-wrapper-object-types": "error",
"typescript/prefer-as-const": "error",
"typescript/prefer-namespace-keyword": "error",
"typescript/require-array-sort-compare": "warn",
"typescript/restrict-template-expressions": "warn",
"typescript/triple-slash-reference": "error",
"typescript/unbound-method": "warn",
"unicorn/no-await-in-promise-methods": "warn",
"unicorn/no-empty-file": "off", // manually off bacause of existing warning. may turn it on in the future
"unicorn/no-invalid-fetch-options": "warn",
"unicorn/no-invalid-remove-event-listener": "warn",
"unicorn/no-new-array": "off", // manually off bacause of existing warning. may turn it on in the future
"unicorn/no-single-promise-in-promise-methods": "warn",
"unicorn/no-thenable": "off", // manually off bacause of existing warning. may turn it on in the future
"unicorn/no-unnecessary-await": "warn",
"unicorn/no-useless-fallback-in-spread": "warn",
"unicorn/no-useless-length-check": "warn",
"unicorn/no-useless-spread": "off", // manually off bacause of existing warning. may turn it on in the future
"unicorn/prefer-set-size": "warn",
"unicorn/prefer-string-starts-ends-with": "warn",
"use-isnan": "error",
"valid-typeof": "error"
},
"settings": {
"jsdoc": {
"augmentsExtendsReplacesDocs": false,
"exemptDestructuredRootsFromChecks": false,
"ignoreInternal": false,
"ignorePrivate": false,
"ignoreReplacesDocs": true,
"implementsReplacesDocs": false,
"overrideReplacesDocs": true,
"tagNamePreference": {}
},
"jsx-a11y": {
"attributes": {},
"components": {},
"polymorphicPropName": null
},
"next": {
"rootDir": []
},
"react": {
"formComponents": [],
"linkComponents": []
}
}
}
1 change: 1 addition & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"dbaeumer.vscode-eslint",
"editorconfig.editorconfig",
"lokalise.i18n-ally",
"oxc.oxc-vscode",
"biomejs.biome"
]
}
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"editor.codeActionsOnSave": {
"source.fixAll.biome": "explicit",
"source.fixAll.eslint": "explicit",
"source.fixAll.oxc": "explicit",
"source.organizeImports": "never"
},
"editor.formatOnSave": true,
Expand Down
9 changes: 7 additions & 2 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import tseslint from '@electron-toolkit/eslint-config-ts'
import eslint from '@eslint/js'
import eslintReact from '@eslint-react/eslint-plugin'
import { defineConfig } from 'eslint/config'
import oxlint from 'eslint-plugin-oxlint'
import reactHooks from 'eslint-plugin-react-hooks'
import simpleImportSort from 'eslint-plugin-simple-import-sort'
import unusedImports from 'eslint-plugin-unused-imports'
Expand Down Expand Up @@ -50,7 +51,7 @@ export default defineConfig([
{
// LoggerService Custom Rules - only apply to src directory
files: ['src/**/*.{ts,tsx,js,jsx}'],
ignores: ['src/**/__tests__/**', 'src/**/__mocks__/**', 'src/**/*.test.*'],
ignores: ['src/**/__tests__/**', 'src/**/__mocks__/**', 'src/**/*.test.*', 'src/preload/**'],
rules: {
'no-restricted-syntax': [
process.env.PRCI ? 'error' : 'warn',
Expand Down Expand Up @@ -125,5 +126,9 @@ export default defineConfig([
'src/renderer/src/ui/**',
'packages/**/dist'
]
}
},
// turn off oxlint supported rules.
...oxlint.configs['flat/eslint'],
...oxlint.configs['flat/typescript'],
...oxlint.configs['flat/unicorn']
])
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,11 @@
"test:ui": "vitest --ui",
"test:watch": "vitest",
"test:e2e": "yarn playwright test",
"test:lint": "eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts",
"test:lint": "oxlint --deny-warnings && eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts",
"test:scripts": "vitest scripts",
"lint": "oxlint --fix && eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix && yarn typecheck && yarn check:i18n",
"format": "biome format --write && biome lint --write",
"format:check": "biome format && biome lint",
"lint": "eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix && yarn typecheck && yarn check:i18n",
"prepare": "git config blame.ignoreRevsFile .git-blame-ignore-revs && husky",
"claude": "dotenv -e .env -- claude"
},
Expand Down Expand Up @@ -245,6 +245,7 @@
"emoji-picker-element": "^1.22.1",
"epub": "patch:epub@npm%3A1.3.0#~/.yarn/patches/epub-npm-1.3.0-8325494ffe.patch",
"eslint": "^9.22.0",
"eslint-plugin-oxlint": "^1.15.0",
"eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-simple-import-sort": "^12.1.1",
"eslint-plugin-unused-imports": "^4.1.4",
Expand Down Expand Up @@ -280,6 +281,8 @@
"notion-helper": "^1.3.22",
"npx-scope-finder": "^1.2.0",
"openai": "patch:openai@npm%3A5.12.2#~/.yarn/patches/openai-npm-5.12.2-30b075401c.patch",
"oxlint": "^1.15.0",
"oxlint-tsgolint": "^0.2.0",
"p-queue": "^8.1.0",
"pdf-lib": "^1.17.1",
"pdf-parse": "^1.1.1",
Expand Down
2 changes: 1 addition & 1 deletion src/main/apiServer/middleware/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { loggerService } from '../../services/LoggerService'

const logger = loggerService.withContext('ApiServerErrorHandler')

// eslint-disable-next-line @typescript-eslint/no-unused-vars
// oxlint-disable-next-line @typescript-eslint/no-unused-vars
export const errorHandler = (err: Error, _req: Request, res: Response, _next: NextFunction) => {
logger.error('API Server Error:', err)

Expand Down
6 changes: 4 additions & 2 deletions src/main/ipc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { handleZoomFactor } from '@main/utils/zoom'
import { SpanEntity, TokenUsage } from '@mcp-trace/trace-core'
import { MIN_WINDOW_HEIGHT, MIN_WINDOW_WIDTH, UpgradeChannel } from '@shared/config/constant'
import { IpcChannel } from '@shared/IpcChannel'
import { FileMetadata, Provider, Shortcut, ThemeMode } from '@types'
import { FileMetadata, OcrProvider, Provider, Shortcut, SupportedOcrFile, ThemeMode } from '@types'
import checkDiskSpace from 'check-disk-space'
import { BrowserWindow, dialog, ipcMain, ProxyConfig, session, shell, systemPreferences, webContents } from 'electron'
import fontList from 'font-list'
Expand Down Expand Up @@ -827,7 +827,9 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
ipcMain.handle(IpcChannel.CodeTools_Run, codeToolsService.run)

// OCR
ipcMain.handle(IpcChannel.OCR_ocr, (_, ...args: Parameters<typeof ocrService.ocr>) => ocrService.ocr(...args))
ipcMain.handle(IpcChannel.OCR_ocr, (_, file: SupportedOcrFile, provider: OcrProvider) =>
ocrService.ocr(file, provider)
)

// CherryIN
ipcMain.handle(IpcChannel.Cherryin_GetSignature, (_, params) => generateSignature(params))
Expand Down
2 changes: 1 addition & 1 deletion src/main/knowledge/embedjs/loader/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,9 @@ export async function addFileLoader(

if (jsonParsed) {
loaderReturn = await ragApplication.addLoader(new JsonLoader({ object: jsonObject }), forceReload)
break
}
// fallthrough - JSON 解析失败时作为文本处理
// oxlint-disable-next-line no-fallthrough 利用switch特性,刻意不break
default:
// 文本类型处理(默认)
// 如果是其他文本类型且尚未读取文件,则读取文件
Expand Down
2 changes: 1 addition & 1 deletion src/main/knowledge/embedjs/loader/odLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export enum OdType {
OdtLoader = 'OdtLoader',
OdsLoader = 'OdsLoader',
OdpLoader = 'OdpLoader',
undefined = 'undefined'
Undefined = 'undefined'
}

export class OdLoader<OdType> extends BaseLoader<{ type: string }> {
Expand Down
2 changes: 1 addition & 1 deletion src/main/services/ExportService.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-case-declarations */
/* oxlint-disable no-case-declarations */
// ExportService

import { loggerService } from '@logger'
Expand Down
2 changes: 1 addition & 1 deletion src/main/services/MistralClientManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export class MistralClientManager {
private static instance: MistralClientManager
private client: Mistral | null = null

// eslint-disable-next-line @typescript-eslint/no-empty-function
// oxlint-disable-next-line @typescript-eslint/no-empty-function
private constructor() {}

public static getInstance(): MistralClientManager {
Expand Down
2 changes: 1 addition & 1 deletion src/main/services/ProxyManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ export class ProxyManager {
https.request = this.bindHttpMethod(this.originalHttpsRequest, agent)
}

// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
// oxlint-disable-next-line @typescript-eslint/no-unsafe-function-type
private bindHttpMethod(originalMethod: Function, agent: http.Agent | https.Agent) {
return (...args: any[]) => {
let url: string | URL | undefined
Expand Down
8 changes: 1 addition & 7 deletions src/main/services/ocr/builtin/SystemOcrService.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import { isLinux, isWin } from '@main/constant'
import { loadOcrImage } from '@main/utils/ocr'
import { OcrAccuracy, recognize } from '@napi-rs/system-ocr'
import {
ImageFileMetadata,
isImageFileMetadata as isImageFileMetadata,
OcrResult,
OcrSystemConfig,
SupportedOcrFile
} from '@types'
import { ImageFileMetadata, isImageFileMetadata, OcrResult, OcrSystemConfig, SupportedOcrFile } from '@types'

import { OcrBaseService } from './OcrBaseService'

Expand Down
Loading