pake-cli 3.7.3 → 3.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/cli.js +26 -9
- package/package.json +1 -1
- package/src-tauri/Cargo.lock +1 -1
- package/src-tauri/Cargo.toml +1 -1
- package/src-tauri/pake.json +2 -1
- package/src-tauri/src/app/config.rs +1 -0
- package/src-tauri/src/app/window.rs +17 -4
- package/src-tauri/src/inject/theme_refresh.js +22 -87
- package/src-tauri/src/lib.rs +8 -0
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<h4 align="right"><strong>English</strong> | <a href="README_CN.md">简体中文</a
|
|
1
|
+
<h4 align="right"><strong>English</strong> | <a href="README_CN.md">简体中文</a></h4>
|
|
2
2
|
<p align="center">
|
|
3
3
|
<img src=https://gw.alipayobjects.com/zos/k/fa/logo-modified.png width=138/>
|
|
4
4
|
</p>
|
|
@@ -196,7 +196,7 @@ For style customization, feature enhancement, container communication and other
|
|
|
196
196
|
Pake's development can not be without these Hackers. They contributed a lot of capabilities for Pake. Also, welcome to follow them! ❤️
|
|
197
197
|
|
|
198
198
|
<a href="https://github.com/tw93/Pake/graphs/contributors">
|
|
199
|
-
<img src="
|
|
199
|
+
<img src="./CONTRIBUTORS.svg?v=2" alt="Contributors" width="1000" />
|
|
200
200
|
</a>
|
|
201
201
|
|
|
202
202
|
## Support
|
package/dist/cli.js
CHANGED
|
@@ -22,7 +22,7 @@ import * as psl from 'psl';
|
|
|
22
22
|
import { InvalidArgumentError, program as program$1, Option } from 'commander';
|
|
23
23
|
|
|
24
24
|
var name = "pake-cli";
|
|
25
|
-
var version = "3.7.
|
|
25
|
+
var version = "3.7.5";
|
|
26
26
|
var description = "🤱🏻 Turn any webpage into a desktop app with one command. 🤱🏻 一键打包网页生成轻量桌面应用。";
|
|
27
27
|
var engines = {
|
|
28
28
|
node: ">=18.0.0"
|
|
@@ -484,7 +484,7 @@ async function mergeConfig(url, options, tauriConf) {
|
|
|
484
484
|
await fsExtra.copy(sourcePath, destPath);
|
|
485
485
|
}
|
|
486
486
|
}));
|
|
487
|
-
const { width, height, fullscreen, maximize, hideTitleBar, alwaysOnTop, appVersion, darkMode, disabledWebShortcuts, activationShortcut, userAgent, showSystemTray, systemTrayIcon, useLocalFile, identifier, name = 'pake-app', resizable = true, inject, proxyUrl, installerLanguage, hideOnClose, incognito, title, wasm, enableDragDrop, multiInstance, startToTray, forceInternalNavigation, zoom, minWidth, minHeight, ignoreCertificateErrors, } = options;
|
|
487
|
+
const { width, height, fullscreen, maximize, hideTitleBar, alwaysOnTop, appVersion, darkMode, disabledWebShortcuts, activationShortcut, userAgent, showSystemTray, systemTrayIcon, useLocalFile, identifier, name = 'pake-app', resizable = true, inject, proxyUrl, installerLanguage, hideOnClose, incognito, title, wasm, enableDragDrop, multiInstance, startToTray, forceInternalNavigation, zoom, minWidth, minHeight, ignoreCertificateErrors, newWindow, } = options;
|
|
488
488
|
const { platform } = process;
|
|
489
489
|
const platformHideOnClose = hideOnClose ?? platform === 'darwin';
|
|
490
490
|
const tauriConfWindowOptions = {
|
|
@@ -509,6 +509,7 @@ async function mergeConfig(url, options, tauriConf) {
|
|
|
509
509
|
min_width: minWidth,
|
|
510
510
|
min_height: minHeight,
|
|
511
511
|
ignore_certificate_errors: ignoreCertificateErrors,
|
|
512
|
+
new_window: newWindow,
|
|
512
513
|
};
|
|
513
514
|
Object.assign(tauriConf.pake.windows[0], { url, ...tauriConfWindowOptions });
|
|
514
515
|
tauriConf.productName = name;
|
|
@@ -842,10 +843,10 @@ class BaseBuilder {
|
|
|
842
843
|
logger.info(`✺ Located in China, using ${packageManager}/rsProxy CN mirror.`);
|
|
843
844
|
const projectCnConf = path.join(tauriSrcPath, 'rust_proxy.toml');
|
|
844
845
|
await fsExtra.copy(projectCnConf, projectConf);
|
|
845
|
-
await shellExec(`cd "${npmDirectory}" && ${packageManager} install${registryOption}${peerDepsOption}`, timeout, buildEnv);
|
|
846
|
+
await shellExec(`cd "${npmDirectory}" && ${packageManager} install${registryOption}${peerDepsOption}`, timeout, { ...buildEnv, CI: 'true' });
|
|
846
847
|
}
|
|
847
848
|
else {
|
|
848
|
-
await shellExec(`cd "${npmDirectory}" && ${packageManager} install${peerDepsOption}`, timeout, buildEnv);
|
|
849
|
+
await shellExec(`cd "${npmDirectory}" && ${packageManager} install${peerDepsOption}`, timeout, { ...buildEnv, CI: 'true' });
|
|
849
850
|
}
|
|
850
851
|
spinner.succeed(chalk.green('Package installed!'));
|
|
851
852
|
}
|
|
@@ -861,7 +862,7 @@ class BaseBuilder {
|
|
|
861
862
|
try {
|
|
862
863
|
const projectCnConf = path.join(tauriSrcPath, 'rust_proxy.toml');
|
|
863
864
|
await fsExtra.copy(projectCnConf, projectConf);
|
|
864
|
-
await shellExec(`cd "${npmDirectory}" && ${packageManager} install${registryOption}${peerDepsOption}`, timeout, buildEnv);
|
|
865
|
+
await shellExec(`cd "${npmDirectory}" && ${packageManager} install${registryOption}${peerDepsOption}`, timeout, { ...buildEnv, CI: 'true' });
|
|
865
866
|
retrySpinner.succeed(chalk.green('Package installed with CN mirror!'));
|
|
866
867
|
}
|
|
867
868
|
catch (retryError) {
|
|
@@ -1275,6 +1276,7 @@ class WinBuilder extends BaseBuilder {
|
|
|
1275
1276
|
class LinuxBuilder extends BaseBuilder {
|
|
1276
1277
|
constructor(options) {
|
|
1277
1278
|
super(options);
|
|
1279
|
+
this.currentBuildType = '';
|
|
1278
1280
|
const target = options.targets || 'deb';
|
|
1279
1281
|
if (target.includes('-arm64')) {
|
|
1280
1282
|
this.buildFormat = target.replace('-arm64', '');
|
|
@@ -1305,7 +1307,7 @@ class LinuxBuilder extends BaseBuilder {
|
|
|
1305
1307
|
}
|
|
1306
1308
|
}
|
|
1307
1309
|
}
|
|
1308
|
-
if (
|
|
1310
|
+
if (this.currentBuildType === 'rpm') {
|
|
1309
1311
|
return `${name}-${version}-1.${arch}`;
|
|
1310
1312
|
}
|
|
1311
1313
|
return `${name}_${version}_${arch}`;
|
|
@@ -1317,10 +1319,16 @@ class LinuxBuilder extends BaseBuilder {
|
|
|
1317
1319
|
.map((t) => t.trim());
|
|
1318
1320
|
for (const target of targetTypes) {
|
|
1319
1321
|
if (requestedTargets.includes(target)) {
|
|
1322
|
+
this.currentBuildType = target;
|
|
1320
1323
|
await this.buildAndCopy(url, target);
|
|
1321
1324
|
}
|
|
1322
1325
|
}
|
|
1323
1326
|
}
|
|
1327
|
+
// Override buildAndCopy to ensure currentBuildType is synced if called directly, though the loop above handles it most of the time.
|
|
1328
|
+
async buildAndCopy(url, target) {
|
|
1329
|
+
this.currentBuildType = target;
|
|
1330
|
+
await super.buildAndCopy(url, target);
|
|
1331
|
+
}
|
|
1324
1332
|
getBuildCommand(packageManager = 'pnpm') {
|
|
1325
1333
|
const configPath = path.join('src-tauri', '.pake', 'tauri.conf.json');
|
|
1326
1334
|
const buildTarget = this.buildArch === 'arm64'
|
|
@@ -1331,11 +1339,16 @@ class LinuxBuilder extends BaseBuilder {
|
|
|
1331
1339
|
if (features.length > 0) {
|
|
1332
1340
|
fullCommand += ` --features ${features.join(',')}`;
|
|
1333
1341
|
}
|
|
1342
|
+
if (this.currentBuildType) {
|
|
1343
|
+
fullCommand += ` --bundles ${this.currentBuildType}`;
|
|
1344
|
+
}
|
|
1334
1345
|
// Enable verbose output for AppImage builds when debugging or PAKE_VERBOSE is set.
|
|
1335
1346
|
// AppImage builds often fail with minimal error messages from linuxdeploy,
|
|
1336
1347
|
// so verbose mode helps diagnose issues like strip failures and missing dependencies.
|
|
1337
|
-
if (this.
|
|
1338
|
-
(this.options.
|
|
1348
|
+
if (this.currentBuildType === 'appimage' &&
|
|
1349
|
+
(this.options.targets.includes('appimage') ||
|
|
1350
|
+
this.options.debug ||
|
|
1351
|
+
process.env.PAKE_VERBOSE)) {
|
|
1339
1352
|
fullCommand += ' --verbose';
|
|
1340
1353
|
}
|
|
1341
1354
|
return fullCommand;
|
|
@@ -1897,7 +1910,7 @@ const DEFAULT_PAKE_OPTIONS = {
|
|
|
1897
1910
|
targets: (() => {
|
|
1898
1911
|
switch (process.platform) {
|
|
1899
1912
|
case 'linux':
|
|
1900
|
-
return 'deb';
|
|
1913
|
+
return 'deb,appimage';
|
|
1901
1914
|
case 'darwin':
|
|
1902
1915
|
return 'dmg';
|
|
1903
1916
|
case 'win32':
|
|
@@ -1925,6 +1938,7 @@ const DEFAULT_PAKE_OPTIONS = {
|
|
|
1925
1938
|
minWidth: 0,
|
|
1926
1939
|
minHeight: 0,
|
|
1927
1940
|
ignoreCertificateErrors: false,
|
|
1941
|
+
newWindow: false,
|
|
1928
1942
|
};
|
|
1929
1943
|
|
|
1930
1944
|
function validateNumberInput(value) {
|
|
@@ -2075,6 +2089,9 @@ ${green('|_| \\__,_|_|\\_\\___| can turn any webpage into a desktop app with
|
|
|
2075
2089
|
.addOption(new Option('--iterative-build', 'Turn on rapid build mode (app only, no dmg/deb/msi), good for debugging')
|
|
2076
2090
|
.default(DEFAULT_PAKE_OPTIONS.iterativeBuild)
|
|
2077
2091
|
.hideHelp())
|
|
2092
|
+
.addOption(new Option('--new-window', 'Allow new window for third-party login')
|
|
2093
|
+
.default(DEFAULT_PAKE_OPTIONS.newWindow)
|
|
2094
|
+
.hideHelp())
|
|
2078
2095
|
.version(packageJson.version, '-v, --version')
|
|
2079
2096
|
.configureHelp({
|
|
2080
2097
|
sortSubcommands: true,
|
package/package.json
CHANGED
package/src-tauri/Cargo.lock
CHANGED
package/src-tauri/Cargo.toml
CHANGED
package/src-tauri/pake.json
CHANGED
|
@@ -58,12 +58,16 @@ pub fn set_window(app: &mut App, config: &PakeConfig, tauri_config: &Config) ->
|
|
|
58
58
|
.visible(false)
|
|
59
59
|
.user_agent(user_agent)
|
|
60
60
|
.resizable(window_config.resizable)
|
|
61
|
-
.fullscreen(window_config.fullscreen)
|
|
62
61
|
.maximized(window_config.maximize)
|
|
63
62
|
.inner_size(window_config.width, window_config.height)
|
|
64
63
|
.always_on_top(window_config.always_on_top)
|
|
65
64
|
.incognito(window_config.incognito);
|
|
66
65
|
|
|
66
|
+
#[cfg(any(target_os = "windows", target_os = "macos"))]
|
|
67
|
+
{
|
|
68
|
+
window_builder = window_builder.fullscreen(window_config.fullscreen);
|
|
69
|
+
}
|
|
70
|
+
|
|
67
71
|
if window_config.min_width > 0.0 || window_config.min_height > 0.0 {
|
|
68
72
|
let min_w = if window_config.min_width > 0.0 {
|
|
69
73
|
window_config.min_width
|
|
@@ -82,6 +86,11 @@ pub fn set_window(app: &mut App, config: &PakeConfig, tauri_config: &Config) ->
|
|
|
82
86
|
window_builder = window_builder.disable_drag_drop_handler();
|
|
83
87
|
}
|
|
84
88
|
|
|
89
|
+
if window_config.new_window {
|
|
90
|
+
window_builder = window_builder
|
|
91
|
+
.on_new_window(move |_url, _features| tauri::webview::NewWindowResponse::Allow);
|
|
92
|
+
}
|
|
93
|
+
|
|
85
94
|
// Add initialization scripts
|
|
86
95
|
window_builder = window_builder
|
|
87
96
|
.initialization_script(&config_script)
|
|
@@ -148,9 +157,13 @@ pub fn set_window(app: &mut App, config: &PakeConfig, tauri_config: &Config) ->
|
|
|
148
157
|
};
|
|
149
158
|
window_builder = window_builder.title_bar_style(title_bar_style);
|
|
150
159
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
160
|
+
// Default to following system theme (None), only force dark when explicitly set
|
|
161
|
+
let theme = if window_config.dark_mode {
|
|
162
|
+
Some(Theme::Dark)
|
|
163
|
+
} else {
|
|
164
|
+
None // Follow system theme
|
|
165
|
+
};
|
|
166
|
+
window_builder = window_builder.theme(theme);
|
|
154
167
|
}
|
|
155
168
|
|
|
156
169
|
// Windows and Linux: set data_directory before proxy_url
|
|
@@ -1,124 +1,59 @@
|
|
|
1
1
|
document.addEventListener("DOMContentLoaded", () => {
|
|
2
|
-
// Helper: Calculate brightness from RGB color
|
|
3
|
-
const isDarkColor = (color) => {
|
|
4
|
-
if (!color) return false;
|
|
5
|
-
const match = color.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
|
|
6
|
-
if (!match) return false;
|
|
7
|
-
const r = parseInt(match[1]);
|
|
8
|
-
const g = parseInt(match[2]);
|
|
9
|
-
const b = parseInt(match[3]);
|
|
10
|
-
// Standard luminance formula
|
|
11
|
-
const luminance = 0.299 * r + 0.587 * g + 0.114 * b;
|
|
12
|
-
return luminance < 128;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
// Debounce helper
|
|
16
2
|
const debounce = (func, wait) => {
|
|
17
3
|
let timeout;
|
|
18
|
-
return
|
|
19
|
-
const later = () => {
|
|
20
|
-
clearTimeout(timeout);
|
|
21
|
-
func(...args);
|
|
22
|
-
};
|
|
4
|
+
return (...args) => {
|
|
23
5
|
clearTimeout(timeout);
|
|
24
|
-
timeout = setTimeout(
|
|
6
|
+
timeout = setTimeout(() => func(...args), wait);
|
|
25
7
|
};
|
|
26
8
|
};
|
|
27
9
|
|
|
28
|
-
// Function to detect and send theme to Rust
|
|
29
10
|
const updateTheme = () => {
|
|
30
|
-
let mode = "light";
|
|
31
|
-
let detected = false;
|
|
32
|
-
|
|
33
|
-
// Strategy 1: Explicit DOM Class/Attribute (High Priority)
|
|
34
|
-
// Many apps use specific classes for hard-coded themes
|
|
35
11
|
const doc = document.documentElement;
|
|
36
12
|
const body = document.body;
|
|
13
|
+
let mode = null;
|
|
37
14
|
|
|
38
|
-
|
|
15
|
+
// Check for explicit theme classes or attributes
|
|
16
|
+
const isDark =
|
|
39
17
|
doc.classList.contains("dark") ||
|
|
40
18
|
body.classList.contains("dark") ||
|
|
41
19
|
doc.getAttribute("data-theme") === "dark" ||
|
|
42
20
|
body.getAttribute("data-theme") === "dark" ||
|
|
43
21
|
doc.style.colorScheme === "dark";
|
|
44
22
|
|
|
45
|
-
const
|
|
23
|
+
const isLight =
|
|
46
24
|
doc.classList.contains("light") ||
|
|
47
25
|
body.classList.contains("light") ||
|
|
48
26
|
doc.getAttribute("data-theme") === "light" ||
|
|
49
27
|
body.getAttribute("data-theme") === "light" ||
|
|
50
28
|
doc.style.colorScheme === "light";
|
|
51
29
|
|
|
52
|
-
if (
|
|
53
|
-
|
|
54
|
-
detected = true;
|
|
55
|
-
} else if (isExplicitLight) {
|
|
56
|
-
mode = "light";
|
|
57
|
-
detected = true;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Strategy 2: Computed Background Color (Fallback & Verification)
|
|
61
|
-
// If no explicit class is found, or to double-check, look at the actual background color.
|
|
62
|
-
// This is useful when the site relies purely on CSS media queries without classes.
|
|
63
|
-
if (!detected) {
|
|
64
|
-
const bodyBg = window.getComputedStyle(document.body).backgroundColor;
|
|
65
|
-
const htmlBg = window.getComputedStyle(
|
|
66
|
-
document.documentElement,
|
|
67
|
-
).backgroundColor;
|
|
30
|
+
if (isDark) mode = "dark";
|
|
31
|
+
else if (isLight) mode = "light";
|
|
68
32
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
mode = isDarkColor(bodyBg) ? "dark" : "light";
|
|
72
|
-
} else if (
|
|
73
|
-
htmlBg &&
|
|
74
|
-
htmlBg !== "rgba(0, 0, 0, 0)" &&
|
|
75
|
-
htmlBg !== "transparent"
|
|
76
|
-
) {
|
|
77
|
-
mode = isDarkColor(htmlBg) ? "dark" : "light";
|
|
78
|
-
} else {
|
|
79
|
-
// Strategy 3: System Preference (Last Resort)
|
|
80
|
-
if (
|
|
81
|
-
window.matchMedia &&
|
|
82
|
-
window.matchMedia("(prefers-color-scheme: dark)").matches
|
|
83
|
-
) {
|
|
84
|
-
mode = "dark";
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Send to Rust
|
|
90
|
-
if (window.__TAURI__ && window.__TAURI__.core) {
|
|
33
|
+
// Only invoke Rust command if an explicit theme override is detected
|
|
34
|
+
if (mode && window.__TAURI__?.core) {
|
|
91
35
|
window.__TAURI__.core.invoke("update_theme_mode", { mode });
|
|
92
36
|
}
|
|
93
37
|
};
|
|
94
38
|
|
|
95
|
-
// Debounced version of updateTheme
|
|
96
39
|
const debouncedUpdateTheme = debounce(updateTheme, 200);
|
|
97
40
|
|
|
98
|
-
// Initial check
|
|
99
|
-
|
|
100
|
-
setTimeout(updateTheme, 100);
|
|
101
|
-
|
|
102
|
-
// Watch for system theme changes
|
|
103
|
-
window
|
|
104
|
-
.matchMedia("(prefers-color-scheme: dark)")
|
|
105
|
-
.addEventListener("change", updateTheme);
|
|
41
|
+
// Initial check with delay to allow site to render
|
|
42
|
+
setTimeout(updateTheme, 500);
|
|
106
43
|
|
|
107
44
|
// Watch for DOM changes
|
|
108
|
-
|
|
109
|
-
const
|
|
110
|
-
debouncedUpdateTheme();
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
observer.observe(document.documentElement, {
|
|
45
|
+
const observer = new MutationObserver(debouncedUpdateTheme);
|
|
46
|
+
const config = {
|
|
114
47
|
attributes: true,
|
|
115
48
|
attributeFilter: ["class", "data-theme", "style"],
|
|
116
49
|
subtree: false,
|
|
117
|
-
}
|
|
50
|
+
};
|
|
118
51
|
|
|
119
|
-
observer.observe(document.
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
52
|
+
observer.observe(document.documentElement, config);
|
|
53
|
+
observer.observe(document.body, config);
|
|
54
|
+
|
|
55
|
+
// Watch for system theme changes (though window should handle this natively now)
|
|
56
|
+
window
|
|
57
|
+
.matchMedia("(prefers-color-scheme: dark)")
|
|
58
|
+
.addEventListener("change", updateTheme);
|
|
124
59
|
});
|
package/src-tauri/src/lib.rs
CHANGED
|
@@ -99,6 +99,14 @@ pub fn run_app() {
|
|
|
99
99
|
tauri::async_runtime::spawn(async move {
|
|
100
100
|
tokio::time::sleep(tokio::time::Duration::from_millis(WINDOW_SHOW_DELAY)).await;
|
|
101
101
|
window_clone.show().unwrap();
|
|
102
|
+
|
|
103
|
+
// Fixed: Linux fullscreen issue with virtual keyboard
|
|
104
|
+
#[cfg(all(not(target_os = "windows"), not(target_os = "macos")))]
|
|
105
|
+
{
|
|
106
|
+
if init_fullscreen {
|
|
107
|
+
window_clone.set_fullscreen(true).unwrap();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
102
110
|
});
|
|
103
111
|
}
|
|
104
112
|
|