From 7c2c68f3a6570eaa8132abae7f8f4d26ea4136dc Mon Sep 17 00:00:00 2001 From: Tw93 Date: Tue, 5 Aug 2025 19:53:58 +0800 Subject: [PATCH] :wrench: Global formatting and update formatting --- .ecrc.json | 3 - .gitattributes | 2 +- .github/FUNDING.yml | 4 +- .github/ISSUE_TEMPLATE/bug-report.yml | 6 +- .github/ISSUE_TEMPLATE/feature.yml | 4 +- .github/workflows/code-quality.yml | 77 ++++ .github/workflows/docker-publish.yml | 2 +- .github/workflows/editorconfig-check.yml | 23 -- .github/workflows/pake-cli.yaml | 40 +-- .github/workflows/pake_build_next.yaml | 2 +- .github/workflows/pake_build_single_app.yaml | 36 +- .github/workflows/rust-code-quality-check.yml | 83 ----- .prettierignore | 20 ++ .prettierrc.json | 15 - CLAUDE.md | 16 +- CODE_OF_CONDUCT.md | 14 +- README.md | 4 +- README_CN.md | 4 +- README_JP.md | 4 +- bin/README.md | 7 +- bin/README_CN.md | 5 +- bin/builders/BaseBuilder.ts | 21 +- bin/builders/BuilderProvider.ts | 5 +- bin/builders/MacBuilder.ts | 4 +- bin/cli.ts | 125 +++++-- bin/defaults.ts | 2 +- bin/dev.ts | 5 +- bin/helpers/merge.ts | 50 ++- bin/helpers/rust.ts | 4 +- bin/helpers/updater.ts | 4 +- bin/options/icon.ts | 17 +- bin/options/index.ts | 8 +- bin/options/logger.ts | 8 +- bin/utils/combine.ts | 8 +- bin/utils/info.ts | 11 +- bin/utils/ip.ts | 4 +- bin/utils/shell.ts | 6 +- dist/cli.js | 332 +++++++++--------- package.json | 1 + rollup.config.js | 56 +-- script/app_config.mjs | 94 +++-- script/build_with_pake_cli.js | 121 ++++--- src-tauri/src/inject/component.js | 11 +- src-tauri/src/inject/event.js | 174 +++++---- src-tauri/src/inject/style.js | 14 +- src-tauri/tauri.linux.conf.json | 4 +- tsconfig.json | 17 +- 47 files changed, 824 insertions(+), 653 deletions(-) delete mode 100644 .ecrc.json create mode 100644 .github/workflows/code-quality.yml delete mode 100644 .github/workflows/editorconfig-check.yml delete mode 100644 .github/workflows/rust-code-quality-check.yml delete mode 100644 .prettierrc.json diff --git a/.ecrc.json b/.ecrc.json deleted file mode 100644 index 4da6169..0000000 --- a/.ecrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "Exclude": ["Cargo\\.lock$", "dist", "*\\.md"] -} diff --git a/.gitattributes b/.gitattributes index ec23583..a69c2ed 100644 --- a/.gitattributes +++ b/.gitattributes @@ -8,4 +8,4 @@ script/* linguist-vendored /icns2png.py linguist-vendored /rollup.config.js linguist-vendored src-tauri/src/inject/* linguist-vendored -src-tauri/src/.pake/* linguist-vendored \ No newline at end of file +src-tauri/src/.pake/* linguist-vendored diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 959808e..e7dad43 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,2 +1,2 @@ -github: ['tw93'] -custom: ['https://miaoyan.app/cats.html?name=Pake'] +github: ["tw93"] +custom: ["https://miaoyan.app/cats.html?name=Pake"] diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index c95bcac..0826f8f 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -1,7 +1,7 @@ name: Bug report description: Problems with the software -title: '[Bug] ' -labels: ['bug'] +title: "[Bug] " +labels: ["bug"] body: - type: markdown attributes: @@ -73,4 +73,4 @@ body: - label: I'm willing to submit a PR! - type: markdown attributes: - value: 'Thanks for completing our form!' + value: "Thanks for completing our form!" diff --git a/.github/ISSUE_TEMPLATE/feature.yml b/.github/ISSUE_TEMPLATE/feature.yml index a9adb44..00759ca 100644 --- a/.github/ISSUE_TEMPLATE/feature.yml +++ b/.github/ISSUE_TEMPLATE/feature.yml @@ -1,6 +1,6 @@ name: Feature description: Add new feature, improve code, and more -labels: ['enhancement'] +labels: ["enhancement"] body: - type: markdown attributes: @@ -43,4 +43,4 @@ body: - label: I'm willing to submit a PR! - type: markdown attributes: - value: 'Thanks for completing our form!' + value: "Thanks for completing our form!" diff --git a/.github/workflows/code-quality.yml b/.github/workflows/code-quality.yml new file mode 100644 index 0000000..a34f3fe --- /dev/null +++ b/.github/workflows/code-quality.yml @@ -0,0 +1,77 @@ +name: Code Quality Check + +on: + push: + pull_request: + workflow_dispatch: + +permissions: + actions: write + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + formatting: + name: Code Formatting Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "20" + cache: "npm" + + - name: Install dependencies + run: npm ci + + - name: Check EditorConfig compliance + uses: editorconfig-checker/action-editorconfig-checker@main + + - name: Run EditorConfig checker with exclusions + run: editorconfig-checker -exclude 'Cargo\.lock|dist/.*|.*\.(md|icns|ico|png|jpg|jpeg|gif|svg|desktop|wxs|plist|toml)$|cli\.js$|node_modules/.*|target/.*|src-tauri/(target|icons|png)/.*' + + - name: Check Prettier formatting + run: npx prettier --check . --ignore-unknown + + rust-quality: + name: Rust Code Quality + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + fail-fast: false + defaults: + run: + shell: bash + working-directory: src-tauri + steps: + - uses: actions/checkout@v4 + + - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + components: rustfmt, clippy + + - uses: rui314/setup-mold@v1 + if: matrix.os == 'ubuntu-latest' + + - uses: taiki-e/install-action@v1 + with: + tool: cargo-hack + + - name: Install Ubuntu dependencies + if: matrix.os == 'ubuntu-latest' + uses: awalsh128/cache-apt-pkgs-action@v1.4.3 + with: + packages: libdbus-1-dev libsoup3.0-dev libjavascriptcoregtk-4.1-dev libwebkit2gtk-4.1-dev build-essential curl wget file libxdo-dev libssl-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev gnome-video-effects gnome-video-effects-extra + version: 1.0 + + - name: Check Rust formatting + run: cargo fmt --all -- --color=always --check + + - name: Run Clippy lints + run: cargo hack --feature-powerset --exclude-features cli-build --no-dev-deps clippy diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 83b408f..23c8c2e 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -1,7 +1,7 @@ name: Build and Publish Docker Image on: - workflow_dispatch: # Manual + workflow_dispatch: # Manual env: REGISTRY: ghcr.io diff --git a/.github/workflows/editorconfig-check.yml b/.github/workflows/editorconfig-check.yml deleted file mode 100644 index 78c818b..0000000 --- a/.github/workflows/editorconfig-check.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Check EditorConfig - -on: - push: - pull_request: - workflow_dispatch: - -permissions: - actions: write - contents: read - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - editorconfig-check: - name: Run EditorConfig Check - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: editorconfig-checker/action-editorconfig-checker@main - - run: editorconfig-checker -config .ecrc.json diff --git a/.github/workflows/pake-cli.yaml b/.github/workflows/pake-cli.yaml index c81fb3e..9312e83 100644 --- a/.github/workflows/pake-cli.yaml +++ b/.github/workflows/pake-cli.yaml @@ -3,55 +3,55 @@ on: workflow_dispatch: inputs: platform: - description: 'Platform' + description: "Platform" required: true - default: 'macos-latest' + default: "macos-latest" type: choice options: - - 'windows-latest' - - 'macos-latest' - - 'ubuntu-24.04' + - "windows-latest" + - "macos-latest" + - "ubuntu-24.04" url: - description: 'URL' + description: "URL" required: true name: - description: 'Name, English, Linux no capital' + description: "Name, English, Linux no capital" required: true icon: - description: 'Icon, Image URL, Optional' + description: "Icon, Image URL, Optional" required: false width: - description: 'Width, Optional' + description: "Width, Optional" required: false - default: '1200' + default: "1200" height: - description: 'Height, Optional' + description: "Height, Optional" required: false - default: '780' + default: "780" fullscreen: - description: 'Fullscreen, At startup, Optional' + description: "Fullscreen, At startup, Optional" required: false type: boolean default: false hide_title_bar: - description: 'Hide TitleBar, MacOS only, Optional' + description: "Hide TitleBar, MacOS only, Optional" required: false type: boolean default: false multi_arch: - description: 'MultiArch, MacOS only, Optional' + description: "MultiArch, MacOS only, Optional" required: false type: boolean default: false targets: - description: 'Targets, Linux only, Optional' + description: "Targets, Linux only, Optional" required: false - default: 'deb' + default: "deb" type: choice options: - - 'deb' - - 'appimage' - - 'rpm' + - "deb" + - "appimage" + - "rpm" jobs: build: diff --git a/.github/workflows/pake_build_next.yaml b/.github/workflows/pake_build_next.yaml index 778f4a5..d8afcf7 100644 --- a/.github/workflows/pake_build_next.yaml +++ b/.github/workflows/pake_build_next.yaml @@ -2,7 +2,7 @@ name: Build All Popular Apps on: push: tags: - - 'V*' + - "V*" jobs: read_apps_config: diff --git a/.github/workflows/pake_build_single_app.yaml b/.github/workflows/pake_build_single_app.yaml index 793e9c0..5d39a28 100644 --- a/.github/workflows/pake_build_single_app.yaml +++ b/.github/workflows/pake_build_single_app.yaml @@ -3,43 +3,43 @@ on: workflow_dispatch: inputs: name: - description: 'App Name' + description: "App Name" required: true - default: 'twitter' + default: "twitter" title: - description: 'App Title' + description: "App Title" required: true - default: 'Twitter' + default: "Twitter" name_zh: - description: 'App Name in Chinese' + description: "App Name in Chinese" required: true - default: '推特' + default: "推特" url: - description: 'App URL' + description: "App URL" required: true - default: 'https://twitter.com/' + default: "https://twitter.com/" workflow_call: inputs: name: - description: 'App Name' + description: "App Name" type: string required: true - default: 'twitter' + default: "twitter" title: - description: 'App Title' + description: "App Title" required: true type: string - default: 'Twitter' + default: "Twitter" name_zh: - description: 'App Name in Chinese' + description: "App Name in Chinese" required: true type: string - default: '推特' + default: "推特" url: - description: 'App URL' + description: "App URL" required: true type: string - default: 'https://twitter.com/' + default: "https://twitter.com/" jobs: build_single_app: @@ -144,7 +144,7 @@ jobs: uses: actions/upload-artifact@v4 if: startsWith(github.ref, 'refs/tags/') != true with: - path: 'output/*/*.*' + path: "output/*/*.*" - name: Upload For Release # arg info: https://github.com/ncipollo/release-action#release-action @@ -152,5 +152,5 @@ jobs: if: startsWith(github.ref, 'refs/tags/') == true with: allowUpdates: true - artifacts: 'output/*/*.*' + artifacts: "output/*/*.*" token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/rust-code-quality-check.yml b/.github/workflows/rust-code-quality-check.yml deleted file mode 100644 index b2453f4..0000000 --- a/.github/workflows/rust-code-quality-check.yml +++ /dev/null @@ -1,83 +0,0 @@ -name: Check Rust Code - -on: - push: - pull_request: - workflow_dispatch: - -permissions: - actions: write - contents: read - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -defaults: - run: - shell: bash - working-directory: src-tauri - -jobs: - cargo-test: - name: Test codebase on ${{ matrix.os }} (cargo test) - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: - - windows-latest - - ubuntu-latest - - macos-latest - fail-fast: false - steps: - - uses: actions/checkout@v4 - - uses: actions-rust-lang/setup-rust-toolchain@v1 - - uses: rui314/setup-mold@v1 - - uses: taiki-e/install-action@v1 - with: - tool: cargo-hack,nextest - - name: Install dependencies for Ubuntu - if: matrix.os == 'ubuntu-latest' - uses: awalsh128/cache-apt-pkgs-action@v1.4.3 - with: - packages: libdbus-1-dev libsoup3.0-dev libjavascriptcoregtk-4.1-dev libwebkit2gtk-4.1-dev build-essential curl wget file libxdo-dev libssl-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev gnome-video-effects gnome-video-effects-extra - version: 1.0 - - name: Run unit & integration tests with nextest - run: cargo hack --feature-powerset --exclude-features cli-build nextest run --no-tests=pass - - cargo-clippy: - name: Check codebase quality (cargo clippy) - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: - - windows-latest - - ubuntu-latest - - macos-latest - fail-fast: false - steps: - - uses: actions/checkout@v4 - - uses: actions-rust-lang/setup-rust-toolchain@v1 - with: - components: clippy - - uses: taiki-e/install-action@cargo-hack - - name: Install dependencies for Ubuntu - if: matrix.os == 'ubuntu-latest' - uses: awalsh128/cache-apt-pkgs-action@v1.4.3 - with: - packages: libdbus-1-dev libsoup3.0-dev libjavascriptcoregtk-4.1-dev libwebkit2gtk-4.1-dev build-essential curl wget libssl-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev gnome-video-effects gnome-video-effects-extra - version: 1.0 - - name: Run all-features code quality checks - run: cargo hack --feature-powerset --exclude-features cli-build --no-dev-deps clippy - - name: Run normal code quality check - run: cargo clippy - - cargo-fmt: - name: Enforce codebase style (cargo fmt) - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions-rust-lang/setup-rust-toolchain@v1 - with: - components: rustfmt - - run: cargo fmt --all -- --color=always --check diff --git a/.prettierignore b/.prettierignore index e029b86..bdf9c58 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,3 +1,23 @@ src-tauri/target node_modules dist/**/* +*.ico +*.icns +*.png +*.jpg +*.jpeg +*.gif +*.svg +*.bin +*.exe +*.dll +*.so +*.dylib +Cargo.lock +src-tauri/Cargo.lock +pnpm-lock.yaml +cli.js +*.desktop +*.wxs +*.plist +*.toml diff --git a/.prettierrc.json b/.prettierrc.json deleted file mode 100644 index f4af6f9..0000000 --- a/.prettierrc.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "arrowParens": "avoid", - "bracketSpacing": true, - "endOfLine": "lf", - "bracketSameLine": false, - "jsxSingleQuote": false, - "printWidth": 140, - "proseWrap": "preserve", - "quoteProps": "as-needed", - "semi": true, - "singleQuote": true, - "tabWidth": 2, - "trailingComma": "all", - "useTabs": false -} diff --git a/CLAUDE.md b/CLAUDE.md index 4899cf6..639c445 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -70,17 +70,17 @@ npm run analyze 1. **CLI Tool** (`bin/`): Node.js/TypeScript-based command-line interface - - `bin/cli.ts` - Main CLI entry point with Commander.js - - `bin/builders/` - Platform-specific builders (Mac, Windows, Linux) - - `bin/options/` - CLI option processing and validation - - `bin/utils/` - Utility functions for URL validation, platform detection +- `bin/cli.ts` - Main CLI entry point with Commander.js +- `bin/builders/` - Platform-specific builders (Mac, Windows, Linux) +- `bin/options/` - CLI option processing and validation +- `bin/utils/` - Utility functions for URL validation, platform detection 2. **Tauri Application** (`src-tauri/`): Rust-based desktop app framework - - `src-tauri/src/lib.rs` - Main application entry point - - `src-tauri/src/app/` - Application modules (config, window, system tray, shortcuts) - - `src-tauri/src/inject/` - JavaScript/CSS injection for web pages - - `src-tauri/pake.json` - Default app configuration +- `src-tauri/src/lib.rs` - Main application entry point +- `src-tauri/src/app/` - Application modules (config, window, system tray, shortcuts) +- `src-tauri/src/inject/` - JavaScript/CSS injection for web pages +- `src-tauri/pake.json` - Default app configuration 3. **Build System**: Uses Rollup for CLI bundling and Tauri for app packaging diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index a771bbb..6590101 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -20,21 +20,17 @@ community include: - Demonstrating empathy and kindness toward other people - Being respectful of differing opinions, viewpoints, and experiences - Giving and gracefully accepting constructive feedback -- Accepting responsibility and apologizing to those affected by our mistakes, - and learning from the experience -- Focusing on what is best not just for us as individuals, but for the - overall community +- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience +- Focusing on what is best not just for us as individuals, but for the overall community Examples of unacceptable behavior include: -- The use of erotic language or imagery, and sexual attention or - advances of any kind +- The use of erotic language or imagery, and sexual attention or advances of any kind - Trolling, insulting or derogatory comments, and personal or political attacks - Public or private harassment - Publishing others' private information, such as a physical or email - address, without their explicit permission -- Other conduct which could reasonably be considered inappropriate in a - professional setting + address, without their explicit permission +- Other conduct which could reasonably be considered inappropriate in a professional setting ## Enforcement Responsibilities diff --git a/README.md b/README.md index 9f6fae5..322b31e 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ - + Grok Mac Windows @@ -112,7 +112,7 @@ - Excalidraw + Excalidraw Mac Windows Linux diff --git a/README_CN.md b/README_CN.md index d43ac24..bdff4fc 100644 --- a/README_CN.md +++ b/README_CN.md @@ -46,7 +46,7 @@ - + Grok Mac Windows @@ -111,7 +111,7 @@ - Excalidraw + Excalidraw Mac Windows Linux diff --git a/README_JP.md b/README_JP.md index 2d226e8..533872e 100644 --- a/README_JP.md +++ b/README_JP.md @@ -47,7 +47,7 @@ - + Grok Mac Windows @@ -112,7 +112,7 @@ - Excalidraw + Excalidraw Mac Windows Linux diff --git a/bin/README.md b/bin/README.md index 1da7520..6483bfa 100644 --- a/bin/README.md +++ b/bin/README.md @@ -13,7 +13,6 @@ npm install pake-cli -g - **CRITICAL**: Consult [Tauri prerequisites](https://tauri.app/start/prerequisites/) before proceeding. - For Windows users (ensure that `Win10 SDK (10.0.19041.0)` and `Visual Studio build tool 2022 (>=17.2)` are installed), additional installations are required: - 1. Microsoft Visual C++ 2015-2022 Redistributable (x64) 2. Microsoft Visual C++ 2015-2022 Redistributable (x86) 3. Microsoft Visual C++ 2012 Redistributable (x86) (optional) @@ -251,7 +250,7 @@ Supports both comma-separated and multiple option formats: # Comma-separated (recommended) --inject ./tools/style.css,./tools/hotkey.js -# Multiple options +# Multiple options --inject ./tools/style.css --inject ./tools/hotkey.js # Single file @@ -285,8 +284,8 @@ The `DEFAULT_DEV_PAKE_OPTIONS` configuration in `bin/defaults.ts` can be modifie ```typescript export const DEFAULT_DEV_PAKE_OPTIONS: PakeCliOptions & { url: string } = { ...DEFAULT_PAKE_OPTIONS, - url: 'https://weread.qq.com', - name: 'Weread', + url: "https://weread.qq.com", + name: "Weread", }; ``` diff --git a/bin/README_CN.md b/bin/README_CN.md index a8b9ed2..47286f1 100644 --- a/bin/README_CN.md +++ b/bin/README_CN.md @@ -13,7 +13,6 @@ npm install pake-cli -g - **非常重要**:请参阅 Tauri 的 [依赖项指南](https://tauri.app/start/prerequisites/)。 - 对于 Windows 用户,请确保至少安装了 `Win10 SDK(10.0.19041.0)` 和 `Visual Studio Build Tools 2022(版本 17.2 或更高)`,此外还需要安装以下组件: - 1. Microsoft Visual C++ 2015-2022 Redistributable (x64) 2. Microsoft Visual C++ 2015-2022 Redistributable (x86) 3. Microsoft Visual C++ 2012 Redistributable (x86)(可选) @@ -287,8 +286,8 @@ pake [url] [options] ```typescript export const DEFAULT_DEV_PAKE_OPTIONS: PakeCliOptions & { url: string } = { ...DEFAULT_PAKE_OPTIONS, - url: 'https://weread.qq.com', - name: 'Weread', + url: "https://weread.qq.com", + name: "Weread", }; ``` diff --git a/bin/builders/BaseBuilder.ts b/bin/builders/BaseBuilder.ts index f318e36..a6a1666 100644 --- a/bin/builders/BaseBuilder.ts +++ b/bin/builders/BaseBuilder.ts @@ -56,13 +56,17 @@ export default abstract class BaseBuilder { logger.info('✺ Located in China, using npm/rsProxy CN mirror.'); const projectCnConf = path.join(tauriSrcPath, 'rust_proxy.toml'); await fsExtra.copy(projectCnConf, projectConf); - await shellExec(`cd "${npmDirectory}" && npm install --registry=https://registry.npmmirror.com`); + await shellExec( + `cd "${npmDirectory}" && npm install --registry=https://registry.npmmirror.com`, + ); } else { await shellExec(`cd "${npmDirectory}" && npm install`); } spinner.succeed(chalk.green('Package installed!')); if (!tauriTargetPathExists) { - logger.warn('✼ The first packaging may be slow, please be patient and wait, it will be faster afterwards.'); + logger.warn( + '✼ The first packaging may be slow, please be patient and wait, it will be faster afterwards.', + ); } } @@ -110,7 +114,16 @@ export default abstract class BaseBuilder { return `src-tauri/target/${basePath}/bundle/`; } - protected getBuildAppPath(npmDirectory: string, fileName: string, fileType: string): string { - return path.join(npmDirectory, this.getBasePath(), fileType.toLowerCase(), `${fileName}.${fileType}`); + protected getBuildAppPath( + npmDirectory: string, + fileName: string, + fileType: string, + ): string { + return path.join( + npmDirectory, + this.getBasePath(), + fileType.toLowerCase(), + `${fileName}.${fileType}`, + ); } } diff --git a/bin/builders/BuilderProvider.ts b/bin/builders/BuilderProvider.ts index 392c54d..e05ee7f 100644 --- a/bin/builders/BuilderProvider.ts +++ b/bin/builders/BuilderProvider.ts @@ -6,7 +6,10 @@ import { PakeAppOptions } from '@/types'; const { platform } = process; -const buildersMap: Record BaseBuilder> = { +const buildersMap: Record< + string, + new (options: PakeAppOptions) => BaseBuilder +> = { darwin: MacBuilder, win32: WinBuilder, linux: LinuxBuilder, diff --git a/bin/builders/MacBuilder.ts b/bin/builders/MacBuilder.ts index f52d16b..93b49fa 100644 --- a/bin/builders/MacBuilder.ts +++ b/bin/builders/MacBuilder.ts @@ -20,7 +20,9 @@ export default class MacBuilder extends BaseBuilder { } protected getBuildCommand(): string { - return this.options.multiArch ? 'npm run build:mac' : super.getBuildCommand(); + return this.options.multiArch + ? 'npm run build:mac' + : super.getBuildCommand(); } protected getBasePath(): string { diff --git a/bin/cli.ts b/bin/cli.ts index 07b1421..cf22877 100644 --- a/bin/cli.ts +++ b/bin/cli.ts @@ -3,7 +3,10 @@ import { program, Option } from 'commander'; import log from 'loglevel'; import packageJson from '../package.json'; import BuilderProvider from './builders/BuilderProvider'; -import { DEFAULT_PAKE_OPTIONS as DEFAULT, DEFAULT_PAKE_OPTIONS } from './defaults'; +import { + DEFAULT_PAKE_OPTIONS as DEFAULT, + DEFAULT_PAKE_OPTIONS, +} from './defaults'; import { checkUpdateTips } from './helpers/updater'; import handleInputOptions from './options/index'; @@ -18,7 +21,10 @@ ${green('| __/ (_| | < __/')} ${yellow('https://github.com/tw93/pake')} ${green('|_| \\__,_|_|\\_\\___| can turn any webpage into a desktop app with Rust.')} `; -program.addHelpText('beforeAll', logo).usage(`[url] [options]`).showHelpAfterError(); +program + .addHelpText('beforeAll', logo) + .usage(`[url] [options]`) + .showHelpAfterError(); program .argument('[url]', 'The web URL you want to package', validateUrlInput) @@ -26,15 +32,26 @@ program // If the platform is Linux, use `-` as the connector, and convert all characters to lowercase. // For example, Google Translate will become google-translate. .option('--name ', 'Application name', (value, previous) => { - const platform = process.platform - const connector = platform === 'linux' ? '-' : ' ' - const name = previous === undefined ? value : `${previous}${connector}${value}` - - return platform === 'linux' ? name.toLowerCase() : name + const platform = process.platform; + const connector = platform === 'linux' ? '-' : ' '; + const name = + previous === undefined ? value : `${previous}${connector}${value}`; + + return platform === 'linux' ? name.toLowerCase() : name; }) .option('--icon ', 'Application icon', DEFAULT.icon) - .option('--width ', 'Window width', validateNumberInput, DEFAULT.width) - .option('--height ', 'Window height', validateNumberInput, DEFAULT.height) + .option( + '--width ', + 'Window width', + validateNumberInput, + DEFAULT.width, + ) + .option( + '--height ', + 'Window height', + validateNumberInput, + DEFAULT.height, + ) .option('--use-local-file', 'Use local file packaging', DEFAULT.useLocalFile) .option('--fullscreen', 'Start in full screen', DEFAULT.fullscreen) .option('--hide-title-bar', 'For Mac, hide title bar', DEFAULT.hideTitleBar) @@ -44,41 +61,93 @@ program 'Injection of .js or .css files', (val, previous) => { if (!val) return DEFAULT.inject; - + // Split by comma and trim whitespace, filter out empty strings - const files = val.split(',') - .map(item => item.trim()) - .filter(item => item.length > 0); - + const files = val + .split(',') + .map((item) => item.trim()) + .filter((item) => item.length > 0); + // If previous values exist (from multiple --inject options), merge them return previous ? [...previous, ...files] : files; }, DEFAULT.inject, ) .option('--debug', 'Debug build and more output', DEFAULT.debug) - .addOption(new Option('--proxy-url ', 'Proxy URL for all network requests').default(DEFAULT_PAKE_OPTIONS.proxyUrl).hideHelp()) - .addOption(new Option('--user-agent ', 'Custom user agent').default(DEFAULT.userAgent).hideHelp()) - .addOption(new Option('--targets ', 'For Linux, option "deb" or "appimage"').default(DEFAULT.targets).hideHelp()) - .addOption(new Option('--app-version ', 'App version, the same as package.json version').default(DEFAULT.appVersion).hideHelp()) - .addOption(new Option('--always-on-top', 'Always on the top level').default(DEFAULT.alwaysOnTop).hideHelp()) - .addOption(new Option('--dark-mode', 'Force Mac app to use dark mode').default(DEFAULT.darkMode).hideHelp()) - .addOption(new Option('--disabled-web-shortcuts', 'Disabled webPage shortcuts').default(DEFAULT.disabledWebShortcuts).hideHelp()) .addOption( - new Option('--activation-shortcut ', 'Shortcut key to active App').default(DEFAULT_PAKE_OPTIONS.activationShortcut).hideHelp(), + new Option('--proxy-url ', 'Proxy URL for all network requests') + .default(DEFAULT_PAKE_OPTIONS.proxyUrl) + .hideHelp(), + ) + .addOption( + new Option('--user-agent ', 'Custom user agent') + .default(DEFAULT.userAgent) + .hideHelp(), + ) + .addOption( + new Option('--targets ', 'For Linux, option "deb" or "appimage"') + .default(DEFAULT.targets) + .hideHelp(), + ) + .addOption( + new Option( + '--app-version ', + 'App version, the same as package.json version', + ) + .default(DEFAULT.appVersion) + .hideHelp(), + ) + .addOption( + new Option('--always-on-top', 'Always on the top level') + .default(DEFAULT.alwaysOnTop) + .hideHelp(), + ) + .addOption( + new Option('--dark-mode', 'Force Mac app to use dark mode') + .default(DEFAULT.darkMode) + .hideHelp(), + ) + .addOption( + new Option('--disabled-web-shortcuts', 'Disabled webPage shortcuts') + .default(DEFAULT.disabledWebShortcuts) + .hideHelp(), + ) + .addOption( + new Option('--activation-shortcut ', 'Shortcut key to active App') + .default(DEFAULT_PAKE_OPTIONS.activationShortcut) + .hideHelp(), + ) + .addOption( + new Option('--show-system-tray', 'Show system tray in app') + .default(DEFAULT.showSystemTray) + .hideHelp(), + ) + .addOption( + new Option('--system-tray-icon ', 'Custom system tray icon') + .default(DEFAULT.systemTrayIcon) + .hideHelp(), + ) + .addOption( + new Option('--hide-on-close', 'Hide window on close instead of exiting') + .default(DEFAULT.hideOnClose) + .hideHelp(), + ) + .addOption( + new Option('--installer-language ', 'Installer language') + .default(DEFAULT.installerLanguage) + .hideHelp(), ) - .addOption(new Option('--show-system-tray', 'Show system tray in app').default(DEFAULT.showSystemTray).hideHelp()) - .addOption(new Option('--system-tray-icon ', 'Custom system tray icon').default(DEFAULT.systemTrayIcon).hideHelp()) - .addOption(new Option('--hide-on-close', 'Hide window on close instead of exiting').default(DEFAULT.hideOnClose).hideHelp()) - .addOption(new Option('--installer-language ', 'Installer language').default(DEFAULT.installerLanguage).hideHelp()) .version(packageJson.version, '-v, --version', 'Output the current version') .action(async (url: string, options: PakeCliOptions) => { await checkUpdateTips(); if (!url) { - program.outputHelp(str => { + program.outputHelp((str) => { return str .split('\n') - .filter(line => !/((-h,|--help)|((-v|-V),|--version))\s+.+$/.test(line)) + .filter( + (line) => !/((-h,|--help)|((-v|-V),|--version))\s+.+$/.test(line), + ) .join('\n'); }); process.exit(0); diff --git a/bin/defaults.ts b/bin/defaults.ts index 3725020..06beb3a 100644 --- a/bin/defaults.ts +++ b/bin/defaults.ts @@ -18,7 +18,7 @@ export const DEFAULT_PAKE_OPTIONS: PakeCliOptions = { targets: 'deb', useLocalFile: false, systemTrayIcon: '', - proxyUrl: "", + proxyUrl: '', debug: false, inject: [], installerLanguage: 'en-US', diff --git a/bin/dev.ts b/bin/dev.ts index d577ab7..09224db 100644 --- a/bin/dev.ts +++ b/bin/dev.ts @@ -6,7 +6,10 @@ import BuilderProvider from './builders/BuilderProvider'; async function startBuild() { log.setDefaultLevel('debug'); - const appOptions = await handleInputOptions(DEFAULT_DEV_PAKE_OPTIONS, DEFAULT_DEV_PAKE_OPTIONS.url); + const appOptions = await handleInputOptions( + DEFAULT_DEV_PAKE_OPTIONS, + DEFAULT_DEV_PAKE_OPTIONS.url, + ); log.debug('PakeAppOptions', appOptions); const builder = BuilderProvider.create(appOptions); diff --git a/bin/helpers/merge.ts b/bin/helpers/merge.ts index e658ad0..346d4ac 100644 --- a/bin/helpers/merge.ts +++ b/bin/helpers/merge.ts @@ -7,7 +7,11 @@ import logger from '@/options/logger'; import { PakeAppOptions, PlatformMap } from '@/types'; import { tauriConfigDirectory } from '@/utils/dir'; -export async function mergeConfig(url: string, options: PakeAppOptions, tauriConf: any) { +export async function mergeConfig( + url: string, + options: PakeAppOptions, + tauriConf: any, +) { const { width, height, @@ -78,7 +82,11 @@ export async function mergeConfig(url: string, options: PakeAppOptions, tauriCon // ignore it, because about_pake.html have be erased. // const filesToCopyBack = ['cli.js', 'about_pake.html']; const filesToCopyBack = ['cli.js']; - await Promise.all(filesToCopyBack.map(file => fsExtra.copy(path.join(distBakDir, file), path.join(distDir, file)))); + await Promise.all( + filesToCopyBack.map((file) => + fsExtra.copy(path.join(distBakDir, file), path.join(distDir, file)), + ), + ); } tauriConf.pake.windows[0].url = fileName; @@ -107,7 +115,9 @@ export async function mergeConfig(url: string, options: PakeAppOptions, tauriCon if (validTargets.includes(options.targets)) { tauriConf.bundle.targets = [options.targets]; } else { - logger.warn(`✼ The target must be one of ${validTargets.join(', ')}, the default 'deb' will be used.`); + logger.warn( + `✼ The target must be one of ${validTargets.join(', ')}, the default 'deb' will be used.`, + ); } } @@ -154,23 +164,31 @@ export async function mergeConfig(url: string, options: PakeAppOptions, tauriCon logger.warn(`✼ Icon will remain as default.`); } } else { - logger.warn('✼ Custom icon path may be invalid, default icon will be used instead.'); + logger.warn( + '✼ Custom icon path may be invalid, default icon will be used instead.', + ); tauriConf.bundle.icon = [iconInfo.defaultIcon]; } // Set tray icon path. - let trayIconPath = platform === 'darwin' ? 'png/icon_512.png' : tauriConf.bundle.icon[0]; + let trayIconPath = + platform === 'darwin' ? 'png/icon_512.png' : tauriConf.bundle.icon[0]; if (systemTrayIcon.length > 0) { try { await fsExtra.pathExists(systemTrayIcon); // 需要判断图标格式,默认只支持ico和png两种 let iconExt = path.extname(systemTrayIcon).toLowerCase(); if (iconExt == '.png' || iconExt == '.ico') { - const trayIcoPath = path.join(npmDirectory, `src-tauri/png/${name.toLowerCase()}${iconExt}`); + const trayIcoPath = path.join( + npmDirectory, + `src-tauri/png/${name.toLowerCase()}${iconExt}`, + ); trayIconPath = `png/${name.toLowerCase()}${iconExt}`; await fsExtra.copy(systemTrayIcon, trayIcoPath); } else { - logger.warn(`✼ System tray icon must be .ico or .png, but you provided ${iconExt}.`); + logger.warn( + `✼ System tray icon must be .ico or .png, but you provided ${iconExt}.`, + ); logger.warn(`✼ Default system tray icon will be used.`); } } catch { @@ -184,15 +202,22 @@ export async function mergeConfig(url: string, options: PakeAppOptions, tauriCon delete tauriConf.app.trayIcon; - const injectFilePath = path.join(npmDirectory, `src-tauri/src/inject/custom.js`); + const injectFilePath = path.join( + npmDirectory, + `src-tauri/src/inject/custom.js`, + ); // inject js or css files if (inject?.length > 0) { - if (!inject.every(item => item.endsWith('.css') || item.endsWith('.js'))) { + if ( + !inject.every((item) => item.endsWith('.css') || item.endsWith('.js')) + ) { logger.error('The injected file must be in either CSS or JS format.'); return; } - const files = inject.map(filepath => (path.isAbsolute(filepath) ? filepath : path.join(process.cwd(), filepath))); + const files = inject.map((filepath) => + path.isAbsolute(filepath) ? filepath : path.join(process.cwd(), filepath), + ); tauriConf.pake.inject = files; await combineFiles(files, injectFilePath); } else { @@ -208,7 +233,10 @@ export async function mergeConfig(url: string, options: PakeAppOptions, tauriCon linux: 'tauri.linux.conf.json', }; - const configPath = path.join(tauriConfigDirectory, platformConfigPaths[platform]); + const configPath = path.join( + tauriConfigDirectory, + platformConfigPaths[platform], + ); const bundleConf = { bundle: tauriConf.bundle }; console.log('pakeConfig', tauriConf.pake); diff --git a/bin/helpers/rust.ts b/bin/helpers/rust.ts index 661f8ee..9834b89 100644 --- a/bin/helpers/rust.ts +++ b/bin/helpers/rust.ts @@ -18,7 +18,9 @@ export async function installRust() { const spinner = getSpinner('Downloading Rust...'); try { - await shellExec(IS_WIN ? rustInstallScriptForWindows : rustInstallScriptForMac); + await shellExec( + IS_WIN ? rustInstallScriptForWindows : rustInstallScriptForMac, + ); spinner.succeed(chalk.green('Rust installed successfully!')); } catch (error) { console.error('Error installing Rust:', error.message); diff --git a/bin/helpers/updater.ts b/bin/helpers/updater.ts index a55837b..bdb6bd7 100644 --- a/bin/helpers/updater.ts +++ b/bin/helpers/updater.ts @@ -2,5 +2,7 @@ import updateNotifier from 'update-notifier'; import packageJson from '../../package.json'; export async function checkUpdateTips() { - updateNotifier({ pkg: packageJson, updateCheckInterval: 1000 * 60 }).notify({ isGlobal: true }); + updateNotifier({ pkg: packageJson, updateCheckInterval: 1000 * 60 }).notify({ + isGlobal: true, + }); } diff --git a/bin/options/icon.ts b/bin/options/icon.ts index 55c8c23..d8e47f4 100644 --- a/bin/options/icon.ts +++ b/bin/options/icon.ts @@ -19,12 +19,14 @@ export async function handleIcon(options: PakeAppOptions) { return path.resolve(options.icon); } } else { - logger.warn('✼ No icon given, default in use. For a custom icon, use --icon option.'); + logger.warn( + '✼ No icon given, default in use. For a custom icon, use --icon option.', + ); const iconPath = IS_WIN ? 'src-tauri/png/icon_256.ico' : IS_LINUX - ? 'src-tauri/png/icon_512.png' - : 'src-tauri/icons/icon.icns'; + ? 'src-tauri/png/icon_512.png' + : 'src-tauri/icons/icon.icns'; return path.join(npmDirectory, iconPath); } } @@ -32,7 +34,9 @@ export async function handleIcon(options: PakeAppOptions) { export async function downloadIcon(iconUrl: string) { const spinner = getSpinner('Downloading icon...'); try { - const iconResponse = await axios.get(iconUrl, { responseType: 'arraybuffer' }); + const iconResponse = await axios.get(iconUrl, { + responseType: 'arraybuffer', + }); const iconData = await iconResponse.data; if (!iconData) { @@ -49,7 +53,10 @@ export async function downloadIcon(iconUrl: string) { // Fix this for linux if (IS_LINUX) { iconPath = 'png/linux_temp.png'; - await fsExtra.outputFile(`${npmDirectory}/src-tauri/${iconPath}`, iconData); + await fsExtra.outputFile( + `${npmDirectory}/src-tauri/${iconPath}`, + iconData, + ); } else { await fsExtra.outputFile(iconPath, iconData); } diff --git a/bin/options/index.ts b/bin/options/index.ts index f1295df..a85dee3 100644 --- a/bin/options/index.ts +++ b/bin/options/index.ts @@ -20,7 +20,10 @@ function isValidName(name: string, platform: NodeJS.Platform): boolean { return !!name && reg.test(name); } -export default async function handleOptions(options: PakeCliOptions, url: string): Promise { +export default async function handleOptions( + options: PakeCliOptions, + url: string, +): Promise { const { platform } = process; const isActions = process.env.GITHUB_ACTIONS; let name = options.name; @@ -36,7 +39,8 @@ export default async function handleOptions(options: PakeCliOptions, url: string if (!isValidName(name, platform)) { const LINUX_NAME_ERROR = `✕ Name should only include lowercase letters, numbers, and dashes (not leading dashes), and must contain at least one lowercase letter or number. Examples: com-123-xxx, 123pan, pan123, weread, we-read.`; const DEFAULT_NAME_ERROR = `✕ Name should only include letters, numbers, dashes, and spaces (not leading dashes and spaces), and must contain at least one letter or number. Examples: 123pan, 123Pan, Pan123, weread, WeRead, WERead, we-read, We Read.`; - const errorMsg = platform === 'linux' ? LINUX_NAME_ERROR : DEFAULT_NAME_ERROR; + const errorMsg = + platform === 'linux' ? LINUX_NAME_ERROR : DEFAULT_NAME_ERROR; logger.error(errorMsg); if (isActions) { name = resolveAppName(url, platform); diff --git a/bin/options/logger.ts b/bin/options/logger.ts index 0461d4c..d35164b 100644 --- a/bin/options/logger.ts +++ b/bin/options/logger.ts @@ -3,19 +3,19 @@ import log from 'loglevel'; const logger = { info(...msg: any[]) { - log.info(...msg.map(m => chalk.white(m))); + log.info(...msg.map((m) => chalk.white(m))); }, debug(...msg: any[]) { log.debug(...msg); }, error(...msg: any[]) { - log.error(...msg.map(m => chalk.red(m))); + log.error(...msg.map((m) => chalk.red(m))); }, warn(...msg: any[]) { - log.info(...msg.map(m => chalk.yellow(m))); + log.info(...msg.map((m) => chalk.yellow(m))); }, success(...msg: any[]) { - log.info(...msg.map(m => chalk.green(m))); + log.info(...msg.map((m) => chalk.green(m))); }, }; diff --git a/bin/utils/combine.ts b/bin/utils/combine.ts index 641c834..8b5c7c0 100644 --- a/bin/utils/combine.ts +++ b/bin/utils/combine.ts @@ -1,7 +1,7 @@ import fs from 'fs'; export default async function combineFiles(files: string[], output: string) { - const contents = files.map(file => { + const contents = files.map((file) => { const fileContent = fs.readFileSync(file); if (file.endsWith('.css')) { return ( @@ -11,7 +11,11 @@ export default async function combineFiles(files: string[], output: string) { ); } - return "window.addEventListener('DOMContentLoaded', (_event) => { " + fileContent + ' });'; + return ( + "window.addEventListener('DOMContentLoaded', (_event) => { " + + fileContent + + ' });' + ); }); fs.writeFileSync(output, contents.join('\n')); return files; diff --git a/bin/utils/info.ts b/bin/utils/info.ts index f9ad6ac..0d077dd 100644 --- a/bin/utils/info.ts +++ b/bin/utils/info.ts @@ -5,11 +5,18 @@ import chalk from 'chalk'; // Generates an identifier based on the given URL. export function getIdentifier(url: string) { - const postFixHash = crypto.createHash('md5').update(url).digest('hex').substring(0, 6); + const postFixHash = crypto + .createHash('md5') + .update(url) + .digest('hex') + .substring(0, 6); return `com.pake.${postFixHash}`; } -export async function promptText(message: string, initial?: string): Promise { +export async function promptText( + message: string, + initial?: string, +): Promise { const response = await prompts({ type: 'text', name: 'content', diff --git a/bin/utils/ip.ts b/bin/utils/ip.ts index c3b6434..daf2999 100644 --- a/bin/utils/ip.ts +++ b/bin/utils/ip.ts @@ -13,13 +13,13 @@ const ping = async (host: string) => { // Prevent timeouts from affecting user experience. const requestPromise = new Promise((resolve, reject) => { - const req = http.get(`http://${ip.address}`, res => { + const req = http.get(`http://${ip.address}`, (res) => { const delay = new Date().getTime() - start.getTime(); res.resume(); resolve(delay); }); - req.on('error', err => { + req.on('error', (err) => { reject(err); }); }); diff --git a/bin/utils/shell.ts b/bin/utils/shell.ts index 404c451..77d8051 100644 --- a/bin/utils/shell.ts +++ b/bin/utils/shell.ts @@ -5,10 +5,12 @@ export async function shellExec(command: string) { try { const { exitCode } = await execa(command, { cwd: npmDirectory, - stdio: 'inherit' + stdio: 'inherit', }); return exitCode; } catch (error) { - throw new Error(`Error occurred while executing command "${command}". Exit code: ${error.exitCode}`); + throw new Error( + `Error occurred while executing command "${command}". Exit code: ${error.exitCode}`, + ); } } diff --git a/dist/cli.js b/dist/cli.js index 29bd246..7f79a9d 100644 --- a/dist/cli.js +++ b/dist/cli.js @@ -23,232 +23,232 @@ var name = "pake-cli"; var version$1 = "3.1.2"; var description = "🤱🏻 Turn any webpage into a desktop app with Rust. 🤱🏻 利用 Rust 轻松构建轻量级多端桌面应用。"; var engines = { - node: ">=16.0.0" + node: ">=16.0.0" }; var bin = { - pake: "./cli.js" + pake: "./cli.js" }; var repository = { - type: "git", - url: "https://github.com/tw93/pake.git" + type: "git", + url: "https://github.com/tw93/pake.git" }; var author = { - name: "Tw93", - email: "tw93@qq.com" + name: "Tw93", + email: "tw93@qq.com" }; var keywords = [ - "pake", - "pake-cli", - "rust", - "tauri", - "no-electron", - "productivity" + "pake", + "pake-cli", + "rust", + "tauri", + "no-electron", + "productivity" ]; var files = [ - "dist", - "src-tauri", - "cli.js" + "dist", + "src-tauri", + "cli.js" ]; var scripts = { - start: "npm run dev", - dev: "npm run tauri dev", - build: "npm run tauri build --release", - "build:debug": "npm run tauri build -- --debug", - "build:mac": "npm run tauri build -- --target universal-apple-darwin", - "build:config": "chmod +x script/app_config.mjs && node script/app_config.mjs", - analyze: "cd src-tauri && cargo bloat --release --crates", - tauri: "tauri", - cli: "rollup -c rollup.config.js --watch", - "cli:dev": "cross-env NODE_ENV=development rollup -c rollup.config.js -w", - "cli:build": "cross-env NODE_ENV=production rollup -c rollup.config.js", - prepublishOnly: "npm run cli:build" + start: "npm run dev", + dev: "npm run tauri dev", + build: "npm run tauri build --release", + "build:debug": "npm run tauri build -- --debug", + "build:mac": "npm run tauri build -- --target universal-apple-darwin", + "build:config": "chmod +x script/app_config.mjs && node script/app_config.mjs", + analyze: "cd src-tauri && cargo bloat --release --crates", + tauri: "tauri", + cli: "rollup -c rollup.config.js --watch", + "cli:dev": "cross-env NODE_ENV=development rollup -c rollup.config.js -w", + "cli:build": "cross-env NODE_ENV=production rollup -c rollup.config.js", + prepublishOnly: "npm run cli:build" }; var type = "module"; var exports = "./dist/pake.js"; var license = "MIT"; var dependencies = { - "@tauri-apps/api": "^2.2.0", - "@tauri-apps/cli": "^2.2.5", - axios: "^1.7.9", - chalk: "^5.4.1", - commander: "^13.1.0", - execa: "^9.5.2", - "file-type": "^20.0.0", - "fs-extra": "^11.3.0", - "is-url": "^1.2.4", - loglevel: "^1.9.2", - ora: "^8.1.1", - prompts: "^2.4.2", - psl: "^1.15.0", - "tmp-promise": "^3.0.3", - "update-notifier": "^7.3.1" + "@tauri-apps/api": "^2.2.0", + "@tauri-apps/cli": "^2.2.5", + axios: "^1.7.9", + chalk: "^5.4.1", + commander: "^13.1.0", + execa: "^9.5.2", + "file-type": "^20.0.0", + "fs-extra": "^11.3.0", + "is-url": "^1.2.4", + loglevel: "^1.9.2", + ora: "^8.1.1", + prompts: "^2.4.2", + psl: "^1.15.0", + "tmp-promise": "^3.0.3", + "update-notifier": "^7.3.1" }; var devDependencies = { - "@rollup/plugin-alias": "^5.1.1", - "@rollup/plugin-commonjs": "^28.0.2", - "@rollup/plugin-json": "^6.1.0", - "@rollup/plugin-replace": "^6.0.2", - "@rollup/plugin-terser": "^0.4.4", - "@types/fs-extra": "^11.0.4", - "@types/is-url": "^1.2.32", - "@types/node": "^22.10.8", - "@types/page-icon": "^0.3.6", - "@types/prompts": "^2.4.9", - "@types/psl": "^1.1.3", - "@types/tmp": "^0.2.6", - "@types/update-notifier": "^6.0.8", - "app-root-path": "^3.1.0", - "cross-env": "^7.0.3", - rollup: "^4.31.0", - "rollup-plugin-typescript2": "^0.36.0", - tslib: "^2.8.1", - typescript: "^5.7.3" + "@rollup/plugin-alias": "^5.1.1", + "@rollup/plugin-commonjs": "^28.0.2", + "@rollup/plugin-json": "^6.1.0", + "@rollup/plugin-replace": "^6.0.2", + "@rollup/plugin-terser": "^0.4.4", + "@types/fs-extra": "^11.0.4", + "@types/is-url": "^1.2.32", + "@types/node": "^22.10.8", + "@types/page-icon": "^0.3.6", + "@types/prompts": "^2.4.9", + "@types/psl": "^1.1.3", + "@types/tmp": "^0.2.6", + "@types/update-notifier": "^6.0.8", + "app-root-path": "^3.1.0", + "cross-env": "^7.0.3", + rollup: "^4.31.0", + "rollup-plugin-typescript2": "^0.36.0", + tslib: "^2.8.1", + typescript: "^5.7.3" }; var packageJson = { - name: name, - version: version$1, - description: description, - engines: engines, - bin: bin, - repository: repository, - author: author, - keywords: keywords, - files: files, - scripts: scripts, - type: type, - exports: exports, - license: license, - dependencies: dependencies, - devDependencies: devDependencies + name: name, + version: version$1, + description: description, + engines: engines, + bin: bin, + repository: repository, + author: author, + keywords: keywords, + files: files, + scripts: scripts, + type: type, + exports: exports, + license: license, + dependencies: dependencies, + devDependencies: devDependencies }; var windows = [ - { - url: "https://weread.qq.com/", - url_type: "web", - hide_title_bar: true, - fullscreen: false, - width: 1200, - height: 780, - resizable: true, - always_on_top: false, - dark_mode: false, - activation_shortcut: "", - disabled_web_shortcuts: false, - hide_on_close: true - } + { + url: "https://weread.qq.com/", + url_type: "web", + hide_title_bar: true, + fullscreen: false, + width: 1200, + height: 780, + resizable: true, + always_on_top: false, + dark_mode: false, + activation_shortcut: "", + disabled_web_shortcuts: false, + hide_on_close: true + } ]; var user_agent = { - macos: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Safari/605.1.15", - linux: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36", - windows: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36" + macos: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Safari/605.1.15", + linux: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36", + windows: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36" }; var system_tray = { - macos: false, - linux: true, - windows: true + macos: false, + linux: true, + windows: true }; var system_tray_path = "icons/icon.png"; var inject = [ ]; var proxy_url = ""; var pakeConf = { - windows: windows, - user_agent: user_agent, - system_tray: system_tray, - system_tray_path: system_tray_path, - inject: inject, - proxy_url: proxy_url + windows: windows, + user_agent: user_agent, + system_tray: system_tray, + system_tray_path: system_tray_path, + inject: inject, + proxy_url: proxy_url }; var productName$1 = "WeRead"; var identifier = "com.pake.weread"; var version = "1.0.0"; var app = { - withGlobalTauri: true, - trayIcon: { - iconPath: "png/weread_512.png", - iconAsTemplate: false, - id: "pake-tray" - } + withGlobalTauri: true, + trayIcon: { + iconPath: "png/weread_512.png", + iconAsTemplate: false, + id: "pake-tray" + } }; var build = { - frontendDist: "../dist" + frontendDist: "../dist" }; var CommonConf = { - productName: productName$1, - identifier: identifier, - version: version, - app: app, - build: build + productName: productName$1, + identifier: identifier, + version: version, + app: app, + build: build }; var bundle$2 = { - icon: [ - "png/weread_256.ico", - "png/weread_32.ico" - ], - active: true, - resources: [ - "png/weread_32.ico" - ], - targets: [ - "msi" - ], - windows: { - digestAlgorithm: "sha256", - wix: { - language: [ - "en-US" - ], - template: "assets/main.wxs" - } - } + icon: [ + "png/weread_256.ico", + "png/weread_32.ico" + ], + active: true, + resources: [ + "png/weread_32.ico" + ], + targets: [ + "msi" + ], + windows: { + digestAlgorithm: "sha256", + wix: { + language: [ + "en-US" + ], + template: "assets/main.wxs" + } + } }; var WinConf = { - bundle: bundle$2 + bundle: bundle$2 }; var bundle$1 = { - icon: [ - "icons/weread.icns" - ], - active: true, - macOS: { - }, - targets: [ - "dmg" - ] + icon: [ + "icons/weread.icns" + ], + active: true, + macOS: { + }, + targets: [ + "dmg" + ] }; var MacConf = { - bundle: bundle$1 + bundle: bundle$1 }; var productName = "we-read"; var bundle = { - icon: [ - "png/weread_512.png" - ], - active: true, - linux: { - deb: { - depends: [ - "curl", - "wget" - ], - files: { - "/usr/share/applications/com-pake-weread.desktop": "assets/com-pake-weread.desktop" - } - } - }, - targets: [ - "deb", - "appimage" - ] + icon: [ + "png/weread_512.png" + ], + active: true, + linux: { + deb: { + depends: [ + "curl", + "wget" + ], + files: { + "/usr/share/applications/com-pake-weread.desktop": "assets/com-pake-weread.desktop" + } + } + }, + targets: [ + "deb", + "appimage" + ] }; var LinuxConf = { - productName: productName, - bundle: bundle + productName: productName, + bundle: bundle }; const platformConfigs = { diff --git a/package.json b/package.json index f7beffb..ce701fb 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "cli": "rollup -c rollup.config.js --watch", "cli:dev": "cross-env NODE_ENV=development rollup -c rollup.config.js -w", "cli:build": "cross-env NODE_ENV=production rollup -c rollup.config.js", + "format": "npx prettier --write . --ignore-unknown", "prepublishOnly": "npm run cli:build" }, "type": "module", diff --git a/rollup.config.js b/rollup.config.js index e65d184..8a3d2c2 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,40 +1,40 @@ -import path from 'path'; -import appRootPath from 'app-root-path'; -import typescript from 'rollup-plugin-typescript2'; -import alias from '@rollup/plugin-alias'; -import commonjs from '@rollup/plugin-commonjs'; -import json from '@rollup/plugin-json'; -import replace from '@rollup/plugin-replace'; -import chalk from 'chalk'; -import { spawn, exec } from 'child_process'; +import path from "path"; +import appRootPath from "app-root-path"; +import typescript from "rollup-plugin-typescript2"; +import alias from "@rollup/plugin-alias"; +import commonjs from "@rollup/plugin-commonjs"; +import json from "@rollup/plugin-json"; +import replace from "@rollup/plugin-replace"; +import chalk from "chalk"; +import { spawn, exec } from "child_process"; -const isProduction = process.env.NODE_ENV === 'production'; +const isProduction = process.env.NODE_ENV === "production"; const devPlugins = !isProduction ? [pakeCliDevPlugin()] : []; export default { - input: isProduction ? 'bin/cli.ts' : 'bin/dev.ts', + input: isProduction ? "bin/cli.ts" : "bin/dev.ts", output: { - file: isProduction ? 'dist/cli.js' : 'dist/dev.js', - format: 'es', + file: isProduction ? "dist/cli.js" : "dist/dev.js", + format: "es", sourcemap: !isProduction, }, watch: { - include: 'bin/**', - exclude: 'node_modules/**', + include: "bin/**", + exclude: "node_modules/**", }, plugins: [ json(), typescript({ - tsconfig: 'tsconfig.json', + tsconfig: "tsconfig.json", clean: true, // Clear cache }), commonjs(), replace({ - 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV), + "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV), preventAssignment: true, }), alias({ - entries: [{ find: '@', replacement: path.join(appRootPath.path, 'bin') }], + entries: [{ find: "@", replacement: path.join(appRootPath.path, "bin") }], }), ...devPlugins, ], @@ -47,38 +47,38 @@ function pakeCliDevPlugin() { let devHasStarted = false; return { - name: 'pake-cli-dev-plugin', + name: "pake-cli-dev-plugin", buildEnd() { - const command = 'node'; - const cliCmdArgs = ['./dist/dev.js']; + const command = "node"; + const cliCmdArgs = ["./dist/dev.js"]; cliChildProcess = spawn(command, cliCmdArgs, { detached: true }); - cliChildProcess.stdout.on('data', data => { + cliChildProcess.stdout.on("data", (data) => { console.log(chalk.green(data.toString())); }); - cliChildProcess.stderr.on('data', data => { + cliChildProcess.stderr.on("data", (data) => { console.error(chalk.yellow(data.toString())); }); - cliChildProcess.on('close', async code => { + cliChildProcess.on("close", async (code) => { console.log(chalk.yellow(`cli running end with code: ${code}`)); if (devHasStarted) return; devHasStarted = true; devChildProcess = await exec( - 'npm run tauri dev -- --config ./src-tauri/.pake/tauri.conf.json --features cli-build', + "npm run tauri dev -- --config ./src-tauri/.pake/tauri.conf.json --features cli-build", ); - devChildProcess.stdout.on('data', data => { + devChildProcess.stdout.on("data", (data) => { console.log(chalk.green(data.toString())); }); - devChildProcess.stderr.on('data', data => { + devChildProcess.stderr.on("data", (data) => { console.error(chalk.yellow(data.toString())); }); - devChildProcess.on('close', code => { + devChildProcess.on("close", (code) => { console.log(chalk.yellow(`dev running end: ${code}`)); process.exit(code); }); diff --git a/script/app_config.mjs b/script/app_config.mjs index cda3651..56f93e8 100755 --- a/script/app_config.mjs +++ b/script/app_config.mjs @@ -1,11 +1,11 @@ -import pakeJson from '../src-tauri/pake.json' assert { type: 'json' }; -import tauriJson from '../src-tauri/tauri.conf.json' assert { type: 'json' }; -import windowsJson from '../src-tauri/tauri.windows.conf.json' assert { type: 'json' }; -import macosJson from '../src-tauri/tauri.macos.conf.json' assert { type: 'json' }; -import linuxJson from '../src-tauri/tauri.linux.conf.json' assert { type: 'json' }; +import pakeJson from "../src-tauri/pake.json" assert { type: "json" }; +import tauriJson from "../src-tauri/tauri.conf.json" assert { type: "json" }; +import windowsJson from "../src-tauri/tauri.windows.conf.json" assert { type: "json" }; +import macosJson from "../src-tauri/tauri.macos.conf.json" assert { type: "json" }; +import linuxJson from "../src-tauri/tauri.linux.conf.json" assert { type: "json" }; -import { writeFileSync, existsSync, copyFileSync } from 'fs'; -import os from 'os'; +import { writeFileSync, existsSync, copyFileSync } from "fs"; +import os from "os"; const desktopEntry = `[Desktop Entry] Encoding=UTF-8 @@ -25,15 +25,15 @@ const variables = { title: process.env.TITLE, nameZh: process.env.NAME_ZH, - pakeConfigPath: 'src-tauri/pake.json', - tauriConfigPath: 'src-tauri/tauri.conf.json', + pakeConfigPath: "src-tauri/pake.json", + tauriConfigPath: "src-tauri/tauri.conf.json", identifier: `com.pake.${process.env.NAME}`, linux: { - configFilePath: 'src-tauri/tauri.linux.conf.json', + configFilePath: "src-tauri/tauri.linux.conf.json", iconPath: `src-tauri/png/${process.env.NAME}_512.png`, productName: `com-pake-${process.env.NAME}`, - defaultIconPath: 'src-tauri/png/icon_512.png', + defaultIconPath: "src-tauri/png/icon_512.png", icon: [`png/${process.env.NAME}_512.png`], desktopEntry, desktopEntryPath: `src-tauri/assets/com-pake-${process.env.NAME}.desktop`, @@ -43,17 +43,17 @@ const variables = { }, }, macos: { - configFilePath: 'src-tauri/tauri.macos.conf.json', + configFilePath: "src-tauri/tauri.macos.conf.json", iconPath: `src-tauri/icons/${process.env.NAME}.icns`, - defaultPath: 'src-tauri/icons/icon.icns', + defaultPath: "src-tauri/icons/icon.icns", icon: [`icons/${process.env.NAME}.icns`], }, windows: { - configFilePath: 'src-tauri/tauri.windows.conf.json', + configFilePath: "src-tauri/tauri.windows.conf.json", iconPath: `src-tauri/png/${process.env.NAME}_32.ico`, - defaultPath: 'src-tauri/png/icon_32.ico', + defaultPath: "src-tauri/png/icon_32.ico", hdIconPath: `src-tauri/png/${process.env.NAME}_256.ico`, - hdDefaultPath: 'src-tauri/png/icon_256.ico', + hdDefaultPath: "src-tauri/png/icon_256.ico", icon: [`png/${process.env.NAME}_256.ico`, `png/${process.env.NAME}_32.ico`], resources: [`png/${process.env.NAME}_32.ico`], }, @@ -69,20 +69,23 @@ let platformVariables; let platformConfig; switch (os.platform()) { - case 'linux': + case "linux": platformVariables = variables.linux; platformConfig = linuxJson; updateDesktopEntry(); break; - case 'darwin': + case "darwin": platformVariables = variables.macos; platformConfig = macosJson; break; - case 'win32': + case "win32": platformConfig = windowsJson; platformVariables = variables.windows; updateResources(); - updateIconFile(platformVariables.hdIconPath, platformVariables.hdDefaultPath); + updateIconFile( + platformVariables.hdIconPath, + platformVariables.hdDefaultPath, + ); break; } @@ -93,29 +96,29 @@ updatePlatformConfig(platformConfig, platformVariables); save(); function validate() { - if (!('URL' in process.env)) { - console.log('URL is not set'); + if (!("URL" in process.env)) { + console.log("URL is not set"); process.exit(1); } console.log(`URL: ${process.env.URL}`); - if (!('NAME' in process.env)) { - console.log('NAME is not set'); + if (!("NAME" in process.env)) { + console.log("NAME is not set"); process.exit(1); } console.log(`NAME: ${process.env.NAME}`); - if (!('TITLE' in process.env)) { - console.log('TITLE is not set'); + if (!("TITLE" in process.env)) { + console.log("TITLE is not set"); process.exit(1); } console.log(`TITLE: ${process.env.TITLE}`); - if (!('NAME_ZH' in process.env)) { - console.log('NAME_ZH is not set'); + if (!("NAME_ZH" in process.env)) { + console.log("NAME_ZH is not set"); process.exit(1); } @@ -128,18 +131,23 @@ function updatePakeJson() { function updateTauriJson() { tauriJson.productName = variables.title; - writeFileSync('src-tauri/tauri.conf.json', JSON.stringify(tauriJson, null, 2)); + writeFileSync( + "src-tauri/tauri.conf.json", + JSON.stringify(tauriJson, null, 2), + ); } function updateIconFile(iconPath, defaultIconPath) { if (!existsSync(iconPath)) { - console.warn(`Icon for ${process.env.NAME} not found, will use default icon`); + console.warn( + `Icon for ${process.env.NAME} not found, will use default icon`, + ); copyFileSync(defaultIconPath, iconPath); } } function updatePlatformConfig(platformConfig, platformVariables) { - platformConfig.bundle['icon'] = platformVariables.icon; + platformConfig.bundle["icon"] = platformVariables.icon; platformConfig.identifier = variables.identifier; } @@ -147,17 +155,31 @@ function save() { writeFileSync(variables.pakeConfigPath, JSON.stringify(pakeJson, null, 2)); writeFileSync(variables.tauriConfigPath, JSON.stringify(tauriJson, null, 2)); - writeFileSync(variables.linux.configFilePath, JSON.stringify(linuxJson, null, 2)); - writeFileSync(platformVariables.configFilePath, JSON.stringify(platformConfig, null, 2)); + writeFileSync( + variables.linux.configFilePath, + JSON.stringify(linuxJson, null, 2), + ); + writeFileSync( + platformVariables.configFilePath, + JSON.stringify(platformConfig, null, 2), + ); - writeFileSync(variables.macos.configFilePath, JSON.stringify(macosJson, null, 2)); + writeFileSync( + variables.macos.configFilePath, + JSON.stringify(macosJson, null, 2), + ); - writeFileSync(variables.windows.configFilePath, JSON.stringify(windowsJson, null, 2)); + writeFileSync( + variables.windows.configFilePath, + JSON.stringify(windowsJson, null, 2), + ); } function updateDesktopEntry() { linuxJson.bundle.linux.deb.files = {}; - linuxJson.bundle.linux.deb.files[variables.linux.desktopEntryConfig.configKey] = variables.linux.desktopEntryConfig.configValue; + linuxJson.bundle.linux.deb.files[ + variables.linux.desktopEntryConfig.configKey + ] = variables.linux.desktopEntryConfig.configValue; writeFileSync(variables.linux.desktopEntryPath, variables.linux.desktopEntry); } diff --git a/script/build_with_pake_cli.js b/script/build_with_pake_cli.js index 9a54d32..2d8808d 100644 --- a/script/build_with_pake_cli.js +++ b/script/build_with_pake_cli.js @@ -1,62 +1,73 @@ -import fs from 'fs'; -import path from 'path'; -import axios from 'axios'; -import { execa } from 'execa'; +import fs from "fs"; +import path from "path"; +import axios from "axios"; +import { execa } from "execa"; // Configuration logging const logConfiguration = () => { - console.log('Welcome to use pake-cli to build app'); - console.log('Node.js info in your localhost:', process.version); - console.log('\n=======================\n'); - console.log('Pake parameters:'); - console.log('url:', process.env.URL); - console.log('name:', process.env.NAME); - console.log('icon:', process.env.ICON); - console.log('height:', process.env.HEIGHT); - console.log('width:', process.env.WIDTH); - console.log('fullscreen:', process.env.FULLSCREEN); - console.log('hide-title-bar:', process.env.HIDE_TITLE_BAR); - console.log('is multi arch? only for Mac:', process.env.MULTI_ARCH); - console.log('targets type? only for Linux:', process.env.TARGETS); - console.log('===========================\n'); + console.log("Welcome to use pake-cli to build app"); + console.log("Node.js info in your localhost:", process.version); + console.log("\n=======================\n"); + console.log("Pake parameters:"); + console.log("url:", process.env.URL); + console.log("name:", process.env.NAME); + console.log("icon:", process.env.ICON); + console.log("height:", process.env.HEIGHT); + console.log("width:", process.env.WIDTH); + console.log("fullscreen:", process.env.FULLSCREEN); + console.log("hide-title-bar:", process.env.HIDE_TITLE_BAR); + console.log("is multi arch? only for Mac:", process.env.MULTI_ARCH); + console.log("targets type? only for Linux:", process.env.TARGETS); + console.log("===========================\n"); }; // Build parameters construction const buildParameters = () => { - const params = ['cli.js', process.env.URL, '--name', process.env.NAME, '--height', process.env.HEIGHT, '--width', process.env.WIDTH]; + const params = [ + "cli.js", + process.env.URL, + "--name", + process.env.NAME, + "--height", + process.env.HEIGHT, + "--width", + process.env.WIDTH, + ]; - if (process.env.HIDE_TITLE_BAR === 'true') { - params.push('--hide-title-bar'); + if (process.env.HIDE_TITLE_BAR === "true") { + params.push("--hide-title-bar"); } - if (process.env.FULLSCREEN === 'true') { - params.push('--fullscreen'); + if (process.env.FULLSCREEN === "true") { + params.push("--fullscreen"); } - if (process.env.MULTI_ARCH === 'true') { + if (process.env.MULTI_ARCH === "true") { // We'll handle rustup separately since it's a different command - params.push('--multi-arch'); + params.push("--multi-arch"); } if (process.env.TARGETS) { - params.push('--targets', process.env.TARGETS); + params.push("--targets", process.env.TARGETS); } - if (process.platform === 'win32' || process.platform === 'linux') { - params.push('--show-system-tray'); + if (process.platform === "win32" || process.platform === "linux") { + params.push("--show-system-tray"); } return params; }; // Icon download handling -const downloadIcon = async iconFile => { +const downloadIcon = async (iconFile) => { try { - const response = await axios.get(process.env.ICON, { responseType: 'arraybuffer' }); + const response = await axios.get(process.env.ICON, { + responseType: "arraybuffer", + }); fs.writeFileSync(iconFile, response.data); - return ['--icon', iconFile]; + return ["--icon", iconFile]; } catch (error) { - console.error('Error occurred during icon download:', error); + console.error("Error occurred during icon download:", error); throw error; } }; @@ -64,14 +75,14 @@ const downloadIcon = async iconFile => { // Get icon file name based on platform const getIconFileName = () => { switch (process.platform) { - case 'linux': - return 'icon.png'; - case 'darwin': - return 'icon.icns'; - case 'win32': - return 'icon.ico'; + case "linux": + return "icon.png"; + case "darwin": + return "icon.icns"; + case "win32": + return "icon.ico"; default: - throw new Error('Unable to detect your OS system'); + throw new Error("Unable to detect your OS system"); } }; @@ -80,47 +91,49 @@ const main = async () => { try { logConfiguration(); - const cliPath = path.join(process.cwd(), 'node_modules/pake-cli'); + const cliPath = path.join(process.cwd(), "node_modules/pake-cli"); process.chdir(cliPath); let params = buildParameters(); - if (process.env.MULTI_ARCH === 'true') { - await execa('rustup', ['target', 'add', 'aarch64-apple-darwin']); + if (process.env.MULTI_ARCH === "true") { + await execa("rustup", ["target", "add", "aarch64-apple-darwin"]); } - if (process.env.ICON && process.env.ICON !== '') { + if (process.env.ICON && process.env.ICON !== "") { const iconFile = getIconFileName(); const iconParams = await downloadIcon(iconFile); params.push(...iconParams); } else { - console.log("Won't download the icon as ICON environment variable is not defined!"); + console.log( + "Won't download the icon as ICON environment variable is not defined!", + ); } - console.log('Pake parameters:', params.join(' ')); - console.log('Compiling....'); + console.log("Pake parameters:", params.join(" ")); + console.log("Compiling...."); // Execute the CLI command - await execa('node', params, { stdio: 'inherit' }); + await execa("node", params, { stdio: "inherit" }); // Create output directory if it doesn't exist - if (!fs.existsSync('output')) { - fs.mkdirSync('output'); + if (!fs.existsSync("output")) { + fs.mkdirSync("output"); } // Move built files to output directory - const files = fs.readdirSync('.'); + const files = fs.readdirSync("."); const namePattern = new RegExp(`^${process.env.NAME}\\..*$`); for (const file of files) { if (namePattern.test(file)) { - await execa('mv', [file, path.join('output', file)]); + await execa("mv", [file, path.join("output", file)]); } } - console.log('Build Success'); - process.chdir('../..'); + console.log("Build Success"); + process.chdir("../.."); } catch (error) { - console.error('Build failed:', error); + console.error("Build failed:", error); process.exit(1); } }; diff --git a/src-tauri/src/inject/component.js b/src-tauri/src/inject/component.js index 0907145..f55491d 100644 --- a/src-tauri/src/inject/component.js +++ b/src-tauri/src/inject/component.js @@ -1,15 +1,16 @@ -document.addEventListener('DOMContentLoaded', () => { +document.addEventListener("DOMContentLoaded", () => { // Toast function pakeToast(msg) { - const m = document.createElement('div'); + const m = document.createElement("div"); m.innerHTML = msg; m.style.cssText = - 'max-width:60%;min-width: 80px;padding:0 12px;height: 32px;color: rgb(255, 255, 255);line-height: 32px;text-align: center;border-radius: 8px;position: fixed; bottom:24px;right: 28px;z-index: 999999;background: rgba(0, 0, 0,.8);font-size: 13px;'; + "max-width:60%;min-width: 80px;padding:0 12px;height: 32px;color: rgb(255, 255, 255);line-height: 32px;text-align: center;border-radius: 8px;position: fixed; bottom:24px;right: 28px;z-index: 999999;background: rgba(0, 0, 0,.8);font-size: 13px;"; document.body.appendChild(m); setTimeout(function () { const d = 0.5; - m.style.transition = 'transform ' + d + 's ease-in, opacity ' + d + 's ease-in'; - m.style.opacity = '0'; + m.style.transition = + "transform " + d + "s ease-in, opacity " + d + "s ease-in"; + m.style.opacity = "0"; setTimeout(function () { document.body.removeChild(m); }, d * 1000); diff --git a/src-tauri/src/inject/event.js b/src-tauri/src/inject/event.js index 1691d26..957ee56 100644 --- a/src-tauri/src/inject/event.js +++ b/src-tauri/src/inject/event.js @@ -1,32 +1,32 @@ const shortcuts = { - '[': () => window.history.back(), - ']': () => window.history.forward(), - '-': () => zoomOut(), - '=': () => zoomIn(), - '+': () => zoomIn(), - 0: () => setZoom('100%'), + "[": () => window.history.back(), + "]": () => window.history.forward(), + "-": () => zoomOut(), + "=": () => zoomIn(), + "+": () => zoomIn(), + 0: () => setZoom("100%"), r: () => window.location.reload(), ArrowUp: () => scrollTo(0, 0), ArrowDown: () => scrollTo(0, document.body.scrollHeight), }; function setZoom(zoom) { - const html = document.getElementsByTagName('html')[0]; + const html = document.getElementsByTagName("html")[0]; html.style.zoom = zoom; - window.localStorage.setItem('htmlZoom', zoom); + window.localStorage.setItem("htmlZoom", zoom); } function zoomCommon(zoomChange) { - const currentZoom = window.localStorage.getItem('htmlZoom') || '100%'; + const currentZoom = window.localStorage.getItem("htmlZoom") || "100%"; setZoom(zoomChange(currentZoom)); } function zoomIn() { - zoomCommon(currentZoom => `${Math.min(parseInt(currentZoom) + 10, 200)}%`); + zoomCommon((currentZoom) => `${Math.min(parseInt(currentZoom) + 10, 200)}%`); } function zoomOut() { - zoomCommon(currentZoom => `${Math.max(parseInt(currentZoom) - 10, 30)}%`); + zoomCommon((currentZoom) => `${Math.max(parseInt(currentZoom) - 10, 30)}%`); } function handleShortcut(event) { @@ -47,42 +47,45 @@ function isDownloadLink(url) { 'svg', 'swf', 'tar', 'tif', 'tiff', 'ts', 'txt', 'wav', 'webm', 'webp', 'wma', 'wmv', 'xls', 'xlsx', 'xml', 'zip', 'json', 'yaml', '7zip', 'mkv', ]; - const downloadLinkPattern = new RegExp(`\\.(${fileExtensions.join('|')})$`, 'i'); + const downloadLinkPattern = new RegExp( + `\\.(${fileExtensions.join("|")})$`, + "i", + ); return downloadLinkPattern.test(url); } -document.addEventListener('DOMContentLoaded', () => { +document.addEventListener("DOMContentLoaded", () => { const tauri = window.__TAURI__; const appWindow = tauri.window.getCurrentWindow(); const invoke = tauri.core.invoke; - if (!document.getElementById('pake-top-dom')) { - const topDom = document.createElement('div'); - topDom.id = 'pake-top-dom'; + if (!document.getElementById("pake-top-dom")) { + const topDom = document.createElement("div"); + topDom.id = "pake-top-dom"; document.body.appendChild(topDom); } - const domEl = document.getElementById('pake-top-dom'); + const domEl = document.getElementById("pake-top-dom"); - domEl.addEventListener('touchstart', () => { + domEl.addEventListener("touchstart", () => { appWindow.startDragging(); }); - domEl.addEventListener('mousedown', e => { + domEl.addEventListener("mousedown", (e) => { e.preventDefault(); if (e.buttons === 1 && e.detail !== 2) { appWindow.startDragging(); } }); - domEl.addEventListener('dblclick', () => { - appWindow.isFullscreen().then(fullscreen => { + domEl.addEventListener("dblclick", () => { + appWindow.isFullscreen().then((fullscreen) => { appWindow.setFullscreen(!fullscreen); }); }); - if (window['pakeConfig']?.disabled_web_shortcuts !== true) { - document.addEventListener('keyup', event => { + if (window["pakeConfig"]?.disabled_web_shortcuts !== true) { + document.addEventListener("keyup", (event) => { if (/windows|linux/i.test(navigator.userAgent) && event.ctrlKey) { handleShortcut(event); } @@ -96,7 +99,7 @@ document.addEventListener('DOMContentLoaded', () => { function collectUrlToBlobs() { const backupCreateObjectURL = window.URL.createObjectURL; window.blobToUrlCaches = new Map(); - window.URL.createObjectURL = blob => { + window.URL.createObjectURL = (blob) => { const url = backupCreateObjectURL.call(window.URL, blob); window.blobToUrlCaches.set(url, blob); return url; @@ -104,7 +107,7 @@ document.addEventListener('DOMContentLoaded', () => { } function convertBlobUrlToBinary(blobUrl) { - return new Promise(resolve => { + return new Promise((resolve) => { const blob = window.blobToUrlCaches.get(blobUrl); const reader = new FileReader(); @@ -116,7 +119,7 @@ document.addEventListener('DOMContentLoaded', () => { } function downloadFromDataUri(dataURI, filename) { - const byteString = atob(dataURI.split(',')[1]); + const byteString = atob(dataURI.split(",")[1]); // write the bytes of the string to an ArrayBuffer const bufferArray = new ArrayBuffer(byteString.length); @@ -129,7 +132,7 @@ document.addEventListener('DOMContentLoaded', () => { } // write the ArrayBuffer to a binary, and you're done - invoke('download_file_by_binary', { + invoke("download_file_by_binary", { params: { filename, binary: Array.from(binary), @@ -138,8 +141,8 @@ document.addEventListener('DOMContentLoaded', () => { } function downloadFromBlobUrl(blobUrl, filename) { - convertBlobUrlToBinary(blobUrl).then(binary => { - invoke('download_file_by_binary', { + convertBlobUrlToBinary(blobUrl).then((binary) => { + invoke("download_file_by_binary", { params: { filename, binary, @@ -151,20 +154,20 @@ document.addEventListener('DOMContentLoaded', () => { // detect blob download by createElement("a") function detectDownloadByCreateAnchor() { const createEle = document.createElement; - document.createElement = el => { - if (el !== 'a') return createEle.call(document, el); + document.createElement = (el) => { + if (el !== "a") return createEle.call(document, el); const anchorEle = createEle.call(document, el); // use addEventListener to avoid overriding the original click event. anchorEle.addEventListener( - 'click', - e => { + "click", + (e) => { const url = anchorEle.href; const filename = anchorEle.download || getFilenameFromUrl(url); if (window.blobToUrlCaches.has(url)) { downloadFromBlobUrl(url, filename); // case: download from dataURL -> convert dataURL -> - } else if (url.startsWith('data:')) { + } else if (url.startsWith("data:")) { downloadFromDataUri(url, filename); } }, @@ -176,12 +179,14 @@ document.addEventListener('DOMContentLoaded', () => { } // process special download protocol['data:','blob:'] - const isSpecialDownload = url => ['blob', 'data'].some(protocol => url.startsWith(protocol)); + const isSpecialDownload = (url) => + ["blob", "data"].some((protocol) => url.startsWith(protocol)); - const isDownloadRequired = (url, anchorElement, e) => anchorElement.download || e.metaKey || e.ctrlKey || isDownloadLink(url); + const isDownloadRequired = (url, anchorElement, e) => + anchorElement.download || e.metaKey || e.ctrlKey || isDownloadLink(url); - const handleExternalLink = url => { - invoke('plugin:shell|open', { + const handleExternalLink = (url) => { + invoke("plugin:shell|open", { path: url, }); }; @@ -191,23 +196,25 @@ document.addEventListener('DOMContentLoaded', () => { try { const linkUrl = new URL(url); const currentUrl = new URL(window.location.href); - + if (linkUrl.hostname === currentUrl.hostname) return true; - + // Extract root domain (e.g., bilibili.com from www.bilibili.com) const getRootDomain = (hostname) => { - const parts = hostname.split('.'); - return parts.length >= 2 ? parts.slice(-2).join('.') : hostname; + const parts = hostname.split("."); + return parts.length >= 2 ? parts.slice(-2).join(".") : hostname; }; - - return getRootDomain(currentUrl.hostname) === getRootDomain(linkUrl.hostname); + + return ( + getRootDomain(currentUrl.hostname) === getRootDomain(linkUrl.hostname) + ); } catch (e) { return false; } }; - const detectAnchorElementClick = e => { - const anchorElement = e.target.closest('a'); + const detectAnchorElementClick = (e) => { + const anchorElement = e.target.closest("a"); if (anchorElement && anchorElement.href) { const target = anchorElement.target; @@ -216,39 +223,52 @@ document.addEventListener('DOMContentLoaded', () => { let filename = anchorElement.download || getFilenameFromUrl(absoluteUrl); // Handle _blank links: same domain navigates in-app, cross-domain opens new window - if (target === '_blank') { + if (target === "_blank") { e.preventDefault(); e.stopImmediatePropagation(); - + if (isSameDomain(absoluteUrl)) { window.location.href = absoluteUrl; } else { - const newWindow = originalWindowOpen.call(window, absoluteUrl, '_blank', 'width=1200,height=800,scrollbars=yes,resizable=yes'); + const newWindow = originalWindowOpen.call( + window, + absoluteUrl, + "_blank", + "width=1200,height=800,scrollbars=yes,resizable=yes", + ); if (!newWindow) handleExternalLink(absoluteUrl); } return; } - if (target === '_new') { + if (target === "_new") { e.preventDefault(); handleExternalLink(absoluteUrl); return; } // Process download links for Rust to handle. - if (isDownloadRequired(absoluteUrl, anchorElement, e) && !isSpecialDownload(absoluteUrl)) { + if ( + isDownloadRequired(absoluteUrl, anchorElement, e) && + !isSpecialDownload(absoluteUrl) + ) { e.preventDefault(); e.stopImmediatePropagation(); - invoke('download_file', { params: { url: absoluteUrl, filename } }); + invoke("download_file", { params: { url: absoluteUrl, filename } }); return; } // Handle regular links: same domain allows normal navigation, cross-domain opens new window - if (!target || target === '_self') { + if (!target || target === "_self") { if (!isSameDomain(absoluteUrl)) { e.preventDefault(); e.stopImmediatePropagation(); - const newWindow = originalWindowOpen.call(window, absoluteUrl, '_blank', 'width=1200,height=800,scrollbars=yes,resizable=yes'); + const newWindow = originalWindowOpen.call( + window, + absoluteUrl, + "_blank", + "width=1200,height=800,scrollbars=yes,resizable=yes", + ); if (!newWindow) handleExternalLink(absoluteUrl); } } @@ -256,7 +276,7 @@ document.addEventListener('DOMContentLoaded', () => { }; // Prevent some special websites from executing in advance, before the click event is triggered. - document.addEventListener('click', detectAnchorElementClick, true); + document.addEventListener("click", detectAnchorElementClick, true); collectUrlToBlobs(); detectDownloadByCreateAnchor(); @@ -265,20 +285,28 @@ document.addEventListener('DOMContentLoaded', () => { const originalWindowOpen = window.open; window.open = function (url, name, specs) { // Apple login and google login - if (name === 'AppleAuthentication') { + if (name === "AppleAuthentication") { //do nothing - } else if (specs && (specs.includes('height=') || specs.includes('width='))) { + } else if ( + specs && + (specs.includes("height=") || specs.includes("width=")) + ) { location.href = url; } else { const baseUrl = window.location.origin + window.location.pathname; const hrefUrl = new URL(url, baseUrl); const absoluteUrl = hrefUrl.href; - + // Apply same domain logic as anchor links if (isSameDomain(absoluteUrl)) { // Same domain: navigate in app or open new window based on specs - if (name === '_blank' || !name) { - return originalWindowOpen.call(window, absoluteUrl, '_blank', 'width=1200,height=800,scrollbars=yes,resizable=yes'); + if (name === "_blank" || !name) { + return originalWindowOpen.call( + window, + absoluteUrl, + "_blank", + "width=1200,height=800,scrollbars=yes,resizable=yes", + ); } else { location.href = absoluteUrl; } @@ -300,27 +328,27 @@ document.addEventListener('DOMContentLoaded', () => { // Fix Chinese input method "Enter" on Safari document.addEventListener( - 'keydown', - e => { + "keydown", + (e) => { if (e.keyCode === 229) e.stopPropagation(); }, true, ); }); -document.addEventListener('DOMContentLoaded', function () { - let permVal = 'granted'; +document.addEventListener("DOMContentLoaded", function () { + let permVal = "granted"; window.Notification = function (title, options) { const { invoke } = window.__TAURI__.core; - const body = options?.body || ''; - let icon = options?.icon || ''; + const body = options?.body || ""; + let icon = options?.icon || ""; // If the icon is a relative path, convert to full path using URI - if (icon.startsWith('/')) { + if (icon.startsWith("/")) { icon = window.location.origin + icon; } - invoke('send_notification', { + invoke("send_notification", { params: { title, body, @@ -329,19 +357,19 @@ document.addEventListener('DOMContentLoaded', function () { }); }; - window.Notification.requestPermission = async () => 'granted'; + window.Notification.requestPermission = async () => "granted"; - Object.defineProperty(window.Notification, 'permission', { + Object.defineProperty(window.Notification, "permission", { enumerable: true, get: () => permVal, - set: v => { + set: (v) => { permVal = v; }, }); }); function setDefaultZoom() { - const htmlZoom = window.localStorage.getItem('htmlZoom'); + const htmlZoom = window.localStorage.getItem("htmlZoom"); if (htmlZoom) { setZoom(htmlZoom); } @@ -349,5 +377,5 @@ function setDefaultZoom() { function getFilenameFromUrl(url) { const urlPath = new URL(url).pathname; - return urlPath.substring(urlPath.lastIndexOf('/') + 1); + return urlPath.substring(urlPath.lastIndexOf("/") + 1); } diff --git a/src-tauri/src/inject/style.js b/src-tauri/src/inject/style.js index e481a7d..4f141bb 100644 --- a/src-tauri/src/inject/style.js +++ b/src-tauri/src/inject/style.js @@ -1,4 +1,4 @@ -window.addEventListener('DOMContentLoaded', _event => { +window.addEventListener("DOMContentLoaded", (_event) => { // Customize and transform existing functions const contentCSS = ` #page #footer-wrapper, @@ -293,7 +293,7 @@ window.addEventListener('DOMContentLoaded', _event => { margin-top: 15px; } `; - const contentStyleElement = document.createElement('style'); + const contentStyleElement = document.createElement("style"); contentStyleElement.innerHTML = contentCSS; document.head.appendChild(contentStyleElement); @@ -317,7 +317,7 @@ window.addEventListener('DOMContentLoaded', _event => { } #root > .excalidraw-app> .excalidraw-container .App-menu.App-menu_top{ - margin-top: 15px; + margin-top: 15px; } .geist-page nav.dashboard_nav__PRmJv, @@ -361,7 +361,7 @@ window.addEventListener('DOMContentLoaded', _event => { } body > div.relative.flex.h-full.w-full.overflow-hidden.transition-colors.z-0 > div.z-\\[21\\].flex-shrink-0.overflow-x-hidden.bg-token-sidebar-surface-primary.max-md\\:\\!w-0 > div > div > div > nav > div.flex.justify-between.h-\\[60px\\].items-center.md\\:h-header-height { - padding-top: 25px; + padding-top: 25px; } body > div.relative.flex.h-full.w-full.overflow-hidden.transition-colors.z-0 > div.relative.flex.h-full.max-w-full.flex-1.flex-col.overflow-hidden > main > div.composer-parent.flex.h-full.flex-col.focus-visible\\:outline-0 > div.flex-1.overflow-hidden.\\@container\\/thread > div > div.absolute.left-0.right-0 > div{ @@ -457,9 +457,9 @@ window.addEventListener('DOMContentLoaded', _event => { } } `; - const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0; - if (window['pakeConfig']?.hide_title_bar && isMac) { - const topPaddingStyleElement = document.createElement('style'); + const isMac = navigator.platform.toUpperCase().indexOf("MAC") >= 0; + if (window["pakeConfig"]?.hide_title_bar && isMac) { + const topPaddingStyleElement = document.createElement("style"); topPaddingStyleElement.innerHTML = topPaddingCSS; document.head.appendChild(topPaddingStyleElement); } diff --git a/src-tauri/tauri.linux.conf.json b/src-tauri/tauri.linux.conf.json index 11a0fd3..3937c2e 100644 --- a/src-tauri/tauri.linux.conf.json +++ b/src-tauri/tauri.linux.conf.json @@ -6,7 +6,9 @@ "linux": { "deb": { "depends": ["curl", "wget"], - "files": { "/usr/share/applications/com-pake-weread.desktop": "assets/com-pake-weread.desktop" } + "files": { + "/usr/share/applications/com-pake-weread.desktop": "assets/com-pake-weread.desktop" + } } }, "targets": ["deb", "appimage"] diff --git a/tsconfig.json b/tsconfig.json index c8d6d40..2b52639 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,13 +2,8 @@ "compilerOptions": { "module": "ESNext", "target": "es2020", - "types": [ - "node" - ], - "lib": [ - "es2020", - "dom" - ], + "types": ["node"], + "lib": ["es2020", "dom"], "esModuleInterop": true, "resolveJsonModule": true, "allowSyntheticDefaultImports": true, @@ -18,12 +13,8 @@ "outDir": "dist", "baseUrl": ".", "paths": { - "@/*": [ - "bin/*" - ] + "@/*": ["bin/*"] } }, - "include": [ - "bin/**/*" - ] + "include": ["bin/**/*"] }