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 CHANGED
@@ -1,4 +1,4 @@
1
- <h4 align="right"><strong>English</strong> | <a href="README_CN.md">简体中文</a> | <a href="README_JP.md">日本語</a></h4>
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="https://raw.githubusercontent.com/tw93/Pake/main/CONTRIBUTORS.svg?sanitize=true" alt="Contributors" width="1000" />
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.3";
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 (targets === 'rpm') {
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.options.targets === 'appimage' &&
1338
- (this.options.debug || process.env.PAKE_VERBOSE)) {
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pake-cli",
3
- "version": "3.7.3",
3
+ "version": "3.7.5",
4
4
  "description": "🤱🏻 Turn any webpage into a desktop app with one command. 🤱🏻 一键打包网页生成轻量桌面应用。",
5
5
  "engines": {
6
6
  "node": ">=18.0.0"
@@ -2539,7 +2539,7 @@ dependencies = [
2539
2539
 
2540
2540
  [[package]]
2541
2541
  name = "pake"
2542
- version = "3.7.3"
2542
+ version = "3.7.5"
2543
2543
  dependencies = [
2544
2544
  "serde",
2545
2545
  "serde_json",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "pake"
3
- version = "3.7.3"
3
+ version = "3.7.5"
4
4
  description = "🤱🏻 Turn any webpage into a desktop app with Rust."
5
5
  authors = ["Tw93"]
6
6
  license = "MIT"
@@ -18,7 +18,8 @@
18
18
  "enable_drag_drop": false,
19
19
  "maximize": false,
20
20
  "start_to_tray": false,
21
- "force_internal_navigation": false
21
+ "force_internal_navigation": false,
22
+ "new_window": false
22
23
  }
23
24
  ],
24
25
  "user_agent": {
@@ -19,6 +19,7 @@ pub struct WindowConfig {
19
19
  pub title: Option<String>,
20
20
  pub enable_wasm: bool,
21
21
  pub enable_drag_drop: bool,
22
+ pub new_window: bool,
22
23
  pub start_to_tray: bool,
23
24
  #[serde(default)]
24
25
  pub force_internal_navigation: bool,
@@ -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
- if window_config.dark_mode {
152
- window_builder = window_builder.theme(Some(Theme::Dark));
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 function executedFunction(...args) {
19
- const later = () => {
20
- clearTimeout(timeout);
21
- func(...args);
22
- };
4
+ return (...args) => {
23
5
  clearTimeout(timeout);
24
- timeout = setTimeout(later, wait);
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
- const isExplicitDark =
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 isExplicitLight =
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 (isExplicitDark) {
53
- mode = "dark";
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
- // Check body first, then html
70
- if (bodyBg && bodyBg !== "rgba(0, 0, 0, 0)" && bodyBg !== "transparent") {
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
- // Delay slightly to ensure styles are applied
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
- // We observe attributes for class changes, and also style changes just in case
109
- const observer = new MutationObserver((mutations) => {
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.body, {
120
- attributes: true,
121
- attributeFilter: ["class", "data-theme", "style"],
122
- subtree: false,
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
  });
@@ -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