diff --git a/.github/workflows/auto-commit-comments.yml b/.github/workflows/auto-commit-comments.yml deleted file mode 100644 index 55c4287a15..0000000000 --- a/.github/workflows/auto-commit-comments.yml +++ /dev/null @@ -1,69 +0,0 @@ -name: Auto Post Commit Message to Coding Work Order - -on: - push: - branches: ['release-v*.*', 'develop-v*.*'] - pull_request: - branches: ['release-v*.*', 'develop-v*.*'] - -jobs: - Check-Commit-Style: - runs-on: ubuntu-latest - outputs: - check-style: ${{ steps.check-style.outputs.error }} - commit-message: ${{ steps.check-style.outputs.commit-message }} - issue-code: ${{ steps.check-style.outputs.issue-code }} - issue-project: ${{ steps.check-style.outputs.issue-project }} - commit-id: ${{ steps.check-style.outputs.commit-id }} - steps: - - name: Checkout Enterprise Branch if PUSH - if: ${{ github.event_name == 'push' }} - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Checkout Enterprise Branch if PULL_REQUEST - if: ${{ github.event_name == 'pull_request' }} - uses: actions/checkout@v3 - with: - ref: ${{ github.head_ref }} - fetch-depth: 0 - - name: Commit Message End With \#$number - id: check-style - run: | - message=`git log -1 --pretty=%B` - echo "commit-message=$message" >>$GITHUB_OUTPUT - commit_id=`git rev-parse HEAD` - echo "commit-id=$commit_id" >>$GITHUB_OUTPUT - echo $message | egrep "#[0-9]+" -o | egrep "[0-9]+" -o > /tmp/commit_msg | cat /tmp/commit_msg | ls - echo $message | egrep "\[[a-zA-Z]+\]" -o | egrep "[a-zA-Z]+" -o > /tmp/project | cat /tmp/project | ls - issue_code=`cat /tmp/commit_msg` - echo "issue-code=$issue_code" >>$GITHUB_OUTPUT - flag=`cat /tmp/commit_msg` - project=`cat /tmp/project` - - - if [[ "X${flag}" != "X" ]]; then isPost='true'; else isPost='false'; fi - if [[ "X${project}" == "X" ]]; then project='tapdata'; fi - - echo "error=$isPost" >>$GITHUB_OUTPUT - echo "issue-project=$project" >>$GITHUB_OUTPUT - - Post-Commit-Message: - runs-on: ubuntu-latest - needs: Check-Commit-Style - if: needs.Check-Commit-Style.outputs.check-style == 'true' - steps: - - name: Post Commit Message to Work Order - run: | - echo "${{ needs.Check-Commit-Style.outputs.check-style }}" - curl \ - -X POST \ - -H "Accept: */*" \ - -H "Authorization: token ${{ secrets.CODING_TOKEN }}" \ - https://tapdata.coding.net/open-api?Action=CreateIssueComment \ - -d '{ - "Action": "CreateIssueComment", - "ProjectName": "${{ needs.Check-Commit-Style.outputs.issue-project }}", - "IssueCode": ${{ needs.Check-Commit-Style.outputs.issue-code }}, - "Content": "'"$GITHUB_ACTOR Commit: [${{ needs.Check-Commit-Style.outputs.commit-message }}]($GITHUB_SERVER_URL/$GITHUB_REPOSITORY/commit/$GITHUB_SHA)"'" - }' diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index b46f5861ee..0000000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,55 +0,0 @@ -name: Trigger Enterprise Build by RestApi - -on: - push: - branches: ['master', 'release-v*.*.*', 'develop-v*.*.0', 'develop-v*.*'] - pull_request: - branches: ['master', 'release-v*.*.*', 'develop-v*.*.0', 'develop-v*.*'] - -jobs: - Trigger: - runs-on: ubuntu-latest - steps: - # Set env - - name: Set Env if Push - if: ${{ github.event_name == 'push' }} - run: | - echo "ENTERPRISE_BRANCH=${{ github.ref_name }}" >> $GITHUB_ENV - echo "OPENSOURCE_BRANCH=${{ github.ref_name }}" >> $GITHUB_ENV - echo "CURRENT_BRANCH=${{ github.ref_name }}" >> $GITHUB_ENV - echo "TAG_BRANCH=${{ github.ref_name }}" >> $GITHUB_ENV - - name: Set Env if Pull Request - if: ${{ github.event_name == 'pull_request' }} - run: | - echo "ENTERPRISE_BRANCH=${{ github.base_ref }}" >> $GITHUB_ENV - echo "OPENSOURCE_BRANCH=${{ github.base_ref }}" >> $GITHUB_ENV - echo "CURRENT_BRANCH=${{ github.ref }}" >> $GITHUB_ENV - echo "TAG_BRANCH=${{ github.base_ref }}" >> $GITHUB_ENV - - - name: Checkout Code to Get Author and Message - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Trigger by RestApi - run: | - author=`git log -1 --pretty=format:'%an'` - message=`git log -1 --pretty=%B` - time=`git log -1 --date=format:"%Y/%m/%d %T" --format="%ad"` - author_email=`git log -1 --format='%ae'` - curl \ - -X POST \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: token ${{ secrets.TAPDATA_ENT_CICD_TOKEN }}" \ - https://api.github.com/repos/tapdata/tapdata-enterprise/dispatches \ - -d '{ - "event_type": "frontend commit trigger", - "client_payload": { - "frontend_branch": "${{ env.CURRENT_BRANCH }}", - "opensource_branch": "${{ env.OPENSOURCE_BRANCH }}", - "current_branch": "${{ env.ENTERPRISE_BRANCH }}", - "commit_author": "'"${author}"'", - "commit_message": "'"${message}"'", - "commit_time": "'"${time}"'", - "commit_author_email": "'"${author_email}"'" - } - }' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000000..906cfafc64 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,82 @@ +name: CI + +on: + pull_request: + branches: ['main', 'develop', 'release-v*.*'] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + changed-files: + name: Get Changed Files + runs-on: ubuntu-latest + outputs: + lint_files: ${{ steps.changed.outputs.lint_files }} + has_lint_files: ${{ steps.changed.outputs.has_lint_files }} + i18n_files: ${{ steps.changed.outputs.i18n_files }} + has_i18n_files: ${{ steps.changed.outputs.has_i18n_files }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Get changed files + id: changed + run: | + FILES=$(git diff --name-only --diff-filter=ACM origin/${{ github.base_ref }}...HEAD) + + # ESLint: 所有 vue/js/ts/tsx/jsx 文件 + LINT_FILES=$(echo "$FILES" | grep -E '\.(vue|js|ts|tsx|jsx)$' || true) + if [ -n "$LINT_FILES" ]; then + echo "has_lint_files=true" >> $GITHUB_OUTPUT + # 转成空格分隔的单行 + echo "lint_files=$(echo "$LINT_FILES" | tr '\n' ' ')" >> $GITHUB_OUTPUT + else + echo "has_lint_files=false" >> $GITHUB_OUTPUT + echo "lint_files=" >> $GITHUB_OUTPUT + fi + + # i18n: 排除 locale 目录的 vue/js/ts/tsx/jsx 文件 + I18N_FILES=$(echo "$LINT_FILES" | grep -v -E '(locale[s]?/|i18n/langs/)' || true) + if [ -n "$I18N_FILES" ]; then + echo "has_i18n_files=true" >> $GITHUB_OUTPUT + echo "i18n_files=$(echo "$I18N_FILES" | tr '\n' ' ')" >> $GITHUB_OUTPUT + else + echo "has_i18n_files=false" >> $GITHUB_OUTPUT + echo "i18n_files=" >> $GITHUB_OUTPUT + fi + + eslint: + name: ESLint + runs-on: ubuntu-latest + needs: changed-files + if: needs.changed-files.outputs.has_lint_files == 'true' + steps: + - uses: actions/checkout@v4 + + - uses: pnpm/action-setup@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: pnpm + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Run ESLint on changed files + run: pnpm eslint --no-warn-ignored --quiet ${{ needs.changed-files.outputs.lint_files }} + + check-i18n: + name: Check i18n + runs-on: ubuntu-latest + needs: changed-files + if: needs.changed-files.outputs.has_i18n_files == 'true' + steps: + - uses: actions/checkout@v4 + + - name: Check for hardcoded Chinese text + run: node scripts/check-i18n.js ${{ needs.changed-files.outputs.i18n_files }} + diff --git a/.github/workflows/mr-ci.yaml b/.github/workflows/mr-ci.yaml deleted file mode 100644 index 5649472d84..0000000000 --- a/.github/workflows/mr-ci.yaml +++ /dev/null @@ -1,176 +0,0 @@ -name: Merge Request CI - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - -on: - push: - branches: [ "main", "develop", "release-v*.*" ] - pull_request: - branches: [ "main", "develop", "release-v*.*" ] - -jobs: - - Get-Branch: - runs-on: ubuntu-latest - outputs: - FRONTEND_BRANCH: ${{ steps.set-outputs.outputs.FRONTEND_BRANCH }} - steps: - - name: Get Enterprise Branch Name -- Common - run: | - echo "FRONTEND_BRANCH=${{ github.ref_name }}" >> $GITHUB_ENV - - name: Get Enterprise Branch Name -- Pull Request - if: ${{ github.event_name == 'pull_request' }} - run: | - echo "FRONTEND_BRANCH=${{ github.event.pull_request.head.ref }}" >> $GITHUB_ENV - - name: Get Enterprise Branch Name -- Schedule - if: ${{ github.event_name == 'schedule' }} - run: | - echo "FRONTEND_BRANCH=develop" >> $GITHUB_ENV - - name: Set Output - id: set-outputs - run: | - echo "::set-output name=FRONTEND_BRANCH::${FRONTEND_BRANCH}" - - Get-Stable-Branch: - needs: - - Get-Branch - uses: tapdata/tapdata-application/.github/workflows/get-stable-branch-and-set-tag.yaml@main - with: - tapdata-frontend-branch: ${{ needs.Get-Branch.outputs.FRONTEND_BRANCH }} - secrets: - TAPDATA_ENT_CICD_TOKEN: ${{ secrets.TAPDATA_ENT_CICD_TOKEN }} - - Sync-Code-to-Office: - uses: tapdata/tapdata-application/.github/workflows/sync-code-to-office.yaml@main - needs: - - Get-Stable-Branch - with: - tapdata: main - tapdata-enterprise: main - tapdata-license: main - tapdata-connectors: main - tapdata-connectors-enterprise: main - tapdata-enterprise-web: ${{ needs.Get-Stable-Branch.outputs.FRONTEND_BRANCH }} - secrets: - TAPDATA_ENT_CICD_TOKEN: ${{ secrets.TAPDATA_ENT_CICD_TOKEN }} - - Scan-Frontend: - runs-on: ubuntu-latest - needs: - - Sync-Code-to-Office - - Get-Stable-Branch - steps: - - name: Scan -- Tapdata-Enterprise - uses: convictional/trigger-workflow-and-wait@v1.6.1 - with: - owner: tapdata - repo: tapdata-application - github_token: ${{ secrets.TAPDATA_ENT_CICD_TOKEN }} - workflow_file_name: sonarqube-scan.yaml - ref: main - wait_interval: 10 - client_payload: '{"tapdata-enterprise-web": "${{ needs.Get-Stable-Branch.outputs.FRONTEND_BRANCH }}"}' - propagate_failure: true - trigger_workflow: true - wait_workflow: true - -# Build-And-Deploy: -# if: ${{ github.event_name == 'schedule' || inputs.mrci_run }} -# runs-on: ubuntu-latest -# needs: -# - Sync-Code-to-Office -# - Get-Stable-Branch -# outputs: -# IP: ${{ steps.get_ip_port.outputs.IP }} -# PORT: ${{ steps.get_ip_port.outputs.PORT }} -# steps: -# - name: Trigger - Build Tapdata -# uses: convictional/trigger-workflow-and-wait@v1.6.1 -# with: -# owner: tapdata -# repo: tapdata-application -# github_token: ${{ secrets.TAPDATA_ENT_CICD_TOKEN }} -# workflow_file_name: build-tapdata-op.yaml -# ref: main -# wait_interval: 10 -# client_payload: '{"FRONTEND_BRANCH": "${{ needs.Get-Stable-Branch.outputs.FRONTEND_BRANCH }}", "TAG_NAME": "${{ needs.Get-Stable-Branch.outputs.TAG_NAME }}"}' -# propagate_failure: true -# trigger_workflow: true -# wait_workflow: true -# - name: Trigger - Deploy Tapdata -# uses: convictional/trigger-workflow-and-wait@v1.6.1 -# with: -# owner: tapdata -# repo: tapdata-application -# github_token: ${{ secrets.TAPDATA_ENT_CICD_TOKEN }} -# workflow_file_name: deploy-tapdata-op.yaml -# ref: main -# wait_interval: 10 -# client_payload: '{"TAG_NAME": "${{ needs.Get-Stable-Branch.outputs.TAG_NAME }}", "AUTO_TEST": true}' -# propagate_failure: true -# trigger_workflow: true -# wait_workflow: true -# - name: Checkout Tapdata Application -# uses: actions/checkout@v2 -# with: -# repository: 'tapdata/tapdata-application' -# ref: "main" -# token: ${{ secrets.TAPDATA_ENT_CICD_TOKEN }} -# path: tapdata-application -# - name: Get IP and Port -# id: get_ip_port -# run: | -# bash tapdata-application/build/upgrade.sh --get-ip-port=true --version=${{ needs.Get-Stable-Branch.outputs.TAG_NAME }} --deploy-way=docker-compose -# IP=$(cat .service_ip_port | awk -F':' '{print $1}') -# PORT=$(cat .service_ip_port | awk -F':' '{print $2}') -# echo "::set-output name=IP::$IP" -# echo "::set-output name=PORT::$PORT" -# -# TestSigma-Test: -# if: ${{ github.event_name == 'schedule' || inputs.mrci_run }} -# runs-on: ubuntu-latest -# needs: -# - Build-And-Deploy -# steps: -# - name: Set Action -# if: ${{ github.event_name == 'workflow_dispatch' }} -# run: | -# echo "Action=workflow_dispatch" >> $GITHUB_ENV -# - name: Set Action -# if: ${{ github.event_name == 'schedule' }} -# run: | -# echo "Action=schedule" >> $GITHUB_ENV -# - name: Trigger - Deploy Tapdata -# uses: convictional/trigger-workflow-and-wait@v1.6.1 -# with: -# owner: tapdata -# repo: tapdata-application -# github_token: ${{ secrets.TAPDATA_ENT_CICD_TOKEN }} -# workflow_file_name: testsigma.yaml -# ref: main -# wait_interval: 10 -# client_payload: '{"IP": "${{ needs.Build-And-Deploy.outputs.IP }}", "PORT": "${{ needs.Build-And-Deploy.outputs.PORT }}", "Action": "${{ env.Action }}"}' -# propagate_failure: true -# trigger_workflow: true -# wait_workflow: true -# -# CLOSE_ENV: -# if: ${{ github.event_name == 'schedule' || failure() || inputs.mrci_run }} -# runs-on: ubuntu-latest -# needs: -# - TestSigma-Test -# - Get-Stable-Branch -# steps: -# - name: Checkout Tapdata Application -# uses: actions/checkout@v2 -# with: -# repository: 'tapdata/tapdata-application' -# ref: "main" -# token: ${{ secrets.TAPDATA_ENT_CICD_TOKEN }} -# path: tapdata-application -# - name: Close Test Env -# id: get_ip_port -# run: | -# bash tapdata-application/build/upgrade.sh --delete-env=${{ needs.Get-Stable-Branch.outputs.TAG_NAME }} --delete-env-tag=true -# diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000000..34ed966f8f --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,2 @@ +pnpm lint-staged + diff --git a/.lintstagedrc.json b/.lintstagedrc.json new file mode 100644 index 0000000000..08676969c8 --- /dev/null +++ b/.lintstagedrc.json @@ -0,0 +1,6 @@ +{ + "*.{vue,js,ts,tsx,jsx}": [ + "node scripts/check-i18n.js", + "eslint --fix --no-warn-ignored" + ] +} diff --git a/eslint.config.js b/eslint.config.js index f1e46b0b0f..63bf9f7b1a 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -19,6 +19,8 @@ export default sxzz( rules: { 'unicorn/filename-case': 'off', '@eslint-community/eslint-comments/no-unlimited-disable': 'off', // 允许 eslint-disable 不指定规则 + 'unused-imports/no-unused-vars': 'warn', + 'vue/no-unused-refs': 'warn', }, }, ], diff --git a/package.json b/package.json index 0d1f52a5fc..b1f03fc11d 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,9 @@ "type-check": "vue-tsc --noEmit", "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix", "format": "prettier --write src/", - "catalog": "pnpx codemod pnpm/catalog" + "catalog": "pnpx codemod pnpm/catalog", + "check-i18n": "node scripts/check-i18n.js", + "prepare": "husky" }, "dependencies": { "element-plus": "catalog:", @@ -47,9 +49,11 @@ "cross-env": "catalog:", "eslint": "catalog:", "file-loader": "catalog:", + "husky": "^9.1.7", "inquirer": "catalog:", "inquirer-autocomplete-prompt": "catalog:", "jsdom": "catalog:", + "lint-staged": "^16.4.0", "npm-run-all2": "catalog:", "prettier": "catalog:", "typescript": "catalog:", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e655593744..5245c6d06d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -357,6 +357,9 @@ importers: file-loader: specifier: 'catalog:' version: 6.2.0(webpack@5.99.9) + husky: + specifier: ^9.1.7 + version: 9.1.7 inquirer: specifier: 'catalog:' version: 9.3.7 @@ -366,6 +369,9 @@ importers: jsdom: specifier: 'catalog:' version: 24.1.3 + lint-staged: + specifier: ^16.4.0 + version: 16.4.0 npm-run-all2: specifier: 'catalog:' version: 6.2.6 @@ -377,7 +383,7 @@ importers: version: 5.8.3 vite: specifier: 'catalog:' - version: 7.1.12(@types/node@22.18.12)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.1) + version: 7.1.12(@types/node@22.18.12)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.3) vue-tsc: specifier: 'catalog:' version: 2.2.10(typescript@5.8.3) @@ -495,13 +501,13 @@ importers: devDependencies: '@cn-xufei/vite-plugin-svg-icons': specifier: 'catalog:' - version: 2.1.0(vite@7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.1)) + version: 2.1.0(vite@7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.3)) '@vitejs/plugin-vue': specifier: 'catalog:' - version: 6.0.2(vite@7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.1))(vue@3.5.25(typescript@5.8.3)) + version: 6.0.2(vite@7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.3))(vue@3.5.25(typescript@5.8.3)) '@vitejs/plugin-vue-jsx': specifier: 'catalog:' - version: 5.1.2(vite@7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.1))(vue@3.5.25(typescript@5.8.3)) + version: 5.1.2(vite@7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.3))(vue@3.5.25(typescript@5.8.3)) chalk: specifier: 'catalog:' version: 5.4.1 @@ -522,7 +528,7 @@ importers: version: 30.0.0(@babel/parser@7.28.5)(vue@3.5.25(typescript@5.8.3)) vite: specifier: 'catalog:' - version: 7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.1) + version: 7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.3) apps/daas: dependencies: @@ -622,16 +628,16 @@ importers: devDependencies: '@cn-xufei/vite-plugin-svg-icons': specifier: 'catalog:' - version: 2.1.0(vite@7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.1)) + version: 2.1.0(vite@7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.3)) '@tap/types': specifier: workspace:* version: link:../../packages/types '@vitejs/plugin-vue': specifier: 'catalog:' - version: 6.0.2(vite@7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.1))(vue@3.5.25(typescript@5.8.3)) + version: 6.0.2(vite@7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.3))(vue@3.5.25(typescript@5.8.3)) '@vitejs/plugin-vue-jsx': specifier: 'catalog:' - version: 5.1.2(vite@7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.1))(vue@3.5.25(typescript@5.8.3)) + version: 5.1.2(vite@7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.3))(vue@3.5.25(typescript@5.8.3)) cross-env: specifier: 'catalog:' version: 7.0.3 @@ -652,7 +658,7 @@ importers: version: 30.0.0(@babel/parser@7.28.5)(vue@3.5.25(typescript@5.8.3)) vite: specifier: 'catalog:' - version: 7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.1) + version: 7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.3) vue-tsc: specifier: 'catalog:' version: 2.2.10(typescript@5.8.3) @@ -664,7 +670,7 @@ importers: version: link:../../packages/types vite: specifier: 'catalog:' - version: 7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.1) + version: 7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.3) packages/api: dependencies: @@ -2906,6 +2912,10 @@ packages: resolution: {integrity: sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==} engines: {node: '>=14.16'} + ansi-escapes@7.3.0: + resolution: {integrity: sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==} + engines: {node: '>=18'} + ansi-regex@2.1.1: resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} engines: {node: '>=0.10.0'} @@ -2914,6 +2924,10 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} + ansi-styles@2.2.1: resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==} engines: {node: '>=0.10.0'} @@ -2926,6 +2940,10 @@ packages: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} + any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} @@ -3144,10 +3162,18 @@ packages: resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} engines: {node: '>=8'} + cli-cursor@5.0.0: + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} + engines: {node: '>=18'} + cli-spinners@2.9.2: resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} engines: {node: '>=6'} + cli-truncate@5.2.0: + resolution: {integrity: sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==} + engines: {node: '>=20'} + cli-width@4.1.0: resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} engines: {node: '>= 12'} @@ -3178,6 +3204,9 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} @@ -3186,6 +3215,10 @@ packages: resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} engines: {node: '>=18'} + commander@14.0.3: + resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==} + engines: {node: '>=20'} + commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} @@ -3535,6 +3568,9 @@ packages: peerDependencies: vue: ^3.2.0 + emoji-regex@10.6.0: + resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -3582,6 +3618,10 @@ packages: resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} engines: {node: '>=0.12'} + environment@1.1.0: + resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} + engines: {node: '>=18'} + es-abstract@1.24.0: resolution: {integrity: sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==} engines: {node: '>= 0.4'} @@ -3869,6 +3909,9 @@ packages: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} + eventemitter3@5.0.4: + resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} + events@3.3.0: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} @@ -4037,6 +4080,10 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} + get-east-asian-width@1.5.0: + resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==} + engines: {node: '>=18'} + get-intrinsic@1.3.0: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} @@ -4200,6 +4247,11 @@ packages: humanize-ms@1.2.1: resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + husky@9.1.7: + resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==} + engines: {node: '>=18'} + hasBin: true + iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} @@ -4335,6 +4387,10 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} + is-fullwidth-code-point@5.1.0: + resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==} + engines: {node: '>=18'} + is-generator-function@1.1.0: resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} engines: {node: '>= 0.4'} @@ -4653,6 +4709,15 @@ packages: linkify-it@5.0.0: resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} + lint-staged@16.4.0: + resolution: {integrity: sha512-lBWt8hujh/Cjysw5GYVmZpFHXDCgZzhrOm8vbcUdobADZNOK/bRshr2kM3DfgrrtR1DQhfupW9gnIXOfiFi+bw==} + engines: {node: '>=20.17'} + hasBin: true + + listr2@9.0.5: + resolution: {integrity: sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==} + engines: {node: '>=20.0.0'} + loader-runner@4.3.1: resolution: {integrity: sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==} engines: {node: '>=6.11.5'} @@ -4693,6 +4758,10 @@ packages: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} engines: {node: '>=10'} + log-update@6.1.0: + resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} + engines: {node: '>=18'} + longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} @@ -4919,6 +4988,10 @@ packages: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + min-indent@1.0.1: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} @@ -5072,6 +5145,10 @@ packages: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} + onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} + open@8.4.2: resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} engines: {node: '>=12'} @@ -5450,6 +5527,10 @@ packages: resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} engines: {node: '>=8'} + restore-cursor@5.1.0: + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} + engines: {node: '>=18'} + ret@0.1.15: resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} engines: {node: '>=0.12'} @@ -5619,6 +5700,18 @@ packages: signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + slice-ansi@7.1.2: + resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==} + engines: {node: '>=18'} + + slice-ansi@8.0.0: + resolution: {integrity: sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==} + engines: {node: '>=20'} + slick@1.12.2: resolution: {integrity: sha512-4qdtOGcBjral6YIBCWJ0ljFSKNLz9KkhbWtuGvUyRowl1kxfuE1x/Z/aJcaiilpb3do9bl5K7/1h9XC5wWpY/A==} @@ -5708,10 +5801,22 @@ packages: resolution: {integrity: sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==} engines: {node: '>=0.10.0'} + string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + + string-width@8.2.0: + resolution: {integrity: sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw==} + engines: {node: '>=20'} + string.prototype.trim@1.2.10: resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} engines: {node: '>= 0.4'} @@ -5738,6 +5843,10 @@ packages: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} + engines: {node: '>=12'} + strip-indent@4.0.0: resolution: {integrity: sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==} engines: {node: '>=12'} @@ -5829,6 +5938,10 @@ packages: tinyexec@1.0.1: resolution: {integrity: sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==} + tinyexec@1.0.4: + resolution: {integrity: sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==} + engines: {node: '>=18'} + tinyglobby@0.2.14: resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} engines: {node: '>=12.0.0'} @@ -6346,6 +6459,10 @@ packages: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} + wrap-ansi@9.0.2: + resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} + engines: {node: '>=18'} + wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -6405,6 +6522,11 @@ packages: engines: {node: '>= 14.6'} hasBin: true + yaml@2.8.3: + resolution: {integrity: sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==} + engines: {node: '>= 14.6'} + hasBin: true + yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} @@ -6613,7 +6735,7 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 - '@cn-xufei/vite-plugin-svg-icons@2.1.0(vite@7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.1))': + '@cn-xufei/vite-plugin-svg-icons@2.1.0(vite@7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.3))': dependencies: cors: 2.8.5 debug: 4.4.1 @@ -6622,7 +6744,7 @@ snapshots: pathe: 0.2.0 svg-baker: 1.7.0 svgo: 3.3.2 - vite: 7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.1) + vite: 7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.3) transitivePeerDependencies: - supports-color @@ -7759,22 +7881,22 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.10.1': optional: true - '@vitejs/plugin-vue-jsx@5.1.2(vite@7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.1))(vue@3.5.25(typescript@5.8.3))': + '@vitejs/plugin-vue-jsx@5.1.2(vite@7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.3))(vue@3.5.25(typescript@5.8.3))': dependencies: '@babel/core': 7.28.5 '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.5) '@babel/plugin-transform-typescript': 7.28.5(@babel/core@7.28.5) '@rolldown/pluginutils': 1.0.0-beta.52 '@vue/babel-plugin-jsx': 2.0.1(@babel/core@7.28.5) - vite: 7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.1) + vite: 7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.3) vue: 3.5.25(typescript@5.8.3) transitivePeerDependencies: - supports-color - '@vitejs/plugin-vue@6.0.2(vite@7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.1))(vue@3.5.25(typescript@5.8.3))': + '@vitejs/plugin-vue@6.0.2(vite@7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.3))(vue@3.5.25(typescript@5.8.3))': dependencies: '@rolldown/pluginutils': 1.0.0-beta.50 - vite: 7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.1) + vite: 7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.3) vue: 3.5.25(typescript@5.8.3) '@volar/language-core@2.4.17': @@ -8179,10 +8301,16 @@ snapshots: ansi-escapes@6.2.1: {} + ansi-escapes@7.3.0: + dependencies: + environment: 1.1.0 + ansi-regex@2.1.1: {} ansi-regex@5.0.1: {} + ansi-regex@6.2.2: {} + ansi-styles@2.2.1: {} ansi-styles@4.3.0: @@ -8191,6 +8319,8 @@ snapshots: ansi-styles@6.2.1: {} + ansi-styles@6.2.3: {} + any-promise@1.3.0: {} are-docs-informative@0.0.2: {} @@ -8439,8 +8569,17 @@ snapshots: dependencies: restore-cursor: 3.1.0 + cli-cursor@5.0.0: + dependencies: + restore-cursor: 5.1.0 + cli-spinners@2.9.2: {} + cli-truncate@5.2.0: + dependencies: + slice-ansi: 8.0.0 + string-width: 8.2.0 + cli-width@4.1.0: {} clipboard@2.0.11: @@ -8470,12 +8609,16 @@ snapshots: color-name@1.1.4: {} + colorette@2.0.20: {} + combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 commander@12.1.0: {} + commander@14.0.3: {} + commander@2.20.3: {} commander@7.2.0: {} @@ -8836,6 +8979,8 @@ snapshots: transitivePeerDependencies: - '@vue/composition-api' + emoji-regex@10.6.0: {} + emoji-regex@8.0.0: {} emojis-list@3.0.0: {} @@ -8873,6 +9018,8 @@ snapshots: entities@6.0.1: {} + environment@1.1.0: {} + es-abstract@1.24.0: dependencies: array-buffer-byte-length: 1.0.2 @@ -9296,6 +9443,8 @@ snapshots: etag@1.8.1: {} + eventemitter3@5.0.4: {} + events@3.3.0: {} expand-brackets@2.1.4: @@ -9366,9 +9515,9 @@ snapshots: dependencies: format: 0.2.2 - fdir@6.4.6(picomatch@4.0.2): + fdir@6.4.6(picomatch@4.0.3): optionalDependencies: - picomatch: 4.0.2 + picomatch: 4.0.3 fdir@6.5.0(picomatch@4.0.3): optionalDependencies: @@ -9471,6 +9620,8 @@ snapshots: get-caller-file@2.0.5: {} + get-east-asian-width@1.5.0: {} + get-intrinsic@1.3.0: dependencies: call-bind-apply-helpers: 1.0.2 @@ -9644,6 +9795,8 @@ snapshots: dependencies: ms: 2.1.3 + husky@9.1.7: {} + iconv-lite@0.4.24: dependencies: safer-buffer: 2.1.2 @@ -9781,6 +9934,10 @@ snapshots: is-fullwidth-code-point@3.0.0: {} + is-fullwidth-code-point@5.1.0: + dependencies: + get-east-asian-width: 1.5.0 + is-generator-function@1.1.0: dependencies: call-bound: 1.0.4 @@ -10065,6 +10222,24 @@ snapshots: dependencies: uc.micro: 2.1.0 + lint-staged@16.4.0: + dependencies: + commander: 14.0.3 + listr2: 9.0.5 + picomatch: 4.0.3 + string-argv: 0.3.2 + tinyexec: 1.0.4 + yaml: 2.8.3 + + listr2@9.0.5: + dependencies: + cli-truncate: 5.2.0 + colorette: 2.0.20 + eventemitter3: 5.0.4 + log-update: 6.1.0 + rfdc: 1.4.1 + wrap-ansi: 9.0.2 + loader-runner@4.3.1: {} loader-utils@1.4.2: @@ -10106,6 +10281,14 @@ snapshots: chalk: 4.1.2 is-unicode-supported: 0.1.0 + log-update@6.1.0: + dependencies: + ansi-escapes: 7.3.0 + cli-cursor: 5.0.0 + slice-ansi: 7.1.2 + strip-ansi: 7.2.0 + wrap-ansi: 9.0.2 + longest-streak@3.1.0: {} lower-case@2.0.2: @@ -10519,6 +10702,8 @@ snapshots: mimic-fn@2.1.0: {} + mimic-function@5.0.1: {} + min-indent@1.0.1: {} minimatch@10.0.3: @@ -10678,6 +10863,10 @@ snapshots: dependencies: mimic-fn: 2.1.0 + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 + open@8.4.2: dependencies: define-lazy-prop: 2.0.0 @@ -11122,6 +11311,11 @@ snapshots: onetime: 5.1.2 signal-exit: 3.0.7 + restore-cursor@5.1.0: + dependencies: + onetime: 7.0.0 + signal-exit: 4.1.0 + ret@0.1.15: {} reusify@1.1.0: {} @@ -11324,6 +11518,18 @@ snapshots: signal-exit@3.0.7: {} + signal-exit@4.1.0: {} + + slice-ansi@7.1.2: + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 5.1.0 + + slice-ansi@8.0.0: + dependencies: + ansi-styles: 6.2.3 + is-fullwidth-code-point: 5.1.0 + slick@1.12.2: {} snapdragon-node@2.1.1: @@ -11415,12 +11621,25 @@ snapshots: strict-uri-encode@1.1.0: {} + string-argv@0.3.2: {} + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 + string-width@7.2.0: + dependencies: + emoji-regex: 10.6.0 + get-east-asian-width: 1.5.0 + strip-ansi: 7.2.0 + + string-width@8.2.0: + dependencies: + get-east-asian-width: 1.5.0 + strip-ansi: 7.2.0 + string.prototype.trim@1.2.10: dependencies: call-bind: 1.0.8 @@ -11460,6 +11679,10 @@ snapshots: dependencies: ansi-regex: 5.0.1 + strip-ansi@7.2.0: + dependencies: + ansi-regex: 6.2.2 + strip-indent@4.0.0: dependencies: min-indent: 1.0.1 @@ -11555,10 +11778,12 @@ snapshots: tinyexec@1.0.1: {} + tinyexec@1.0.4: {} + tinyglobby@0.2.14: dependencies: - fdir: 6.4.6(picomatch@4.0.2) - picomatch: 4.0.2 + fdir: 6.4.6(picomatch@4.0.3) + picomatch: 4.0.3 tinyglobby@0.2.15: dependencies: @@ -11618,7 +11843,7 @@ snapshots: ts-declaration-location@1.0.7(typescript@5.8.3): dependencies: - picomatch: 4.0.2 + picomatch: 4.0.3 typescript: 5.8.3 tslib@2.3.0: {} @@ -11896,7 +12121,7 @@ snapshots: vary@1.1.2: {} - vite@7.1.12(@types/node@22.18.12)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.1): + vite@7.1.12(@types/node@22.18.12)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.3): dependencies: esbuild: 0.25.5 fdir: 6.5.0(picomatch@4.0.3) @@ -11910,9 +12135,9 @@ snapshots: lightningcss: 1.30.2 sass: 1.89.2 terser: 5.46.1 - yaml: 2.8.1 + yaml: 2.8.3 - vite@7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.1): + vite@7.1.12(@types/node@25.5.0)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.46.1)(yaml@2.8.3): dependencies: esbuild: 0.25.5 fdir: 6.5.0(picomatch@4.0.3) @@ -11926,7 +12151,7 @@ snapshots: lightningcss: 1.30.2 sass: 1.89.2 terser: 5.46.1 - yaml: 2.8.1 + yaml: 2.8.3 vscode-uri@3.1.0: {} @@ -12166,6 +12391,12 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 + wrap-ansi@9.0.2: + dependencies: + ansi-styles: 6.2.1 + string-width: 7.2.0 + strip-ansi: 7.2.0 + wrappy@1.0.2: {} ws@8.18.3: {} @@ -12198,6 +12429,8 @@ snapshots: yaml@2.8.1: {} + yaml@2.8.3: {} + yargs-parser@21.1.1: {} yargs@17.7.2: diff --git a/scripts/check-i18n.js b/scripts/check-i18n.js new file mode 100644 index 0000000000..c512011fec --- /dev/null +++ b/scripts/check-i18n.js @@ -0,0 +1,255 @@ +#!/usr/bin/env node + +/** + * 检测文件中未国际化的中文硬编码 + * + * 用法: + * node scripts/check-i18n.js [文件...] # 检查指定文件(lint-staged 模式) + * node scripts/check-i18n.js --all # 全量扫描(CI 模式) + */ + +import { execSync } from 'node:child_process' +import fs from 'node:fs' +import path from 'node:path' +import process from 'node:process' + +// 中文字符正则(CJK 统一汉字) +const CHINESE_RE = /[\u4E00-\u9FFF]/ + +// 需要排除的目录/文件模式 +const EXCLUDE_PATTERNS = [ + /[\\/]locales?[\\/]/, + /[\\/]node_modules[\\/]/, + /[\\/]dist[\\/]/, + /\.test\.[jt]sx?$/, + /\.spec\.[jt]sx?$/, + /\.d\.ts$/, + /[\\/]i18n[\\/]langs[\\/]/, +] + +// 需要检查的文件扩展名 +const CHECK_EXTENSIONS = ['.vue', '.js', '.ts', '.tsx', '.jsx'] + +// 行级别排除规则 —— 命中则跳过该行 +const LINE_SKIP_PATTERNS = [ + /^\s*\/\//, // 单行注释 + /^\s*\*/, // 块注释中间行 + /^\s*\/\*.*\*\/\s*$/, // 单行块注释 + /^\s*\s*$/, // HTML 注释 + /^\s*