pake-cli 3.11.9 โ†’ 3.11.10

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.
@@ -0,0 +1,20 @@
1
+ Pake Output Exception
2
+
3
+ This is an exception to the GNU General Public License version 3 (GPLv3),
4
+ under which Pake is licensed (see the LICENSE file).
5
+
6
+ As an additional permission under section 7 of the GPLv3:
7
+
8
+ When you use Pake, or a build of Pake produced by the standard Pake build
9
+ and packaging process, to generate a target application ("Pake Output"),
10
+ the portions of Pake incorporated into that Pake Output do not by
11
+ themselves cause the Pake Output as a whole to be or become subject to the
12
+ GPLv3. You may distribute such Pake Output under license terms of your own
13
+ choosing, including proprietary terms.
14
+
15
+ This permission does NOT apply to Pake itself or to any modified version of
16
+ Pake's own source code: anyone who distributes Pake, or a work derived from
17
+ Pake's source code beyond the configuration and packaging performed by the
18
+ standard build process, remains fully bound by the GPLv3.
19
+
20
+ Copyright (c) 2024 Tw93 and the Pake contributors.
package/README.md CHANGED
@@ -202,12 +202,17 @@ Pake's development can not be without these Hackers. They contributed a lot of c
202
202
 
203
203
  ## Support
204
204
 
205
+ - The most direct way to support me is getting [Mole for Mac](https://mole.fit), my paid Mac cleanup app.
205
206
  - If Pake helped you, [share it](https://twitter.com/intent/tweet?url=https://github.com/tw93/Pake&text=Pake%20-%20Turn%20any%20webpage%20into%20a%20desktop%20app%20with%20one%20command.%20Nearly%2020x%20smaller%20than%20Electron%20packages,%20supports%20macOS%20Windows%20Linux) with friends or give it a star.
206
207
  - Got ideas or bugs? Open an issue or PR, feel free to contribute your best AI model.
207
208
  - I have two cats, TangYuan and Coke. If you think Pake delights your life, you can feed them <a href="https://cats.tw93.fun?name=Pake" target="_blank">canned food ๐Ÿฅฉ</a>.
208
209
 
210
+ <details>
211
+ <summary>These lovely people already did ๐Ÿฑ</summary>
212
+ <br/>
209
213
  <a href="https://cats.tw93.fun?name=Pake"><img src="https://cdn.jsdelivr.net/gh/tw93/sponsors@main/assets/sponsors.svg" width="1000" loading="lazy" /></a>
214
+ </details>
210
215
 
211
216
  ## License
212
217
 
213
- Pake is open source under GPL-3.0, see [LICENSE](./LICENSE); apps you build with Pake are entirely yours to use and distribute. If you fork Pake into your own product, to avoid confusion please give it a different name and credit Pake as the source.
218
+ Pake is open source under GPL-3.0, see [LICENSE](./LICENSE) and [Pake Output Exception](./LICENSE-EXCEPTION); apps you build with Pake are entirely yours to use and distribute. If you fork Pake into your own product, to avoid confusion please give it a different name and credit Pake as the source.
package/dist/cli.js CHANGED
@@ -20,7 +20,7 @@ import { InvalidArgumentError, program as program$1, Option } from 'commander';
20
20
  import fs$1 from 'fs';
21
21
 
22
22
  var name = "pake-cli";
23
- var version = "3.11.9";
23
+ var version = "3.11.10";
24
24
  var description = "๐Ÿคฑ๐Ÿป Turn any webpage into a desktop app with one command. ๐Ÿคฑ๐Ÿป ไธ€้”ฎๆ‰“ๅŒ…็ฝ‘้กต็”Ÿๆˆ่ฝป้‡ๆกŒ้ขๅบ”็”จใ€‚";
25
25
  var engines = {
26
26
  node: ">=18.0.0"
@@ -46,6 +46,7 @@ var keywords = [
46
46
  "productivity"
47
47
  ];
48
48
  var files = [
49
+ "LICENSE-EXCEPTION",
49
50
  "dist",
50
51
  "src-tauri"
51
52
  ];
@@ -417,6 +418,9 @@ function filterLinuxTargets(targets) {
417
418
  const requested = targets.split(',').map((target) => target.trim());
418
419
  return LINUX_TARGET_TYPES.filter((target) => requested.includes(target));
419
420
  }
421
+ function needsTemporaryDebForZst(targets) {
422
+ return targets.includes('zst') && !targets.includes('deb');
423
+ }
420
424
 
421
425
  /**
422
426
  * Pure transform from CLI options to the window-config slice that gets
@@ -1407,11 +1411,16 @@ class LinuxBuilder extends BaseBuilder {
1407
1411
  if (targets.length === 0) {
1408
1412
  throw new Error(`No valid Linux target in "${this.options.targets}". Valid targets: ${LINUX_TARGET_TYPES.join(', ')}.`);
1409
1413
  }
1414
+ const useTemporaryDebForZst = needsTemporaryDebForZst(targets);
1410
1415
  for (const target of targets) {
1411
1416
  this.currentBuildType = target;
1412
1417
  if (target === 'zst') {
1413
- await this.buildAndCopy(url, 'deb', false);
1414
- await this.createArchPackageFromDeb();
1418
+ if (useTemporaryDebForZst) {
1419
+ await this.buildAndCopy(url, 'deb', false);
1420
+ }
1421
+ await this.createArchPackageFromDeb({
1422
+ removeSourceDeb: useTemporaryDebForZst,
1423
+ });
1415
1424
  }
1416
1425
  else {
1417
1426
  await this.buildAndCopy(url, target);
@@ -1432,7 +1441,7 @@ class LinuxBuilder extends BaseBuilder {
1432
1441
  }
1433
1442
  }
1434
1443
  }
1435
- async createArchPackageFromDeb() {
1444
+ async createArchPackageFromDeb({ removeSourceDeb, }) {
1436
1445
  const { name = 'pake-app' } = this.options;
1437
1446
  const packageName = generateLinuxPackageName(name);
1438
1447
  const version = tauriConfig.version;
@@ -1493,11 +1502,13 @@ post_remove() {
1493
1502
  }
1494
1503
  `);
1495
1504
  await shellExec(`bsdtar --zstd -cf "${packagePath}" -C "${dataDir}" .PKGINFO .INSTALL usr`);
1496
- await fsExtra.remove(debPath);
1497
1505
  logger.success('โœ” Build success!');
1498
1506
  logger.success('โœ” App installer located in', packagePath);
1499
1507
  }
1500
1508
  finally {
1509
+ if (removeSourceDeb) {
1510
+ await fsExtra.remove(debPath);
1511
+ }
1501
1512
  await fsExtra.remove(workDir);
1502
1513
  }
1503
1514
  }
@@ -2540,6 +2551,9 @@ const DEFAULT_PAKE_OPTIONS = {
2540
2551
  };
2541
2552
 
2542
2553
  function validateNumberInput(value) {
2554
+ if (value.trim() === '') {
2555
+ throw new InvalidArgumentError('Not a number.');
2556
+ }
2543
2557
  const parsedValue = Number(value);
2544
2558
  if (!Number.isFinite(parsedValue)) {
2545
2559
  throw new InvalidArgumentError('Not a number.');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pake-cli",
3
- "version": "3.11.9",
3
+ "version": "3.11.10",
4
4
  "description": "๐Ÿคฑ๐Ÿป Turn any webpage into a desktop app with one command. ๐Ÿคฑ๐Ÿป ไธ€้”ฎๆ‰“ๅŒ…็ฝ‘้กต็”Ÿๆˆ่ฝป้‡ๆกŒ้ขๅบ”็”จใ€‚",
5
5
  "engines": {
6
6
  "node": ">=18.0.0"
@@ -26,6 +26,7 @@
26
26
  "productivity"
27
27
  ],
28
28
  "files": [
29
+ "LICENSE-EXCEPTION",
29
30
  "dist",
30
31
  "src-tauri"
31
32
  ],
@@ -2564,7 +2564,7 @@ dependencies = [
2564
2564
 
2565
2565
  [[package]]
2566
2566
  name = "pake"
2567
- version = "3.11.9"
2567
+ version = "3.11.10"
2568
2568
  dependencies = [
2569
2569
  "objc2",
2570
2570
  "objc2-app-kit",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "pake"
3
- version = "3.11.9"
3
+ version = "3.11.10"
4
4
  description = "๐Ÿคฑ๐Ÿป Turn any webpage into a desktop app with Rust."
5
5
  authors = ["Tw93"]
6
6
  license = "GPL-3.0-or-later"
@@ -272,6 +272,33 @@ function shouldBypassPakeLinkHandling(rawHref) {
272
272
  );
273
273
  }
274
274
 
275
+ function shouldNavigateAuthInCurrentWindow() {
276
+ return /macintosh|mac os x/i.test(navigator.userAgent);
277
+ }
278
+
279
+ function canNavigateAuthUrl(url) {
280
+ const normalizedUrl = normalizeAnchorHref(url).toLowerCase();
281
+ return normalizedUrl !== "" && normalizedUrl !== "about:blank";
282
+ }
283
+
284
+ function navigateInCurrentWindow(url) {
285
+ window.location.href = url;
286
+ return window;
287
+ }
288
+
289
+ function openAuthNavigation(originalWindowOpen, url, name, specs) {
290
+ if (shouldNavigateAuthInCurrentWindow() && canNavigateAuthUrl(url)) {
291
+ return navigateInCurrentWindow(url);
292
+ }
293
+
294
+ const authWindow = originalWindowOpen.call(window, url, name, specs);
295
+ if (!authWindow) {
296
+ return navigateInCurrentWindow(url);
297
+ }
298
+
299
+ return authWindow;
300
+ }
301
+
275
302
  document.addEventListener("DOMContentLoaded", () => {
276
303
  const tauri = window.__TAURI__;
277
304
  const appWindow = tauri.window.getCurrentWindow();
@@ -440,16 +467,12 @@ document.addEventListener("DOMContentLoaded", () => {
440
467
  e.preventDefault();
441
468
  e.stopImmediatePropagation();
442
469
 
443
- const authWindow = originalWindowOpen.call(
444
- window,
470
+ openAuthNavigation(
471
+ originalWindowOpen,
445
472
  absoluteUrl,
446
473
  "_blank",
447
474
  "width=1200,height=800,scrollbars=yes,resizable=yes",
448
475
  );
449
-
450
- if (!authWindow) {
451
- window.location.href = absoluteUrl;
452
- }
453
476
  }
454
477
 
455
478
  return;
@@ -544,9 +567,15 @@ document.addEventListener("DOMContentLoaded", () => {
544
567
  return originalWindowOpen.call(window, url, name, specs);
545
568
  }
546
569
 
547
- // Allow authentication popups to open normally
570
+ // Avoid macOS WebKit auth-popup crashes by navigating auth URLs in-place.
548
571
  if (window.isAuthPopup(url, name)) {
549
- return originalWindowOpen.call(window, url, name, specs);
572
+ try {
573
+ const baseUrl = window.location.origin + window.location.pathname;
574
+ const absoluteUrl = new URL(url, baseUrl).href;
575
+ return openAuthNavigation(originalWindowOpen, absoluteUrl, name, specs);
576
+ } catch (error) {
577
+ return openAuthNavigation(originalWindowOpen, url, name, specs);
578
+ }
550
579
  }
551
580
 
552
581
  try {
@@ -10,6 +10,12 @@ use tauri_plugin_window_state::StateFlags;
10
10
  use std::time::Duration;
11
11
 
12
12
  const WINDOW_SHOW_DELAY: u64 = 50;
13
+ #[cfg(target_os = "linux")]
14
+ const PAKE_LINUX_WEBKIT_SAFE_MODE: &str = "PAKE_LINUX_WEBKIT_SAFE_MODE";
15
+ #[cfg(target_os = "linux")]
16
+ const WEBKIT_DISABLE_DMABUF_RENDERER: &str = "WEBKIT_DISABLE_DMABUF_RENDERER";
17
+ #[cfg(target_os = "linux")]
18
+ const WEBKIT_DISABLE_COMPOSITING_MODE: &str = "WEBKIT_DISABLE_COMPOSITING_MODE";
13
19
 
14
20
  use app::{
15
21
  invoke::{
@@ -21,16 +27,83 @@ use app::{
21
27
  };
22
28
  use util::get_pake_config;
23
29
 
30
+ #[cfg(any(target_os = "linux", test))]
31
+ fn is_disabled_env_value(value: &str) -> bool {
32
+ matches!(
33
+ value.trim().to_ascii_lowercase().as_str(),
34
+ "0" | "false" | "off" | "no" | "native" | "disabled"
35
+ )
36
+ }
37
+
38
+ #[cfg(any(target_os = "linux", test))]
39
+ fn is_non_empty_env_value(value: Option<&str>) -> bool {
40
+ value.map(|value| !value.trim().is_empty()).unwrap_or(false)
41
+ }
42
+
43
+ #[cfg(any(target_os = "linux", test))]
44
+ fn contains_niri(value: &str) -> bool {
45
+ value
46
+ .split([':', ';', ',', ' '])
47
+ .any(|part| part.eq_ignore_ascii_case("niri"))
48
+ }
49
+
50
+ #[cfg(any(target_os = "linux", test))]
51
+ fn should_enable_linux_webkit_safe_mode_from_values(
52
+ safe_mode: Option<&str>,
53
+ niri_socket: Option<&str>,
54
+ desktop_values: &[Option<&str>],
55
+ ) -> bool {
56
+ if let Some(value) = safe_mode.filter(|value| !value.trim().is_empty()) {
57
+ return !is_disabled_env_value(value);
58
+ }
59
+
60
+ let is_niri_session = is_non_empty_env_value(niri_socket)
61
+ || desktop_values
62
+ .iter()
63
+ .flatten()
64
+ .any(|value| contains_niri(value));
65
+
66
+ !is_niri_session
67
+ }
68
+
69
+ #[cfg(target_os = "linux")]
70
+ fn apply_linux_webkit_runtime_flags() {
71
+ let safe_mode = std::env::var(PAKE_LINUX_WEBKIT_SAFE_MODE).ok();
72
+ if safe_mode.as_deref().is_some_and(is_disabled_env_value) {
73
+ std::env::remove_var(WEBKIT_DISABLE_DMABUF_RENDERER);
74
+ std::env::remove_var(WEBKIT_DISABLE_COMPOSITING_MODE);
75
+ return;
76
+ }
77
+
78
+ let desktop_values = [
79
+ std::env::var("XDG_CURRENT_DESKTOP").ok(),
80
+ std::env::var("XDG_SESSION_DESKTOP").ok(),
81
+ std::env::var("DESKTOP_SESSION").ok(),
82
+ ];
83
+ let desktop_refs = desktop_values
84
+ .iter()
85
+ .map(|value| value.as_deref())
86
+ .collect::<Vec<_>>();
87
+
88
+ if !should_enable_linux_webkit_safe_mode_from_values(
89
+ safe_mode.as_deref(),
90
+ std::env::var("NIRI_SOCKET").ok().as_deref(),
91
+ &desktop_refs,
92
+ ) {
93
+ return;
94
+ }
95
+
96
+ if std::env::var(WEBKIT_DISABLE_DMABUF_RENDERER).is_err() {
97
+ std::env::set_var(WEBKIT_DISABLE_DMABUF_RENDERER, "1");
98
+ }
99
+ if std::env::var(WEBKIT_DISABLE_COMPOSITING_MODE).is_err() {
100
+ std::env::set_var(WEBKIT_DISABLE_COMPOSITING_MODE, "1");
101
+ }
102
+ }
103
+
24
104
  pub fn run_app() {
25
105
  #[cfg(target_os = "linux")]
26
- {
27
- if std::env::var("WEBKIT_DISABLE_DMABUF_RENDERER").is_err() {
28
- std::env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "1");
29
- }
30
- if std::env::var("WEBKIT_DISABLE_COMPOSITING_MODE").is_err() {
31
- std::env::set_var("WEBKIT_DISABLE_COMPOSITING_MODE", "1");
32
- }
33
- }
106
+ apply_linux_webkit_runtime_flags();
34
107
 
35
108
  let (pake_config, tauri_config) = get_pake_config();
36
109
  let tauri_app = tauri::Builder::default();
@@ -202,3 +275,58 @@ pub fn run_app() {
202
275
  pub fn run() {
203
276
  run_app()
204
277
  }
278
+
279
+ #[cfg(test)]
280
+ mod tests {
281
+ use super::*;
282
+
283
+ #[test]
284
+ fn linux_webkit_safe_mode_stays_on_by_default() {
285
+ assert!(should_enable_linux_webkit_safe_mode_from_values(
286
+ None,
287
+ None,
288
+ &[None, None, None]
289
+ ));
290
+ }
291
+
292
+ #[test]
293
+ fn linux_webkit_safe_mode_is_disabled_for_niri_socket() {
294
+ assert!(!should_enable_linux_webkit_safe_mode_from_values(
295
+ None,
296
+ Some("/run/user/501/niri.sock"),
297
+ &[None, None, None]
298
+ ));
299
+ }
300
+
301
+ #[test]
302
+ fn linux_webkit_safe_mode_is_disabled_for_niri_desktop() {
303
+ assert!(!should_enable_linux_webkit_safe_mode_from_values(
304
+ None,
305
+ None,
306
+ &[Some("niri"), None, None]
307
+ ));
308
+ }
309
+
310
+ #[test]
311
+ fn linux_webkit_safe_mode_can_be_forced_on_for_niri() {
312
+ assert!(should_enable_linux_webkit_safe_mode_from_values(
313
+ Some("1"),
314
+ Some("/run/user/501/niri.sock"),
315
+ &[Some("niri"), None, None]
316
+ ));
317
+ }
318
+
319
+ #[test]
320
+ fn linux_webkit_safe_mode_can_be_disabled_explicitly() {
321
+ for value in ["0", "false", "off", "no", "native", "disabled"] {
322
+ assert!(
323
+ !should_enable_linux_webkit_safe_mode_from_values(
324
+ Some(value),
325
+ None,
326
+ &[None, None, None]
327
+ ),
328
+ "expected {value} to disable safe mode"
329
+ );
330
+ }
331
+ }
332
+ }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "productName": "Weekly",
3
3
  "identifier": "com.pake.weekly",
4
- "version": "3.11.9",
4
+ "version": "3.11.10",
5
5
  "app": {
6
6
  "withGlobalTauri": true,
7
7
  "trayIcon": {