mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-11-13 22:32:15 +08:00
Ship a native WidgetKit extension (routing mode, TUN and system proxy toggles) as part of every macOS build. The extension talks to the Rust backend over an App Group Unix socket with mutual code-signing checks, reuses the backend i18n catalogs, and stays inert on macOS < 14. A beforeBundle hook builds, localizes and pre-signs the extension before Tauri signs the host; pnpm build resolves a single local signing identity automatically and CI keeps using its injected credentials. An Xcode style-preview host is included for iterating on the widget layout. The i18n cleanup scanner now also scans Swift sources so widget-only keys are not flagged unused. Signed-off-by: Tunglies <77394545+Tunglies@users.noreply.github.com>
167 lines
4.9 KiB
TypeScript
167 lines
4.9 KiB
TypeScript
import eslintJS from '@eslint/js'
|
|
import eslintReact from '@eslint-react/eslint-plugin'
|
|
import { defineConfig } from 'eslint/config'
|
|
import { createTypeScriptImportResolver } from 'eslint-import-resolver-typescript'
|
|
import pluginESx from 'eslint-plugin-es-x'
|
|
import pluginImportX from 'eslint-plugin-import-x'
|
|
import pluginReactCompiler from 'eslint-plugin-react-compiler'
|
|
import pluginReactHooks from 'eslint-plugin-react-hooks'
|
|
import pluginReactRefresh from 'eslint-plugin-react-refresh'
|
|
import PluginSukka from 'eslint-plugin-sukka'
|
|
import pluginUnusedImports from 'eslint-plugin-unused-imports'
|
|
import globals from 'globals'
|
|
import tseslint from 'typescript-eslint'
|
|
|
|
export default defineConfig([
|
|
pluginESx.configs['flat/restrict-to-es2022'],
|
|
{
|
|
files: ['**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
|
|
|
plugins: {
|
|
js: eslintJS,
|
|
// @ts-expect-error -- https://github.com/typescript-eslint/typescript-eslint/issues/11543
|
|
'react-hooks': pluginReactHooks,
|
|
'react-compiler': pluginReactCompiler,
|
|
'es-x': pluginESx,
|
|
'import-x': pluginImportX,
|
|
'react-refresh': pluginReactRefresh,
|
|
'unused-imports': pluginUnusedImports,
|
|
sukka: PluginSukka,
|
|
},
|
|
|
|
extends: [
|
|
eslintJS.configs.recommended,
|
|
tseslint.configs.recommended,
|
|
eslintReact.configs['recommended-typescript'],
|
|
],
|
|
|
|
languageOptions: {
|
|
globals: globals.browser,
|
|
parserOptions: {
|
|
projectService: {
|
|
allowDefaultProject: [
|
|
'eslint.config.ts',
|
|
`vite.config.mts`,
|
|
'scripts/*.mjs',
|
|
'crates/clash-verge-widget/build/*.mjs',
|
|
'tests/*.ts',
|
|
'src/polyfills/*.js',
|
|
'tests/*.mjs',
|
|
],
|
|
},
|
|
},
|
|
},
|
|
|
|
settings: {
|
|
react: {
|
|
version: 'detect',
|
|
},
|
|
'import-x/resolver-next': [
|
|
createTypeScriptImportResolver({
|
|
project: './tsconfig.json',
|
|
}),
|
|
],
|
|
},
|
|
|
|
rules: {
|
|
// React
|
|
'react-hooks/rules-of-hooks': 'error',
|
|
'react-hooks/exhaustive-deps': 'error',
|
|
'react-compiler/react-compiler': 'error',
|
|
'react-refresh/only-export-components': [
|
|
'warn',
|
|
{ allowConstantExport: true },
|
|
],
|
|
|
|
'@eslint-react/no-forward-ref': 'off',
|
|
|
|
// React performance and production quality rules
|
|
'@eslint-react/no-array-index-key': 'warn',
|
|
'@eslint-react/no-children-count': 'error',
|
|
'@eslint-react/no-children-for-each': 'error',
|
|
'@eslint-react/no-children-map': 'error',
|
|
'@eslint-react/no-children-only': 'error',
|
|
'@eslint-react/jsx-no-children-prop': 'error',
|
|
'@eslint-react/no-children-to-array': 'error',
|
|
'@eslint-react/no-class-component': 'error',
|
|
'@eslint-react/no-clone-element': 'error',
|
|
'@eslint-react/no-create-ref': 'error',
|
|
'@eslint-react/no-direct-mutation-state': 'error',
|
|
'@eslint-react/no-implicit-key': 'error',
|
|
'@eslint-react/no-set-state-in-component-did-mount': 'error',
|
|
'@eslint-react/no-set-state-in-component-did-update': 'error',
|
|
'@eslint-react/no-set-state-in-component-will-update': 'error',
|
|
'@eslint-react/no-unstable-context-value': 'warn',
|
|
'@eslint-react/no-unstable-default-props': 'warn',
|
|
'@eslint-react/no-unused-class-component-members': 'error',
|
|
'@eslint-react/no-unused-state': 'error',
|
|
'@eslint-react/jsx-no-useless-fragment': 'warn',
|
|
'sukka/react-prefer-destructuring-assignment': 'warn',
|
|
|
|
// TypeScript
|
|
'@typescript-eslint/no-explicit-any': 'off',
|
|
|
|
// unused-imports 代替 no-unused-vars
|
|
'@typescript-eslint/no-unused-vars': 'off',
|
|
'unused-imports/no-unused-imports': 'error',
|
|
'unused-imports/no-unused-vars': [
|
|
'warn',
|
|
{
|
|
vars: 'all',
|
|
varsIgnorePattern: '^_',
|
|
args: 'after-used',
|
|
argsIgnorePattern: '^_',
|
|
caughtErrorsIgnorePattern: '^ignore',
|
|
},
|
|
],
|
|
|
|
// Import
|
|
'import-x/no-unresolved': 'error',
|
|
'import-x/order': [
|
|
'warn',
|
|
{
|
|
groups: [
|
|
'builtin',
|
|
'external',
|
|
'internal',
|
|
'parent',
|
|
'sibling',
|
|
'index',
|
|
],
|
|
'newlines-between': 'always',
|
|
alphabetize: {
|
|
order: 'asc',
|
|
caseInsensitive: true,
|
|
},
|
|
},
|
|
],
|
|
|
|
// 其他常见
|
|
'prefer-const': 'warn',
|
|
'no-case-declarations': 'error',
|
|
'no-fallthrough': 'error',
|
|
'no-empty': ['warn', { allowEmptyCatch: true }],
|
|
},
|
|
},
|
|
{
|
|
files: ['scripts/*.mjs', 'crates/clash-verge-widget/build/*.mjs'],
|
|
|
|
languageOptions: {
|
|
globals: {
|
|
...globals.browser,
|
|
...globals.node,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
files: ['scripts/perf/*.{mjs,mts}'],
|
|
languageOptions: {
|
|
globals: globals.node,
|
|
parserOptions: {
|
|
projectService: false,
|
|
project: './scripts/perf/tsconfig.node.json',
|
|
},
|
|
},
|
|
},
|
|
])
|