🎨 Optimize the code structure

This commit is contained in:
Tw93
2023-08-04 15:58:08 +08:00
parent c89b65694f
commit 1ac67605ba
13 changed files with 579 additions and 568 deletions

View File

@@ -228,6 +228,13 @@ Pake 的发展离不开这些 Hacker 们,一起贡献了大量能力,也欢
<sub><b>Pan93412</b></sub> <sub><b>Pan93412</b></sub>
</a> </a>
</td> </td>
<td align="center">
<a href="https://github.com/jeasonnow">
<img src="https://avatars.githubusercontent.com/u/16950207?v=4" width="90;" alt="jeasonnow"/>
<br />
<sub><b>Santree</b></sub>
</a>
</td>
<td align="center"> <td align="center">
<a href="https://github.com/wanghanzhen"> <a href="https://github.com/wanghanzhen">
<img src="https://avatars.githubusercontent.com/u/25301012?v=4" width="90;" alt="wanghanzhen"/> <img src="https://avatars.githubusercontent.com/u/25301012?v=4" width="90;" alt="wanghanzhen"/>
@@ -248,15 +255,15 @@ Pake 的发展离不开这些 Hacker 们,一起贡献了大量能力,也欢
<br /> <br />
<sub><b>Essesoul</b></sub> <sub><b>Essesoul</b></sub>
</a> </a>
</td> </td></tr>
<tr>
<td align="center"> <td align="center">
<a href="https://github.com/AielloChan"> <a href="https://github.com/AielloChan">
<img src="https://avatars.githubusercontent.com/u/7900765?v=4" width="90;" alt="AielloChan"/> <img src="https://avatars.githubusercontent.com/u/7900765?v=4" width="90;" alt="AielloChan"/>
<br /> <br />
<sub><b>Aiello</b></sub> <sub><b>Aiello</b></sub>
</a> </a>
</td></tr> </td>
<tr>
<td align="center"> <td align="center">
<a href="https://github.com/m1911star"> <a href="https://github.com/m1911star">
<img src="https://avatars.githubusercontent.com/u/4948120?v=4" width="90;" alt="m1911star"/> <img src="https://avatars.githubusercontent.com/u/4948120?v=4" width="90;" alt="m1911star"/>
@@ -271,13 +278,6 @@ Pake 的发展离不开这些 Hacker 们,一起贡献了大量能力,也欢
<sub><b>Pake Actions</b></sub> <sub><b>Pake Actions</b></sub>
</a> </a>
</td> </td>
<td align="center">
<a href="https://github.com/jeasonnow">
<img src="https://avatars.githubusercontent.com/u/16950207?v=4" width="90;" alt="jeasonnow"/>
<br />
<sub><b>Santree</b></sub>
</a>
</td>
<td align="center"> <td align="center">
<a href="https://github.com/QingZ11"> <a href="https://github.com/QingZ11">
<img src="https://avatars.githubusercontent.com/u/38887077?v=4" width="90;" alt="QingZ11"/> <img src="https://avatars.githubusercontent.com/u/38887077?v=4" width="90;" alt="QingZ11"/>
@@ -328,6 +328,13 @@ Pake 的发展离不开这些 Hacker 们,一起贡献了大量能力,也欢
<sub><b>Fechin</b></sub> <sub><b>Fechin</b></sub>
</a> </a>
</td> </td>
<td align="center">
<a href="https://github.com/Milo123459">
<img src="https://avatars.githubusercontent.com/u/50248166?v=4" width="90;" alt="Milo123459"/>
<br />
<sub><b>Milo</b></sub>
</a>
</td>
<td align="center"> <td align="center">
<a href="https://github.com/princemaple"> <a href="https://github.com/princemaple">
<img src="https://avatars.githubusercontent.com/u/1329716?v=4" width="90;" alt="princemaple"/> <img src="https://avatars.githubusercontent.com/u/1329716?v=4" width="90;" alt="princemaple"/>
@@ -348,15 +355,15 @@ Pake 的发展离不开这些 Hacker 们,一起贡献了大量能力,也欢
<br /> <br />
<sub><b>Null</b></sub> <sub><b>Null</b></sub>
</a> </a>
</td> </td></tr>
<tr>
<td align="center"> <td align="center">
<a href="https://github.com/liusishan"> <a href="https://github.com/liusishan">
<img src="https://avatars.githubusercontent.com/u/33129823?v=4" width="90;" alt="liusishan"/> <img src="https://avatars.githubusercontent.com/u/33129823?v=4" width="90;" alt="liusishan"/>
<br /> <br />
<sub><b>Liusishan</b></sub> <sub><b>Liusishan</b></sub>
</a> </a>
</td></tr> </td>
<tr>
<td align="center"> <td align="center">
<a href="https://github.com/piaoyidage"> <a href="https://github.com/piaoyidage">
<img src="https://avatars.githubusercontent.com/u/5135405?v=4" width="90;" alt="piaoyidage"/> <img src="https://avatars.githubusercontent.com/u/5135405?v=4" width="90;" alt="piaoyidage"/>

4
bin/cli.ts vendored
View File

@@ -38,8 +38,8 @@ program
.option('--iter-copy-file', 'Copy files when URL is a local file', DEFAULT.iterCopyFile) .option('--iter-copy-file', 'Copy files when URL is a local file', DEFAULT.iterCopyFile)
.option('--multi-arch', 'Only for Mac, supports both Intel and M1', DEFAULT.multiArch) .option('--multi-arch', 'Only for Mac, supports both Intel and M1', DEFAULT.multiArch)
.option('--targets <string>', 'Only for Linux, option "deb" or "appimage"', DEFAULT.targets) .option('--targets <string>', 'Only for Linux, option "deb" or "appimage"', DEFAULT.targets)
.option('--inject [injects...]', 'Inject .js or .css for this app', DEFAULT.inject) .option('--inject [injects...]', 'Injection of .js or .css Files', DEFAULT.inject)
.option('--safe-domain [domains...]', 'Please enter the security domains that need to be configured', DEFAULT.safeDomain) .option('--safe-domain [domains...]', 'Domains that Require Security Configuration"', DEFAULT.safeDomain)
.option('--debug', 'Debug mode', DEFAULT.debug) .option('--debug', 'Debug mode', DEFAULT.debug)
.version(packageJson.version, '-v, --version', 'Output the current version') .version(packageJson.version, '-v, --version', 'Output the current version')
.action(async (url: string, options: PakeCliOptions) => { .action(async (url: string, options: PakeCliOptions) => {

8
bin/defaults.ts vendored
View File

@@ -19,9 +19,11 @@ export const DEFAULT_PAKE_OPTIONS: PakeCliOptions = {
safeDomain: [], safeDomain: [],
}; };
// just for cli development // Just for cli development
export const DEFAULT_DEV_PAKE_OPTIONS: PakeCliOptions & {url: string} = { export const DEFAULT_DEV_PAKE_OPTIONS: PakeCliOptions & {url: string} = {
...DEFAULT_PAKE_OPTIONS, ...DEFAULT_PAKE_OPTIONS,
url: 'https://weread.qq.com', url: 'https://weread.qq.com',
name: 'Weread', name: 'WeRead',
} safeDomain:['weread.qq.com'],
transparent: true,
}

716
dist/cli.js vendored
View File

@@ -1,307 +1,313 @@
import chalk from 'chalk'; import chalk from 'chalk';
import { InvalidArgumentError, program } from 'commander'; import { InvalidArgumentError, program } from 'commander';
import log from 'loglevel'; import log from 'loglevel';
import path from 'path'; import path from 'path';
import fsExtra from 'fs-extra'; import fsExtra from 'fs-extra';
import prompts from 'prompts'; import prompts from 'prompts';
import shelljs from 'shelljs'; import shelljs from 'shelljs';
import crypto from 'crypto'; import crypto from 'crypto';
import ora from 'ora'; import ora from 'ora';
import { fileURLToPath } from 'url'; import { fileURLToPath } from 'url';
import dns from 'dns'; import dns from 'dns';
import http from 'http'; import http from 'http';
import { promisify } from 'util'; import { promisify } from 'util';
import updateNotifier from 'update-notifier'; import fs from 'fs';
import axios from 'axios'; import updateNotifier from 'update-notifier';
import { dir } from 'tmp-promise'; import axios from 'axios';
import { fileTypeFromBuffer } from 'file-type'; import { dir } from 'tmp-promise';
import psl from 'psl'; import { fileTypeFromBuffer } from 'file-type';
import isUrl from 'is-url'; import psl from 'psl';
import fs from 'fs'; import isUrl from 'is-url';
var name = "pake-cli"; var name = "pake-cli";
var version = "2.2.5"; var version = "2.2.5";
var description = "🤱🏻 Turn any webpage into a desktop app with Rust. 🤱🏻 很简单的用 Rust 打包网页生成很小的桌面 App。"; var description = "🤱🏻 Turn any webpage into a desktop app with Rust. 🤱🏻 用 Rust 轻松构建轻量级多端桌面应用。";
var engines = { var engines = {
node: ">=16.0.0" node: ">=16.0.0"
}; };
var bin = { var bin = {
pake: "./cli.js" pake: "./cli.js"
}; };
var repository = { var repository = {
type: "git", type: "git",
url: "https://github.com/tw93/pake.git" url: "https://github.com/tw93/pake.git"
}; };
var author = { var author = {
name: "Tw93", name: "Tw93",
email: "tw93@qq.com" email: "tw93@qq.com"
}; };
var keywords = [ var keywords = [
"pake", "pake",
"pake-cli", "pake-cli",
"rust", "rust",
"tauri", "tauri",
"no-electron", "no-electron",
"productivity" "productivity"
]; ];
var files = [ var files = [
"dist", "dist",
"src-tauri", "src-tauri",
"cli.js" "cli.js"
]; ];
var scripts = { var scripts = {
start: "npm run dev", start: "npm run dev",
dev: "npm run tauri dev", dev: "npm run tauri dev",
build: "npm run tauri build --release", build: "npm run tauri build --release",
"build:mac": "npm run tauri build -- --target universal-apple-darwin", "build:debug": "npm run tauri build -- --debug",
"build:all-unix": "chmod +x ./script/build.sh && ./script/build.sh", "build:mac": "npm run tauri build -- --target universal-apple-darwin",
"build:all-windows": "pwsh ./script/build.ps1", "build:all-unix": "chmod +x ./script/build.sh && ./script/build.sh",
analyze: "cd src-tauri && cargo bloat --release --crates", "build:all-windows": "pwsh ./script/build.ps1",
tauri: "tauri", analyze: "cd src-tauri && cargo bloat --release --crates",
cli: "rollup -c rollup.config.js --watch", tauri: "tauri",
"cli:build": "cross-env NODE_ENV=production rollup -c rollup.config.js", cli: "rollup -c rollup.config.js --watch",
prepublishOnly: "npm run cli:build" "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",
var type = "module"; prepublishOnly: "npm run cli:build"
var exports = "./dist/pake.js"; };
var license = "MIT"; var type = "module";
var dependencies = { var exports = "./dist/pake.js";
"@tauri-apps/api": "^1.4.0", var license = "MIT";
"@tauri-apps/cli": "^1.4.0", var dependencies = {
axios: "^1.1.3", "@tauri-apps/api": "^1.4.0",
chalk: "^5.1.2", "@tauri-apps/cli": "^1.4.0",
commander: "^11.0.0", axios: "^1.1.3",
"file-type": "^18.0.0", chalk: "^5.1.2",
"fs-extra": "^11.1.0", commander: "^11.0.0",
"is-url": "^1.2.4", "file-type": "^18.0.0",
loglevel: "^1.8.1", "fs-extra": "^11.1.0",
ora: "^6.1.2", "is-url": "^1.2.4",
prompts: "^2.4.2", loglevel: "^1.8.1",
psl: "^1.9.0", ora: "^6.1.2",
shelljs: "^0.8.5", prompts: "^2.4.2",
"tmp-promise": "^3.0.3", psl: "^1.9.0",
"update-notifier": "^6.0.2" shelljs: "^0.8.5",
}; "tmp-promise": "^3.0.3",
var devDependencies = { "update-notifier": "^6.0.2"
"@rollup/plugin-alias": "^4.0.2", };
"@rollup/plugin-commonjs": "^23.0.2", var devDependencies = {
"@rollup/plugin-json": "^5.0.2", "@rollup/plugin-alias": "^4.0.2",
"@rollup/plugin-terser": "^0.1.0", "@rollup/plugin-commonjs": "^23.0.2",
"@types/fs-extra": "^9.0.13", "@rollup/plugin-json": "^5.0.2",
"@types/is-url": "^1.2.30", "@rollup/plugin-replace": "^5.0.2",
"@types/page-icon": "^0.3.4", "@rollup/plugin-terser": "^0.1.0",
"@types/prompts": "^2.4.1", "@types/fs-extra": "^9.0.13",
"@types/psl": "^1.1.0", "@types/is-url": "^1.2.30",
"@types/shelljs": "^0.8.11", "@types/page-icon": "^0.3.4",
"@types/tmp": "^0.2.3", "@types/prompts": "^2.4.1",
"@types/update-notifier": "^6.0.1", "@types/psl": "^1.1.0",
"app-root-path": "^3.1.0", "@types/shelljs": "^0.8.11",
"cross-env": "^7.0.3", "@types/tmp": "^0.2.3",
rollup: "^3.3.0", "@types/update-notifier": "^6.0.1",
"rollup-plugin-typescript2": "^0.34.1", "app-root-path": "^3.1.0",
tslib: "^2.4.1", "cross-env": "^7.0.3",
typescript: "^4.9.3" rollup: "^3.3.0",
}; "rollup-plugin-typescript2": "^0.34.1",
var packageJson = { tslib: "^2.4.1",
name: name, typescript: "^4.9.3"
version: version, };
description: description, var packageJson = {
engines: engines, name: name,
bin: bin, version: version,
repository: repository, description: description,
author: author, engines: engines,
keywords: keywords, bin: bin,
files: files, repository: repository,
scripts: scripts, author: author,
type: type, keywords: keywords,
exports: exports, files: files,
license: license, scripts: scripts,
dependencies: dependencies, type: type,
devDependencies: devDependencies exports: exports,
}; license: license,
dependencies: dependencies,
var windows = [ devDependencies: devDependencies
{ };
url: "https://weread.qq.com/",
transparent: true, var windows = [
fullscreen: false, {
width: 1200, url: "https://weread.qq.com/",
height: 780, transparent: true,
resizable: true, fullscreen: false,
url_type: "web" width: 1200,
} height: 780,
]; resizable: true,
var user_agent = { url_type: "web"
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 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",
var menu = { linux: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36",
macos: true, windows: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
linux: false, };
windows: false var menu = {
}; macos: false,
var system_tray = { linux: false,
macos: false, windows: false
linux: true, };
windows: true var system_tray = {
}; macos: false,
var pakeConf = { linux: true,
windows: windows, windows: true
user_agent: user_agent, };
menu: menu, var inject = [
system_tray: system_tray ];
}; var pakeConf = {
windows: windows,
var tauri$3 = { user_agent: user_agent,
security: { menu: menu,
csp: null, system_tray: system_tray,
dangerousRemoteDomainIpcAccess: [ inject: inject
{ };
domain: "weread.qq.com",
windows: [ var tauri$3 = {
"pake" security: {
], csp: null,
enableTauriAPI: true dangerousRemoteDomainIpcAccess: [
} {
] domain: "weread.qq.com",
}, windows: [
updater: { "pake"
active: false ],
}, enableTauriAPI: true
systemTray: { }
iconPath: "png/weread_512.png", ]
iconAsTemplate: true },
}, updater: {
allowlist: { active: false
all: true, },
fs: { systemTray: {
all: true, iconPath: "png/icon_512.png",
scope: [ iconAsTemplate: true
"$DOWNLOAD/*" },
] allowlist: {
} all: true,
} fs: {
}; all: true,
var build = { scope: [
withGlobalTauri: true, "$DOWNLOAD/*"
devPath: "../dist", ]
distDir: "../dist", }
beforeBuildCommand: "", }
beforeDevCommand: "" };
}; var build = {
var CommonConf = { withGlobalTauri: true,
"package": { devPath: "../dist",
productName: "WeRead", distDir: "../dist",
version: "1.0.0" beforeBuildCommand: "",
}, beforeDevCommand: ""
tauri: tauri$3, };
build: build var CommonConf = {
}; "package": {
productName: "WeRead",
var tauri$2 = { version: "1.0.0"
bundle: { },
icon: [ tauri: tauri$3,
"png/weread_256.ico", build: build
"png/weread_32.ico" };
],
identifier: "com.pake.weread", var tauri$2 = {
active: true, bundle: {
category: "DeveloperTool", icon: [
copyright: "", "png/weread_256.ico",
externalBin: [ "png/weread_32.ico"
], ],
longDescription: "", identifier: "com.pake.weread",
resources: [ active: true,
"png/weread_32.ico" category: "DeveloperTool",
], copyright: "",
shortDescription: "", externalBin: [
targets: [ ],
"msi" longDescription: "",
], resources: [
windows: { "png/weread_32.ico"
certificateThumbprint: null, ],
digestAlgorithm: "sha256", shortDescription: "",
timestampUrl: "", targets: [
wix: { "msi"
language: [ ],
"en-US" windows: {
], certificateThumbprint: null,
template: "assets/main.wxs" digestAlgorithm: "sha256",
} timestampUrl: "",
} wix: {
} language: [
}; "en-US"
var WinConf = { ],
tauri: tauri$2 template: "assets/main.wxs"
}; }
}
var tauri$1 = { }
bundle: { };
icon: [ var WinConf = {
"icons/weread.icns" tauri: tauri$2
], };
identifier: "com.pake.weread",
active: true, var tauri$1 = {
category: "DeveloperTool", bundle: {
copyright: "", icon: [
externalBin: [ "icons/weread.icns"
], ],
longDescription: "", identifier: "com.pake.weread",
macOS: { active: true,
entitlements: null, category: "DeveloperTool",
exceptionDomain: "", copyright: "",
frameworks: [ externalBin: [
], ],
providerShortName: null, longDescription: "",
signingIdentity: null macOS: {
}, entitlements: null,
resources: [ exceptionDomain: "",
], frameworks: [
shortDescription: "", ],
targets: [ providerShortName: null,
"dmg" signingIdentity: null
] },
} resources: [
}; ],
var MacConf = { shortDescription: "",
tauri: tauri$1 targets: [
}; "dmg"
]
var tauri = { }
bundle: { };
icon: [ var MacConf = {
"png/weread_512.png" tauri: tauri$1
], };
identifier: "com.pake.weread",
active: true, var tauri = {
category: "DeveloperTool", bundle: {
copyright: "", icon: [
deb: { "png/weread_512.png"
depends: [ ],
"curl", identifier: "com.pake.weread",
"wget" active: true,
], category: "DeveloperTool",
files: { copyright: "",
"/usr/share/applications/com-pake-weread.desktop": "assets/com-pake-weread.desktop" deb: {
} depends: [
}, "curl",
externalBin: [ "wget"
], ],
longDescription: "", files: {
resources: [ "/usr/share/applications/com-pake-weread.desktop": "assets/com-pake-weread.desktop"
], }
shortDescription: "", },
targets: [ externalBin: [
"deb", ],
"appimage" longDescription: "",
] resources: [
} ],
}; shortDescription: "",
var LinuxConf = { targets: [
tauri: tauri "deb",
}; "appimage"
]
}
};
var LinuxConf = {
tauri: tauri
};
const platformConfigs = { const platformConfigs = {
win32: WinConf, win32: WinConf,
darwin: MacConf, darwin: MacConf,
@@ -318,8 +324,8 @@ let tauriConfig = {
package: CommonConf.package, package: CommonConf.package,
build: CommonConf.build, build: CommonConf.build,
pake: pakeConf, pake: pakeConf,
}; };
// Generates an identifier based on the given URL. // Generates an identifier based on the given URL.
function getIdentifier(url) { function getIdentifier(url) {
const postFixHash = crypto.createHash('md5').update(url).digest('hex').substring(0, 6); const postFixHash = crypto.createHash('md5').update(url).digest('hex').substring(0, 6);
@@ -347,19 +353,19 @@ function getSpinner(text) {
spinner: loadingType, spinner: loadingType,
color: 'cyan', color: 'cyan',
}).start(); }).start();
} }
const { platform: platform$1 } = process; const { platform: platform$1 } = process;
const IS_MAC = platform$1 === 'darwin'; const IS_MAC = platform$1 === 'darwin';
const IS_WIN = platform$1 === 'win32'; const IS_WIN = platform$1 === 'win32';
const IS_LINUX = platform$1 === 'linux'; const IS_LINUX = platform$1 === 'linux';
// Convert the current module URL to a file path // Convert the current module URL to a file path
const currentModulePath = fileURLToPath(import.meta.url); const currentModulePath = fileURLToPath(import.meta.url);
// Resolve the parent directory of the current module // Resolve the parent directory of the current module
const npmDirectory = path.join(path.dirname(currentModulePath), '..'); const npmDirectory = path.join(path.dirname(currentModulePath), '..');
const tauriConfigDirectory = path.join(npmDirectory, 'src-tauri'); const tauriConfigDirectory = path.join(npmDirectory, 'src-tauri');
function shellExec(command) { function shellExec(command) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
shelljs.exec(command, { async: true, silent: false, cwd: npmDirectory }, code => { shelljs.exec(command, { async: true, silent: false, cwd: npmDirectory }, code => {
@@ -371,8 +377,8 @@ function shellExec(command) {
} }
}); });
}); });
} }
const logger = { const logger = {
info(...msg) { info(...msg) {
log.info(...msg.map(m => chalk.white(m))); log.info(...msg.map(m => chalk.white(m)));
@@ -389,8 +395,8 @@ const logger = {
success(...msg) { success(...msg) {
log.info(...msg.map(m => chalk.green(m))); log.info(...msg.map(m => chalk.green(m)));
}, },
}; };
const resolve = promisify(dns.resolve); const resolve = promisify(dns.resolve);
const ping = async (host) => { const ping = async (host) => {
const lookup = promisify(dns.lookup); const lookup = promisify(dns.lookup);
@@ -434,8 +440,8 @@ async function isChinaIP(ip, domain) {
logger.debug(`ping ${domain} failed!`); logger.debug(`ping ${domain} failed!`);
return true; return true;
} }
} }
async function installRust() { async function installRust() {
const isActions = process.env.GITHUB_ACTIONS; const isActions = process.env.GITHUB_ACTIONS;
const isInChina = await isChinaDomain('sh.rustup.rs'); const isInChina = await isChinaDomain('sh.rustup.rs');
@@ -456,8 +462,8 @@ async function installRust() {
} }
function checkRustInstalled() { function checkRustInstalled() {
return shelljs.exec('rustc --version', { silent: true }).code === 0; return shelljs.exec('rustc --version', { silent: true }).code === 0;
} }
async function combineFiles(files, output) { async function combineFiles(files, output) {
const contents = files.map(file => { const contents = files.map(file => {
const fileContent = fs.readFileSync(file); const fileContent = fs.readFileSync(file);
@@ -468,8 +474,8 @@ async function combineFiles(files, output) {
}); });
fs.writeFileSync(output, contents.join('\n')); fs.writeFileSync(output, contents.join('\n'));
return files; return files;
} }
async function mergeConfig(url, options, tauriConf) { async function mergeConfig(url, options, tauriConf) {
const { width, height, fullscreen, transparent, userAgent, showMenu, showSystemTray, systemTrayIcon, iterCopyFile, identifier, name, resizable = true, inject, safeDomain, } = options; const { width, height, fullscreen, transparent, userAgent, showMenu, showSystemTray, systemTrayIcon, iterCopyFile, identifier, name, resizable = true, inject, safeDomain, } = options;
const { platform } = process; const { platform } = process;
@@ -619,7 +625,7 @@ async function mergeConfig(url, options, tauriConf) {
} }
} }
tauriConf.tauri.systemTray.iconPath = trayIconPath; tauriConf.tauri.systemTray.iconPath = trayIconPath;
const injectFilePath = path.join(npmDirectory, `src-tauri/src/inject/_INJECT_.js`); const injectFilePath = path.join(npmDirectory, `src-tauri/src/inject/custom.js`);
// inject js or css files // inject js or css files
if (inject?.length > 0) { if (inject?.length > 0) {
if (!inject.every(item => item.endsWith('.css') || item.endsWith('.js'))) { if (!inject.every(item => item.endsWith('.css') || item.endsWith('.js'))) {
@@ -650,8 +656,8 @@ async function mergeConfig(url, options, tauriConf) {
delete tauriConf2.tauri.bundle; delete tauriConf2.tauri.bundle;
const configJsonPath = path.join(tauriConfigDirectory, 'tauri.conf.json'); const configJsonPath = path.join(tauriConfigDirectory, 'tauri.conf.json');
await fsExtra.outputJSON(configJsonPath, tauriConf2, { spaces: 4 }); await fsExtra.outputJSON(configJsonPath, tauriConf2, { spaces: 4 });
} }
class BaseBuilder { class BaseBuilder {
constructor(options) { constructor(options) {
this.options = options; this.options = options;
@@ -733,8 +739,8 @@ class BaseBuilder {
getBuildAppPath(npmDirectory, fileName, fileType) { getBuildAppPath(npmDirectory, fileName, fileType) {
return path.join(npmDirectory, this.getBasePath(), fileType.toLowerCase(), `${fileName}.${fileType}`); return path.join(npmDirectory, this.getBasePath(), fileType.toLowerCase(), `${fileName}.${fileType}`);
} }
} }
class MacBuilder extends BaseBuilder { class MacBuilder extends BaseBuilder {
constructor(options) { constructor(options) {
super(options); super(options);
@@ -759,8 +765,8 @@ class MacBuilder extends BaseBuilder {
? 'src-tauri/target/universal-apple-darwin/release/bundle' ? 'src-tauri/target/universal-apple-darwin/release/bundle'
: super.getBasePath(); : super.getBasePath();
} }
} }
class WinBuilder extends BaseBuilder { class WinBuilder extends BaseBuilder {
constructor(options) { constructor(options) {
super(options); super(options);
@@ -772,8 +778,8 @@ class WinBuilder extends BaseBuilder {
const language = tauriConfig.tauri.bundle.windows.wix.language[0]; const language = tauriConfig.tauri.bundle.windows.wix.language[0];
return `${name}_${tauriConfig.package.version}_${arch}_${language}`; return `${name}_${tauriConfig.package.version}_${arch}_${language}`;
} }
} }
class LinuxBuilder extends BaseBuilder { class LinuxBuilder extends BaseBuilder {
constructor(options) { constructor(options) {
super(options); super(options);
@@ -798,8 +804,8 @@ class LinuxBuilder extends BaseBuilder {
} }
return super.getFileType(target); return super.getFileType(target);
} }
} }
const { platform } = process; const { platform } = process;
const buildersMap = { const buildersMap = {
darwin: MacBuilder, darwin: MacBuilder,
@@ -814,8 +820,8 @@ class BuilderProvider {
} }
return new Builder(options); return new Builder(options);
} }
} }
const DEFAULT_PAKE_OPTIONS = { const DEFAULT_PAKE_OPTIONS = {
icon: '', icon: '',
height: 780, height: 780,
@@ -833,12 +839,12 @@ const DEFAULT_PAKE_OPTIONS = {
debug: false, debug: false,
inject: [], inject: [],
safeDomain: [], safeDomain: [],
}; };
async function checkUpdateTips() { async function checkUpdateTips() {
updateNotifier({ pkg: packageJson, updateCheckInterval: 1000 * 60 }).notify({ isGlobal: true }); updateNotifier({ pkg: packageJson, updateCheckInterval: 1000 * 60 }).notify({ isGlobal: true });
} }
async function handleIcon(options) { async function handleIcon(options) {
if (options.icon) { if (options.icon) {
if (options.icon.startsWith('http')) { if (options.icon.startsWith('http')) {
@@ -891,8 +897,8 @@ async function downloadIcon(iconUrl) {
} }
throw error; throw error;
} }
} }
// Extracts the domain from a given URL. // Extracts the domain from a given URL.
function getDomain(inputUrl) { function getDomain(inputUrl) {
try { try {
@@ -930,8 +936,8 @@ function normalizeUrl(urlToNormalize) {
else { else {
throw new Error(`Your url "${urlWithProtocol}" is invalid`); throw new Error(`Your url "${urlWithProtocol}" is invalid`);
} }
} }
function resolveAppName(name, platform) { function resolveAppName(name, platform) {
const domain = getDomain(name) || 'pake'; const domain = getDomain(name) || 'pake';
return platform !== 'linux' ? capitalizeFirstLetter(domain) : domain; return platform !== 'linux' ? capitalizeFirstLetter(domain) : domain;
@@ -975,8 +981,8 @@ async function handleOptions(options, url) {
}; };
appOptions.icon = await handleIcon(appOptions); appOptions.icon = await handleIcon(appOptions);
return appOptions; return appOptions;
} }
function validateNumberInput(value) { function validateNumberInput(value) {
const parsedValue = Number(value); const parsedValue = Number(value);
if (isNaN(parsedValue)) { if (isNaN(parsedValue)) {
@@ -995,14 +1001,14 @@ function validateUrlInput(url) {
} }
} }
return url; return url;
} }
const { green, yellow } = chalk; const { green, yellow } = chalk;
const logo = `${chalk.green(' ____ _')} const logo = `${chalk.green(' ____ _')}
${green('| _ \\ __ _| | _____')} ${green('| _ \\ __ _| | _____')}
${green('| |_) / _` | |/ / _ \\')} ${green('| |_) / _` | |/ / _ \\')}
${green('| __/ (_| | < __/')} ${yellow('https://github.com/tw93/pake')} ${green('| __/ (_| | < __/')} ${yellow('https://github.com/tw93/pake')}
${green('|_| \\__,_|_|\\_\\___| can turn any webpage into a desktop app with Rust.')} ${green('|_| \\__,_|_|\\_\\___| can turn any webpage into a desktop app with Rust.')}
`; `;
program program
.addHelpText('beforeAll', logo) .addHelpText('beforeAll', logo)
@@ -1023,8 +1029,8 @@ program
.option('--iter-copy-file', 'Copy files when URL is a local file', DEFAULT_PAKE_OPTIONS.iterCopyFile) .option('--iter-copy-file', 'Copy files when URL is a local file', DEFAULT_PAKE_OPTIONS.iterCopyFile)
.option('--multi-arch', 'Only for Mac, supports both Intel and M1', DEFAULT_PAKE_OPTIONS.multiArch) .option('--multi-arch', 'Only for Mac, supports both Intel and M1', DEFAULT_PAKE_OPTIONS.multiArch)
.option('--targets <string>', 'Only for Linux, option "deb" or "appimage"', DEFAULT_PAKE_OPTIONS.targets) .option('--targets <string>', 'Only for Linux, option "deb" or "appimage"', DEFAULT_PAKE_OPTIONS.targets)
.option('--inject [injects...]', 'inject .js or .css for this app', DEFAULT_PAKE_OPTIONS.inject) .option('--inject [injects...]', 'Injection of .js or .css Files', DEFAULT_PAKE_OPTIONS.inject)
.option('--safe-domain [domains...]', 'domains that can call window.__TAURI__ and use ipc', DEFAULT_PAKE_OPTIONS.safeDomain) .option('--safe-domain [domains...]', 'Domains that Require Security Configuration"', DEFAULT_PAKE_OPTIONS.safeDomain)
.option('--debug', 'Debug mode', DEFAULT_PAKE_OPTIONS.debug) .option('--debug', 'Debug mode', DEFAULT_PAKE_OPTIONS.debug)
.version(packageJson.version, '-v, --version', 'Output the current version') .version(packageJson.version, '-v, --version', 'Output the current version')
.action(async (url, options) => { .action(async (url, options) => {
@@ -1048,4 +1054,4 @@ program
await builder.prepare(); await builder.prepare();
await builder.build(url); await builder.build(url);
}); });
program.parse(); program.parse();

View File

@@ -1,6 +1,5 @@
import chalk from 'chalk'; import chalk from 'chalk';
import {spawn, exec} from 'child_process'; import { spawn, exec } from 'child_process';
// just run in development mode // just run in development mode
export default function pakeCliDevPlugin() { export default function pakeCliDevPlugin() {
@@ -15,8 +14,8 @@ export default function pakeCliDevPlugin() {
const command = 'node'; const command = 'node';
const cliCmdArgs = ['./dist/dev.js']; const cliCmdArgs = ['./dist/dev.js'];
cliChildProcess = spawn(command, cliCmdArgs, {detached: true}); cliChildProcess = spawn(command, cliCmdArgs, { detached: true });
cliChildProcess.stdout.on('data', (data) => { cliChildProcess.stdout.on('data', (data) => {
console.log(chalk.green(data.toString())); console.log(chalk.green(data.toString()));
@@ -35,7 +34,7 @@ export default function pakeCliDevPlugin() {
devChildProcess.stdout.on('data', (data) => { devChildProcess.stdout.on('data', (data) => {
console.log(chalk.green(data.toString())); console.log(chalk.green(data.toString()));
}); });
devChildProcess.stderr.on('data', (data) => { devChildProcess.stderr.on('data', (data) => {
console.error(chalk.yellow(data.toString())); console.error(chalk.yellow(data.toString()));
}); });
@@ -45,6 +44,6 @@ export default function pakeCliDevPlugin() {
process.exit(code); process.exit(code);
}); });
}); });
} },
} };
} }

5
rollup.config.js vendored
View File

@@ -25,12 +25,13 @@ export default {
plugins: [ plugins: [
json(), json(),
typescript({ typescript({
tsconfig: "tsconfig.json", tsconfig: 'tsconfig.json',
clean: true, // 清理缓存 clean: true, // Clear cache
}), }),
commonjs(), commonjs(),
replace({ replace({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV), 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
preventAssignment: true,
}), }),
alias({ alias({
entries: [{ find: '@', replacement: path.join(appRootPath.path, 'bin') }], entries: [{ find: '@', replacement: path.join(appRootPath.path, 'bin') }],

Binary file not shown.

View File

@@ -1,29 +1,29 @@
{ {
"windows": [ "windows": [
{ {
"url": "https://weread.qq.com/", "url": "https://weread.qq.com/",
"transparent": false, "transparent": true,
"fullscreen": false, "fullscreen": false,
"width": 1200, "width": 1200,
"height": 780, "height": 780,
"resizable": true, "resizable": true,
"url_type": "web" "url_type": "web"
} }
], ],
"user_agent": { "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", "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", "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" "windows": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
}, },
"menu": { "menu": {
"macos": false, "macos": false,
"linux": false, "linux": false,
"windows": false "windows": false
}, },
"system_tray": { "system_tray": {
"macos": false, "macos": false,
"linux": true, "linux": true,
"windows": true "windows": true
}, },
"inject": [] "inject": []
} }

View File

@@ -30,7 +30,8 @@ pub fn get_window(app: &mut App, config: PakeConfig, _data_dir: PathBuf) -> Wind
.initialization_script(include_str!("../inject/component.js")) .initialization_script(include_str!("../inject/component.js"))
.initialization_script(include_str!("../inject/event.js")) .initialization_script(include_str!("../inject/event.js"))
.initialization_script(include_str!("../inject/style.js")) .initialization_script(include_str!("../inject/style.js"))
.initialization_script(include_str!("../inject/custom.js")); //Very annoying, otherwise dragging files to the window will not work. //This is necessary to allow for file injection by external developers for customization purposes.
.initialization_script(include_str!("../inject/custom.js"));
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
{ {

View File

@@ -1,2 +1,6 @@
// This file is used to merge the injected external js and css files /*
// and you can also directly add script files that you want to attach to the application in this fil * This file serves as a collection point for external JS and CSS dependencies.
* It amalgamates these external resources for easier injection into the application.
* Additionally, you can directly include any script files in this file
* that you wish to attach to the application.
*/

View File

@@ -68,95 +68,17 @@ document.addEventListener('DOMContentLoaded', () => {
document.body.appendChild(topDom); document.body.appendChild(topDom);
const domEl = document.getElementById('pack-top-dom'); const domEl = document.getElementById('pack-top-dom');
// Collect blob urls to blob by overriding window.URL.createObjectURL
function collectUrlToBlobs() {
const backupCreateObjectURL = window.URL.createObjectURL;
window.blobToUrlCaches = new Map();
window.URL.createObjectURL = (blob) => {
const url = backupCreateObjectURL.call(window.URL, blob);
window.blobToUrlCaches.set(url, blob);
return url;
};
}
function convertBlobUrlToBinary(blobUrl) {
return new Promise((resolve) => {
const blob = window.blobToUrlCaches.get(blobUrl);
const reader = new FileReader();
reader.readAsArrayBuffer(blob);
reader.onload = () => {
resolve(Array.from(new Uint8Array(reader.result)));
};
});
}
function downladFromDataUri(dataURI, filename) {
const byteString = atob(dataURI.split(',')[1]);
// write the bytes of the string to an ArrayBuffer
const bufferArray = new ArrayBuffer(byteString.length);
// create a view into the buffer
const binary = new Uint8Array(bufferArray);
// set the bytes of the buffer to the correct values
for (var i = 0; i < byteString.length; i++) {
binary[i] = byteString.charCodeAt(i);
}
// write the ArrayBuffer to a binary, and you're done
invoke('download_file_by_binary', {
params: {
filename,
binary: Array.from(binary)
},
});
}
function downloadFromBlobUrl(blobUrl, filename) {
convertBlobUrlToBinary(blobUrl).then((binary) => {
invoke('download_file_by_binary', {
params: {
filename,
binary
},
});
});
}
// detect blob download by createElement("a")
function detectDownloadByCreateAnchor() {
const createEle = document.createElement;
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) => {
const url = anchorEle.href;
const filename = anchorEle.download || getFilenameFromUrl(url);
if (window.blobToUrlCaches.has(url)) {
downloadFromBlobUrl(url, filename);
// case: downoload from dataURL -> convert dataURL ->
} else if (url.startsWith('data:')) {
downladFromDataUri(url, filename);
} else {
handleExternalLink(e, url);
}
}, true);
return anchorEle;
};
}
domEl.addEventListener('touchstart', () => { domEl.addEventListener('touchstart', () => {
appWindow.startDragging().then(); appWindow.startDragging().then();
}); });
domEl.addEventListener('mousedown', (e) => {
e.preventDefault();
if (e.buttons === 1 && e.detail !== 2) {
appWindow.startDragging().then();
}
});
domEl.addEventListener('dblclick', () => { domEl.addEventListener('dblclick', () => {
appWindow.isFullscreen().then((fullscreen) => { appWindow.isFullscreen().then((fullscreen) => {
appWindow.setFullscreen(!fullscreen).then(); appWindow.setFullscreen(!fullscreen).then();
@@ -172,8 +94,90 @@ function detectDownloadByCreateAnchor() {
} }
}); });
// Collect blob urls to blob by overriding window.URL.createObjectURL
function collectUrlToBlobs() {
const backupCreateObjectURL = window.URL.createObjectURL;
window.blobToUrlCaches = new Map();
window.URL.createObjectURL = (blob) => {
const url = backupCreateObjectURL.call(window.URL, blob);
window.blobToUrlCaches.set(url, blob);
return url;
};
}
function convertBlobUrlToBinary(blobUrl) {
return new Promise((resolve) => {
const blob = window.blobToUrlCaches.get(blobUrl);
const reader = new FileReader();
reader.readAsArrayBuffer(blob);
reader.onload = () => {
resolve(Array.from(new Uint8Array(reader.result)));
};
});
}
function downloadFromDataUri(dataURI, filename) {
const byteString = atob(dataURI.split(',')[1]);
// write the bytes of the string to an ArrayBuffer
const bufferArray = new ArrayBuffer(byteString.length);
// create a view into the buffer
const binary = new Uint8Array(bufferArray);
// set the bytes of the buffer to the correct values
for (let i = 0; i < byteString.length; i++) {
binary[i] = byteString.charCodeAt(i);
}
// write the ArrayBuffer to a binary, and you're done
invoke('download_file_by_binary', {
params: {
filename,
binary: Array.from(binary)
},
});
}
function downloadFromBlobUrl(blobUrl, filename) {
convertBlobUrlToBinary(blobUrl).then((binary) => {
invoke('download_file_by_binary', {
params: {
filename,
binary
},
});
});
}
// detect blob download by createElement("a")
function detectDownloadByCreateAnchor() {
const createEle = document.createElement;
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) => {
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:')) {
downloadFromDataUri(url, filename);
} else {
handleExternalLink(e, url);
}
}, true);
return anchorEle;
};
}
const isExternalLink = (url, host) => window.location.host !== host; const isExternalLink = (url, host) => window.location.host !== host;
// process special download protocal['data:','blob:'] // process special download protocol['data:','blob:']
const isSpecialDownload = (url) => ['blob', 'data'].some(protocal => url.startsWith(protocal)); const isSpecialDownload = (url) => ['blob', 'data'].some(protocal => url.startsWith(protocal));
const isDownloadRequired = (url, anchorElement, e) => const isDownloadRequired = (url, anchorElement, e) =>
@@ -186,7 +190,7 @@ function detectDownloadByCreateAnchor() {
const handleDownloadLink = (e, url, filename) => { const handleDownloadLink = (e, url, filename) => {
e.preventDefault(); e.preventDefault();
invoke('download_file', { params: { url, filename } }); invoke('download_file', {params: {url, filename}});
}; };
const detectAnchorElementClick = (e) => { const detectAnchorElementClick = (e) => {
@@ -217,7 +221,7 @@ function detectDownloadByCreateAnchor() {
// Rewrite the window.open function. // Rewrite the window.open function.
const originalWindowOpen = window.open; const originalWindowOpen = window.open;
window.open = function(url, name, specs) { window.open = function (url, name, specs) {
// Apple login and google login // Apple login and google login
if (name === 'AppleAuthentication') { if (name === 'AppleAuthentication') {
//do nothing //do nothing
@@ -257,10 +261,3 @@ function getFilenameFromUrl(url) {
const urlPath = new URL(url).pathname; const urlPath = new URL(url).pathname;
return urlPath.substring(urlPath.lastIndexOf('/') + 1); return urlPath.substring(urlPath.lastIndexOf('/') + 1);
} }
// Determine the language of the current system.
function getSystemLanguage() {
const lang = navigator.language.substr(0, 2);
return lang === 'ch' ? 'ch' : 'en';
}

View File

@@ -1,43 +1,39 @@
{ {
"package": { "package": {
"productName": "WeRead", "productName": "WeRead",
"version": "1.0.0" "version": "1.0.0"
}, },
"tauri": { "tauri": {
"security": { "security": {
"csp": null, "csp": null,
"dangerousRemoteDomainIpcAccess": [ "dangerousRemoteDomainIpcAccess": [
{ {
"domain": "weread.qq.com", "domain": "weread.qq.com",
"windows": [ "windows": ["pake"],
"pake" "enableTauriAPI": true
],
"enableTauriAPI": true
}
]
},
"updater": {
"active": false
},
"systemTray": {
"iconPath": "png/icon_512.png",
"iconAsTemplate": true
},
"allowlist": {
"all": true,
"fs": {
"all": true,
"scope": [
"$DOWNLOAD/*"
]
}
} }
]
}, },
"build": { "updater": {
"withGlobalTauri": true, "active": false
"devPath": "../dist", },
"distDir": "../dist", "systemTray": {
"beforeBuildCommand": "", "iconPath": "png/icon_512.png",
"beforeDevCommand": "" "iconAsTemplate": true
},
"allowlist": {
"all": true,
"fs": {
"all": true,
"scope": ["$DOWNLOAD/*"]
}
} }
},
"build": {
"withGlobalTauri": true,
"devPath": "../dist",
"distDir": "../dist",
"beforeBuildCommand": "",
"beforeDevCommand": ""
}
} }

View File

@@ -1,25 +1,23 @@
{ {
"tauri": { "tauri": {
"bundle": { "bundle": {
"icon": ["icons/weread.icns"], "icon": ["icons/weread.icns"],
"identifier": "com.pake.weread", "identifier": "com.pake.weread",
"active": true, "active": true,
"category": "DeveloperTool", "category": "DeveloperTool",
"copyright": "", "copyright": "",
"externalBin": [], "externalBin": [],
"longDescription": "", "longDescription": "",
"macOS": { "macOS": {
"entitlements": null, "entitlements": null,
"exceptionDomain": "", "exceptionDomain": "",
"frameworks": [], "frameworks": [],
"providerShortName": null, "providerShortName": null,
"signingIdentity": null "signingIdentity": null
}, },
"resources": [], "resources": [],
"shortDescription": "", "shortDescription": "",
"targets": [ "targets": ["dmg"]
"dmg"
]
}
} }
}
} }