pake-cli 3.7.8 → 3.8.2

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
@@ -137,21 +137,22 @@
137
137
 
138
138
  <br/>
139
139
 
140
- | Mac | Windows/Linux | Function |
141
- | ------------------------------------------ | --------------------------------------------------- | ----------------------------------- |
142
- | <kbd>⌘</kbd> + <kbd>[</kbd> | <kbd>Ctrl</kbd> + <kbd>←</kbd> | Return to the previous page |
143
- | <kbd>⌘</kbd> + <kbd>]</kbd> | <kbd>Ctrl</kbd> + <kbd>→</kbd> | Go to the next page |
144
- | <kbd>⌘</kbd> + <kbd>↑</kbd> | <kbd>Ctrl</kbd> + <kbd>↑</kbd> | Auto scroll to top of page |
145
- | <kbd>⌘</kbd> + <kbd>↓</kbd> | <kbd>Ctrl</kbd> + <kbd>↓</kbd> | Auto scroll to bottom of page |
146
- | <kbd>⌘</kbd> + <kbd>r</kbd> | <kbd>Ctrl</kbd> + <kbd>r</kbd> | Refresh Page |
147
- | <kbd>⌘</kbd> + <kbd>w</kbd> | <kbd>Ctrl</kbd> + <kbd>w</kbd> | Hide window, not quit |
148
- | <kbd>⌘</kbd> + <kbd>-</kbd> | <kbd>Ctrl</kbd> + <kbd>-</kbd> | Zoom out the page |
149
- | <kbd>⌘</kbd> + <kbd>=</kbd> | <kbd>Ctrl</kbd> + <kbd>=</kbd> | Zoom in the Page |
150
- | <kbd>⌘</kbd> + <kbd>0</kbd> | <kbd>Ctrl</kbd> + <kbd>0</kbd> | Reset the page zoom |
151
- | <kbd>⌘</kbd> + <kbd>L</kbd> | <kbd>Ctrl</kbd> + <kbd>L</kbd> | Copy Current Page URL |
152
- | <kbd>⌘</kbd> + <kbd>⇧</kbd> + <kbd>H</kbd> | <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>H</kbd> | Go to Home Page |
153
- | <kbd>⌘</kbd> + <kbd>⌥</kbd> + <kbd>I</kbd> | <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>I</kbd> | Toggle Developer Tools (Debug Only) |
154
- | <kbd>⌘</kbd> + <kbd>⇧</kbd> + <kbd>⌫</kbd> | <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>Del</kbd> | Clear Cache & Restart |
140
+ | Mac | Windows/Linux | Function |
141
+ | --------------------------------------------------------- | --------------------------------------------------- | ----------------------------------- |
142
+ | <kbd>⌘</kbd> + <kbd>[</kbd> | <kbd>Ctrl</kbd> + <kbd>←</kbd> | Return to the previous page |
143
+ | <kbd>⌘</kbd> + <kbd>]</kbd> | <kbd>Ctrl</kbd> + <kbd>→</kbd> | Go to the next page |
144
+ | <kbd>⌘</kbd> + <kbd>↑</kbd> | <kbd>Ctrl</kbd> + <kbd>↑</kbd> | Auto scroll to top of page |
145
+ | <kbd>⌘</kbd> + <kbd>↓</kbd> | <kbd>Ctrl</kbd> + <kbd>↓</kbd> | Auto scroll to bottom of page |
146
+ | <kbd>⌘</kbd> + <kbd>r</kbd> | <kbd>Ctrl</kbd> + <kbd>r</kbd> | Refresh Page |
147
+ | <kbd>⌘</kbd> + <kbd>w</kbd> | <kbd>Ctrl</kbd> + <kbd>w</kbd> | Hide window, not quit |
148
+ | <kbd>⌘</kbd> + <kbd>-</kbd> | <kbd>Ctrl</kbd> + <kbd>-</kbd> | Zoom out the page |
149
+ | <kbd>⌘</kbd> + <kbd>=</kbd> | <kbd>Ctrl</kbd> + <kbd>=</kbd> | Zoom in the Page |
150
+ | <kbd>⌘</kbd> + <kbd>0</kbd> | <kbd>Ctrl</kbd> + <kbd>0</kbd> | Reset the page zoom |
151
+ | <kbd>⌘</kbd> + <kbd>L</kbd> | <kbd>Ctrl</kbd> + <kbd>L</kbd> | Copy Current Page URL |
152
+ | <kbd>⌘</kbd> + <kbd>⇧</kbd> + <kbd>⌥</kbd> + <kbd>V</kbd> | <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>V</kbd> | Paste and Match Style |
153
+ | <kbd>⌘</kbd> + <kbd>⇧</kbd> + <kbd>H</kbd> | <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>H</kbd> | Go to Home Page |
154
+ | <kbd>⌘</kbd> + <kbd>⌥</kbd> + <kbd>I</kbd> | <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>I</kbd> | Toggle Developer Tools (Debug Only) |
155
+ | <kbd>⌘</kbd> + <kbd>⇧</kbd> + <kbd>⌫</kbd> | <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>Del</kbd> | Clear Cache & Restart |
155
156
 
156
157
  In addition, double-click the title bar to switch to full-screen mode. For Mac users, you can also use the gesture to go to the previous or next page and drag the title bar to move the window. The new menu also offers options for navigation, zoom, and window controls.
157
158
 
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.8";
25
+ var version = "3.8.2";
26
26
  var description = "🤱🏻 Turn any webpage into a desktop app with one command. 🤱🏻 一键打包网页生成轻量桌面应用。";
27
27
  var engines = {
28
28
  node: ">=18.0.0"
@@ -914,7 +914,7 @@ class BaseBuilder {
914
914
  // Warn users about potential AppImage build failures on modern Linux systems.
915
915
  // The linuxdeploy tool bundled in Tauri uses an older strip tool that doesn't
916
916
  // recognize the .relr.dyn section introduced in glibc 2.38+.
917
- if (process.platform === 'linux' && this.options.targets === 'appimage') {
917
+ if (process.platform === 'linux' && target === 'appimage') {
918
918
  if (!buildEnv.NO_STRIP) {
919
919
  logger.warn('⚠ Building AppImage on Linux may fail due to strip incompatibility with glibc 2.38+');
920
920
  logger.warn('⚠ If build fails, retry with: NO_STRIP=1 pake <url> --targets appimage');
@@ -927,7 +927,7 @@ class BaseBuilder {
927
927
  }
928
928
  catch (error) {
929
929
  const shouldRetryWithoutStrip = process.platform === 'linux' &&
930
- this.options.targets === 'appimage' &&
930
+ target === 'appimage' &&
931
931
  !buildEnv.NO_STRIP &&
932
932
  this.isLinuxDeployStripError(error);
933
933
  if (shouldRetryWithoutStrip) {
@@ -1291,18 +1291,20 @@ class LinuxBuilder extends BaseBuilder {
1291
1291
  getFileName() {
1292
1292
  const { name = 'pake-app', targets } = this.options;
1293
1293
  const version = tauriConfig.version;
1294
+ const buildType = this.currentBuildType || targets.split(',').map((t) => t.trim())[0];
1294
1295
  let arch;
1295
1296
  if (this.buildArch === 'arm64') {
1296
- arch = targets === 'rpm' || targets === 'appimage' ? 'aarch64' : 'arm64';
1297
+ arch =
1298
+ buildType === 'rpm' || buildType === 'appimage' ? 'aarch64' : 'arm64';
1297
1299
  }
1298
1300
  else {
1299
1301
  if (this.buildArch === 'x64') {
1300
- arch = targets === 'rpm' ? 'x86_64' : 'amd64';
1302
+ arch = buildType === 'rpm' ? 'x86_64' : 'amd64';
1301
1303
  }
1302
1304
  else {
1303
1305
  arch = this.buildArch;
1304
1306
  if (this.buildArch === 'arm64' &&
1305
- (targets === 'rpm' || targets === 'appimage')) {
1307
+ (buildType === 'rpm' || buildType === 'appimage')) {
1306
1308
  arch = 'aarch64';
1307
1309
  }
1308
1310
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pake-cli",
3
- "version": "3.7.8",
3
+ "version": "3.8.2",
4
4
  "description": "🤱🏻 Turn any webpage into a desktop app with one command. 🤱🏻 一键打包网页生成轻量桌面应用。",
5
5
  "engines": {
6
6
  "node": ">=18.0.0"
@@ -2526,7 +2526,7 @@ dependencies = [
2526
2526
 
2527
2527
  [[package]]
2528
2528
  name = "pake"
2529
- version = "3.7.8"
2529
+ version = "3.8.2"
2530
2530
  dependencies = [
2531
2531
  "serde",
2532
2532
  "serde_json",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "pake"
3
- version = "3.7.8"
3
+ version = "3.8.2"
4
4
  description = "🤱🏻 Turn any webpage into a desktop app with Rust."
5
5
  authors = ["Tw93"]
6
6
  license = "MIT"
@@ -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
+ #[serde(default)]
22
23
  pub new_window: bool,
23
24
  pub start_to_tray: bool,
24
25
  #[serde(default)]
@@ -66,6 +66,13 @@ fn edit_menu(app: &AppHandle<Wry>) -> tauri::Result<Submenu<Wry>> {
66
66
  edit_menu.append(&PredefinedMenuItem::cut(app, None)?)?;
67
67
  edit_menu.append(&PredefinedMenuItem::copy(app, None)?)?;
68
68
  edit_menu.append(&PredefinedMenuItem::paste(app, None)?)?;
69
+ edit_menu.append(&MenuItem::with_id(
70
+ app,
71
+ "paste_and_match_style",
72
+ "Paste and Match Style",
73
+ true,
74
+ Some("CmdOrCtrl+Shift+Option+V"),
75
+ )?)?;
69
76
  edit_menu.append(&PredefinedMenuItem::select_all(app, None)?)?;
70
77
  edit_menu.append(&PredefinedMenuItem::separator(app)?)?;
71
78
  edit_menu.append(&MenuItem::with_id(
@@ -229,6 +236,11 @@ pub fn handle_menu_click(app_handle: &AppHandle, id: &str) {
229
236
  let _ = window.eval("navigator.clipboard.writeText(window.location.href)");
230
237
  }
231
238
  }
239
+ "paste_and_match_style" => {
240
+ if let Some(window) = app_handle.get_webview_window("pake") {
241
+ let _ = window.eval("triggerPasteAsPlainText()");
242
+ }
243
+ }
232
244
  "clear_cache_restart" => {
233
245
  if let Some(window) = app_handle.get_webview_window("pake") {
234
246
  if let Ok(_) = window.clear_all_browsing_data() {
@@ -13,6 +13,7 @@ pub fn set_system_tray(
13
13
  app: &AppHandle,
14
14
  show_system_tray: bool,
15
15
  tray_icon_path: &str,
16
+ _init_fullscreen: bool,
16
17
  ) -> tauri::Result<()> {
17
18
  if !show_system_tray {
18
19
  app.remove_tray_by_id("pake-tray");
@@ -40,6 +41,11 @@ pub fn set_system_tray(
40
41
  "show_app" => {
41
42
  if let Some(window) = app.get_webview_window("pake") {
42
43
  window.show().unwrap();
44
+ #[cfg(target_os = "linux")]
45
+ if _init_fullscreen && !window.is_fullscreen().unwrap_or(false) {
46
+ let _ = window.set_fullscreen(true);
47
+ let _ = window.set_focus();
48
+ }
43
49
  }
44
50
  }
45
51
  "quit" => {
@@ -48,7 +54,7 @@ pub fn set_system_tray(
48
54
  }
49
55
  _ => (),
50
56
  })
51
- .on_tray_icon_event(|tray, event| match event {
57
+ .on_tray_icon_event(move |tray, event| match event {
52
58
  TrayIconEvent::Click { button, .. } => {
53
59
  if button == tauri::tray::MouseButton::Left {
54
60
  if let Some(window) = tray.app_handle().get_webview_window("pake") {
@@ -58,6 +64,10 @@ pub fn set_system_tray(
58
64
  } else {
59
65
  window.show().unwrap();
60
66
  window.set_focus().unwrap();
67
+ #[cfg(target_os = "linux")]
68
+ if _init_fullscreen && !window.is_fullscreen().unwrap_or(false) {
69
+ let _ = window.set_fullscreen(true);
70
+ }
61
71
  }
62
72
  }
63
73
  }
@@ -82,7 +92,11 @@ pub fn set_system_tray(
82
92
  Ok(())
83
93
  }
84
94
 
85
- pub fn set_global_shortcut(app: &AppHandle, shortcut: String) -> tauri::Result<()> {
95
+ pub fn set_global_shortcut(
96
+ app: &AppHandle,
97
+ shortcut: String,
98
+ _init_fullscreen: bool,
99
+ ) -> tauri::Result<()> {
86
100
  if shortcut.is_empty() {
87
101
  return Ok(());
88
102
  }
@@ -113,6 +127,11 @@ pub fn set_global_shortcut(app: &AppHandle, shortcut: String) -> tauri::Result<(
113
127
  } else {
114
128
  window.show().unwrap();
115
129
  window.set_focus().unwrap();
130
+ #[cfg(target_os = "linux")]
131
+ if _init_fullscreen && !window.is_fullscreen().unwrap_or(false)
132
+ {
133
+ let _ = window.set_fullscreen(true);
134
+ }
116
135
  }
117
136
  }
118
137
  }
@@ -24,6 +24,9 @@ document.addEventListener("DOMContentLoaded", () => {
24
24
  // This bridges the HTML5 Fullscreen API to Tauri's native window fullscreen
25
25
  // Works for all video sites (YouTube, Vimeo, Bilibili, etc.)
26
26
  (function () {
27
+ if (window.__PAKE_FULLSCREEN_POLYFILL__) return;
28
+ window.__PAKE_FULLSCREEN_POLYFILL__ = true;
29
+
27
30
  function initFullscreenPolyfill() {
28
31
  if (!window.__TAURI__ || !document.head) {
29
32
  setTimeout(initFullscreenPolyfill, 100);
@@ -37,11 +40,13 @@ document.addEventListener("DOMContentLoaded", () => {
37
40
  let originalParent = null;
38
41
  let originalNextSibling = null;
39
42
  let wasInBody = false;
43
+ let monitorId = null;
40
44
 
41
45
  // Inject fullscreen styles
42
- const styleEl = document.createElement("style");
43
- styleEl.id = "pake-fullscreen-style";
44
- styleEl.textContent = `
46
+ if (!document.getElementById("pake-fullscreen-style")) {
47
+ const styleEl = document.createElement("style");
48
+ styleEl.id = "pake-fullscreen-style";
49
+ styleEl.textContent = `
45
50
  body.pake-fullscreen-active {
46
51
  overflow: hidden !important;
47
52
  }
@@ -65,7 +70,28 @@ document.addEventListener("DOMContentLoaded", () => {
65
70
  object-fit: contain !important;
66
71
  }
67
72
  `;
68
- document.head.appendChild(styleEl);
73
+ document.head.appendChild(styleEl);
74
+ }
75
+
76
+ function startFullscreenMonitor() {
77
+ if (monitorId) return;
78
+ monitorId = setInterval(() => {
79
+ appWindow
80
+ .isFullscreen()
81
+ .then((isFullscreen) => {
82
+ if (fullscreenElement && !isFullscreen) {
83
+ exitFullscreen();
84
+ }
85
+ })
86
+ .catch(() => {});
87
+ }, 500);
88
+ }
89
+
90
+ function stopFullscreenMonitor() {
91
+ if (!monitorId) return;
92
+ clearInterval(monitorId);
93
+ monitorId = null;
94
+ }
69
95
 
70
96
  // Find the actual video element
71
97
  function findMediaElement() {
@@ -136,6 +162,7 @@ document.addEventListener("DOMContentLoaded", () => {
136
162
 
137
163
  // Fullscreen window
138
164
  appWindow.setFullscreen(true).then(() => {
165
+ startFullscreenMonitor();
139
166
  const event = new Event("fullscreenchange", { bubbles: true });
140
167
  document.dispatchEvent(event);
141
168
  element.dispatchEvent(event);
@@ -156,6 +183,8 @@ document.addEventListener("DOMContentLoaded", () => {
156
183
  return Promise.resolve();
157
184
  }
158
185
 
186
+ stopFullscreenMonitor();
187
+
159
188
  const exitingElement = fullscreenElement;
160
189
  const targetElement = actualFullscreenElement;
161
190
 
@@ -252,20 +281,6 @@ document.addEventListener("DOMContentLoaded", () => {
252
281
  },
253
282
  true,
254
283
  );
255
-
256
- // Monitor window fullscreen changes
257
- let lastFullscreenState = false;
258
- setInterval(() => {
259
- appWindow
260
- .isFullscreen()
261
- .then((isFullscreen) => {
262
- if (lastFullscreenState && !isFullscreen && fullscreenElement) {
263
- exitFullscreen();
264
- }
265
- lastFullscreenState = isFullscreen;
266
- })
267
- .catch(() => {});
268
- }, 500);
269
284
  }
270
285
 
271
286
  initFullscreenPolyfill();
@@ -29,6 +29,16 @@ function zoomOut() {
29
29
  zoomCommon((currentZoom) => `${Math.max(parseInt(currentZoom) - 10, 30)}%`);
30
30
  }
31
31
 
32
+ let pasteAsPlainTextPending = false;
33
+
34
+ function triggerPasteAsPlainText() {
35
+ pasteAsPlainTextPending = true;
36
+ document.execCommand("paste");
37
+ setTimeout(() => {
38
+ pasteAsPlainTextPending = false;
39
+ }, 100);
40
+ }
41
+
32
42
  function handleShortcut(event) {
33
43
  if (shortcuts[event.key]) {
34
44
  event.preventDefault();
@@ -36,7 +46,6 @@ function handleShortcut(event) {
36
46
  }
37
47
  }
38
48
 
39
- // Configuration constants
40
49
  const DOWNLOADABLE_FILE_EXTENSIONS = {
41
50
  documents: [
42
51
  "pdf",
@@ -278,6 +287,22 @@ document.addEventListener("DOMContentLoaded", () => {
278
287
  });
279
288
  }
280
289
 
290
+ document.addEventListener(
291
+ "paste",
292
+ (event) => {
293
+ if (pasteAsPlainTextPending) {
294
+ event.preventDefault();
295
+ event.stopImmediatePropagation();
296
+
297
+ const text = event.clipboardData?.getData("text/plain") || "";
298
+ if (text) {
299
+ document.execCommand("insertText", false, text);
300
+ }
301
+ }
302
+ },
303
+ true,
304
+ );
305
+
281
306
  // Collect blob urls to blob by overriding window.URL.createObjectURL
282
307
  function collectUrlToBlobs() {
283
308
  const backupCreateObjectURL = window.URL.createObjectURL;
@@ -95,9 +95,10 @@ pub fn run_app() {
95
95
  app.app_handle(),
96
96
  show_system_tray,
97
97
  &pake_config.system_tray_path,
98
+ init_fullscreen,
98
99
  )
99
100
  .unwrap();
100
- set_global_shortcut(app.app_handle(), activation_shortcut).unwrap();
101
+ set_global_shortcut(app.app_handle(), activation_shortcut, init_fullscreen).unwrap();
101
102
 
102
103
  // Show window after state restoration to prevent position flashing
103
104
  // Unless start_to_tray is enabled, then keep it hidden
@@ -114,6 +115,12 @@ pub fn run_app() {
114
115
  window_clone.set_fullscreen(true).unwrap();
115
116
  // Ensure webview maintains focus for input after fullscreen
116
117
  let _ = window_clone.set_focus();
118
+ } else {
119
+ // Fix: Ubuntu 24.04/GNOME window buttons non-functional until resize (#1122)
120
+ // The window manager needs time to process the MapWindow event before
121
+ // accepting focus requests. Without this, decorations remain non-interactive.
122
+ tokio::time::sleep(tokio::time::Duration::from_millis(30)).await;
123
+ let _ = window_clone.set_focus();
117
124
  }
118
125
  }
119
126
  });
@@ -156,16 +163,16 @@ pub fn run_app() {
156
163
  })
157
164
  .build(tauri::generate_context!())
158
165
  .expect("error while building tauri application")
159
- .run(|app, event| {
166
+ .run(|_app, _event| {
160
167
  // Handle macOS dock icon click to reopen hidden window
161
168
  #[cfg(target_os = "macos")]
162
169
  if let tauri::RunEvent::Reopen {
163
170
  has_visible_windows,
164
171
  ..
165
- } = event
172
+ } = _event
166
173
  {
167
174
  if !has_visible_windows {
168
- if let Some(window) = app.get_webview_window("pake") {
175
+ if let Some(window) = _app.get_webview_window("pake") {
169
176
  let _ = window.show();
170
177
  let _ = window.set_focus();
171
178
  }
@@ -1 +0,0 @@
1
- <html><body><h1>Hello Pake</h1></body></html>
@@ -1,10 +0,0 @@
1
- [source.crates-io]
2
- replace-with = 'rsproxy-sparse'
3
- [source.rsproxy]
4
- registry = "https://rsproxy.cn/crates.io-index"
5
- [source.rsproxy-sparse]
6
- registry = "sparse+https://rsproxy.cn/index/"
7
- [registries.rsproxy]
8
- index = "https://rsproxy.cn/crates.io-index"
9
- [net]
10
- git-fetch-with-cli = true