Initial commit: expo-popcore-app

This commit is contained in:
imeepos
2025-12-25 16:25:55 +08:00
commit 02d0c807cd
160 changed files with 39560 additions and 0 deletions

339
eslint.config.mjs Normal file
View File

@@ -0,0 +1,339 @@
import eslintJs from '@eslint/js'
import typescriptEslint from '@typescript-eslint/eslint-plugin'
import typescriptParser from '@typescript-eslint/parser'
import { defineConfig } from 'eslint/config'
import expoConfig from 'eslint-config-expo/flat.js'
import i18nJsonPlugin from 'eslint-plugin-i18n-json'
import prettierPlugin from 'eslint-plugin-prettier'
import reactCompilerPlugin from 'eslint-plugin-react-compiler'
import reactNativePlugin from 'eslint-plugin-react-native'
import simpleImportSortPlugin from 'eslint-plugin-simple-import-sort'
import tailwindcssPlugin from 'eslint-plugin-tailwindcss'
// 由于 eslint-plugin-unicorn 在解析时出现语法错误,暂时移除该插件
// const unicornPlugin = await import('eslint-plugin-unicorn').catch(() => null)
import unusedImportsPlugin from 'eslint-plugin-unused-imports'
import path from 'path'
import { fileURLToPath } from 'url'
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
// 共享的插件配置 (移除可能与 expo 冲突的插件)
const sharedPlugins = {
prettier: prettierPlugin,
'unused-imports': unusedImportsPlugin,
'simple-import-sort': simpleImportSortPlugin,
tailwindcss: tailwindcssPlugin,
// unicorn: unicornPlugin,
'react-native': reactNativePlugin,
}
// 共享的规则配置
const sharedRules = {
// Prettier 配置
'prettier/prettier': [
'error',
{
singleQuote: true,
endOfLine: 'auto',
trailingComma: 'all',
printWidth: 100,
tabWidth: 4,
semi: false,
arrowParens: 'always',
bracketSameLine: false,
bracketSpacing: true,
jsxSingleQuote: false,
useTabs: false,
quoteProps: 'as-needed',
plugins: ['prettier-plugin-tailwindcss'],
},
{ usePrettierrc: false },
],
// 通用规则
'max-params': ['error', 3],
'max-lines-per-function': ['error', 500],
// Import 规则
'import/prefer-default-export': 'off',
'import/no-cycle': ['error', { maxDepth: '∞' }],
// Import 排序
'simple-import-sort/imports': 'error',
'simple-import-sort/exports': 'error',
// 未使用的导入
'unused-imports/no-unused-imports': 'error',
'unused-imports/no-unused-vars': [
'error',
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
caughtErrorsIgnorePattern: '^_',
},
],
// Tailwind CSS 规则
'tailwindcss/classnames-order': 'off',
'tailwindcss/enforces-negative-arbitrary-values': 'error',
'tailwindcss/enforces-shorthand': 'error',
'tailwindcss/migration-from-tailwind-2': 'error',
'tailwindcss/no-arbitrary-value': 'off',
'tailwindcss/no-contradicting-classname': 'error',
'tailwindcss/no-custom-classname': 'off',
'tailwindcss/no-unnecessary-arbitrary-value': 'error',
// Unicorn 规则
'unicorn/filename-case': [
'error',
{
case: 'kebabCase',
ignore: ['/android', '/ios'],
},
],
// React 规则
'react/display-name': 'off',
'react/destructuring-assignment': 'off',
'react/require-default-props': 'off',
'react/no-unescaped-entities': 'off',
// React/JSX 属性排序规则
'react/jsx-sort-props': [
'error',
{
callbacksLast: true, // 回调函数属性放在最后
shorthandFirst: true, // 简写属性放在前面
shorthandLast: false,
multiline: 'last', // 多行属性放在最后
ignoreCase: true, // 忽略大小写
noSortAlphabetically: false,
reservedFirst: true, // 保留属性(如 key, ref放在最前面
},
],
// JSX 属性换行规则
'react/jsx-max-props-per-line': [
'error',
{
maximum: 1, // 每行最多一个属性
when: 'multiline', // 仅在多行时生效
},
],
// JSX 第一个属性换行规则
'react/jsx-first-prop-new-line': ['error', 'multiline-multiprop'],
// React Native 规则
'react-native/no-unused-styles': 'off',
'react-native/split-platform-components': 'off',
'react-native/no-inline-styles': 'off',
'react-native/no-color-literals': 'off',
'react-native/no-raw-text': 'error',
'react-native/no-single-element-style-arrays': 'off',
// 限制导入规则 - 强制使用自定义 Text 组件
'no-restricted-imports': [
'error',
{
paths: [
{
name: 'react-native',
importNames: ['Text'],
message: 'please use @/components/ui instead of react-native Text',
},
],
patterns: [
{
group: ['react-native'],
importNames: ['Text'],
message: 'please use @/components/ui instead of react-native Text',
},
],
},
],
}
export default defineConfig([
// Base recommended config
eslintJs.configs.recommended,
// Expo config - 添加 expo 配置
expoConfig,
// Global ignores
{
ignores: [
'node_modules/',
'ios/',
'android/',
'.expo/',
'assets/',
'**/.vscode',
'**/.idea',
'dist/',
'**/app.json',
'**/eas.json',
],
},
// Base configuration for JavaScript files
{
files: ['**/*.js', '**/*.jsx', '**/*.mjs'],
plugins: sharedPlugins,
rules: {
...sharedRules,
'no-undef': 'off',
},
languageOptions: {
globals: {
__DEV__: 'readonly',
__dirname: 'readonly',
__filename: 'readonly',
console: 'readonly',
global: 'readonly',
process: 'readonly',
Buffer: 'readonly',
},
ecmaVersion: 'latest',
sourceType: 'module',
},
settings: {
'import/resolver': {
node: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
moduleDirectory: ['node_modules', './'],
},
},
},
},
// TypeScript files configuration
{
files: ['**/*.ts', '**/*.tsx'],
languageOptions: {
parser: typescriptParser,
parserOptions: {
project: './tsconfig.json',
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 'latest',
sourceType: 'module',
tsconfigRootDir: __dirname,
},
globals: {
__DEV__: 'readonly',
__dirname: 'readonly',
__filename: 'readonly',
console: 'readonly',
global: 'readonly',
process: 'readonly',
Buffer: 'readonly',
},
},
plugins: {
...sharedPlugins,
'@typescript-eslint': typescriptEslint,
'react-compiler': reactCompilerPlugin,
},
rules: {
...sharedRules,
// TypeScript 特有规则
'@typescript-eslint/comma-dangle': 'off',
'@typescript-eslint/consistent-type-imports': [
'warn',
{
prefer: 'type-imports',
fixStyle: 'inline-type-imports',
disallowTypeAnnotations: true,
},
],
'@typescript-eslint/no-unused-vars': 'off',
// 禁止使用 any 类型的规则
'@typescript-eslint/no-explicit-any': 'error',
// 禁止将 any 类型作为参数传递
'@typescript-eslint/no-unsafe-argument': 'error',
// 禁止将 any 类型赋值给其他变量
'@typescript-eslint/no-unsafe-assignment': 'error',
// 禁止调用 any 类型的函数
'@typescript-eslint/no-unsafe-call': 'error',
// 禁止访问 any 类型的成员
'@typescript-eslint/no-unsafe-member-access': 'error',
// 禁止从函数返回 any 类型
'@typescript-eslint/no-unsafe-return': 'error',
// React Compiler rules
'react-compiler/react-compiler': 'error',
// Unicorn 特有配置 (覆盖共享配置)
'unicorn/prefer-module': 'off',
// Expo-specific rules
'no-undef': 'off', // TypeScript handles this
},
settings: {
'import/resolver': {
typescript: {
alwaysTryTypes: true,
project: path.resolve(__dirname, './tsconfig.json'),
},
node: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
moduleDirectory: ['node_modules', './'],
},
},
},
},
// Translation files configuration
{
files: ['translations/*.json'],
plugins: {
'i18n-json': i18nJsonPlugin,
},
processor: {
meta: { name: '.json' },
...i18nJsonPlugin.processors['.json'],
},
rules: {
...i18nJsonPlugin.configs.recommended.rules,
// 消息值的语法是否符合特定的国际化格式要求
'i18n-json/valid-message-syntax': [
2,
{
syntax: path.resolve('./scripts/i18next-syntax-validation.js'),
},
],
// 是否包含有效的 JSON 语法
'i18n-json/valid-json': 2,
// 按照特定的顺序排列
// 关闭解决新加字段覆盖问题
'i18n-json/sorted-keys': [
2,
{
order: 'asc',
indentSpaces: 4,
},
],
// 检查是否有缺失的键或者多出来的键
'i18n-json/identical-keys': [
2,
{
filePath: path.resolve('./translations/en-US.json'),
},
],
},
},
])