pake-cli 3.15.6 โ 3.15.7
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/dist/cli.js +55 -11
- package/package.json +2 -3
- package/src-tauri/Cargo.lock +6 -5
- package/src-tauri/Cargo.toml +6 -1
- package/src-tauri/src/app/window.rs +24 -18
- package/src-tauri/tauri.conf.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -14,16 +14,14 @@ import fs from 'fs';
|
|
|
14
14
|
import fs$1 from 'fs/promises';
|
|
15
15
|
import { dir } from 'tmp-promise';
|
|
16
16
|
import { fileTypeFromBuffer } from 'file-type';
|
|
17
|
-
import icongen from 'icon-gen';
|
|
18
|
-
import sharp from 'sharp';
|
|
19
17
|
import * as psl from 'psl';
|
|
20
18
|
import { InvalidArgumentError, program as program$1, Option } from 'commander';
|
|
21
19
|
|
|
22
20
|
var name = "pake-cli";
|
|
23
|
-
var version = "3.15.
|
|
21
|
+
var version = "3.15.7";
|
|
24
22
|
var description = "๐คฑ๐ป Turn any webpage into a desktop app with one command. ๐คฑ๐ป ไธ้ฎๆๅ
็ฝ้กต็ๆ่ฝป้ๆก้ขๅบ็จใ";
|
|
25
23
|
var engines = {
|
|
26
|
-
node: ">=20.
|
|
24
|
+
node: ">=20.9.0"
|
|
27
25
|
};
|
|
28
26
|
var packageManager = "pnpm@10.26.2";
|
|
29
27
|
var bin = {
|
|
@@ -80,7 +78,6 @@ var dependencies = {
|
|
|
80
78
|
execa: "^9.6.1",
|
|
81
79
|
"file-type": "^21.3.4",
|
|
82
80
|
"fs-extra": "^11.3.3",
|
|
83
|
-
"icon-gen": "^5.0.0",
|
|
84
81
|
loglevel: "^1.9.2",
|
|
85
82
|
ora: "^9.3.0",
|
|
86
83
|
prompts: "^2.4.2",
|
|
@@ -2114,6 +2111,9 @@ function getIconSourcePriority(url, appName) {
|
|
|
2114
2111
|
: ['domain', 'dashboard'];
|
|
2115
2112
|
}
|
|
2116
2113
|
|
|
2114
|
+
async function loadSharp$1() {
|
|
2115
|
+
return (await import('sharp')).default;
|
|
2116
|
+
}
|
|
2117
2117
|
const ICO_HEADER_SIZE = 6;
|
|
2118
2118
|
const ICO_DIR_ENTRY_SIZE = 16;
|
|
2119
2119
|
const ICO_TYPE_ICON = 1;
|
|
@@ -2247,6 +2247,7 @@ async function pickLargestFrameAsPng(buffer, entries) {
|
|
|
2247
2247
|
// Fallback: let sharp render directly from the ICO buffer. sharp picks the
|
|
2248
2248
|
// largest embedded frame on its own.
|
|
2249
2249
|
try {
|
|
2250
|
+
const sharp = await loadSharp$1();
|
|
2250
2251
|
return await sharp(buffer).png().toBuffer();
|
|
2251
2252
|
}
|
|
2252
2253
|
catch {
|
|
@@ -2268,6 +2269,7 @@ async function ensureMultiResolutionIco(sourcePath, outputPath, preferredSize =
|
|
|
2268
2269
|
if (!sourcePng) {
|
|
2269
2270
|
return await writeIcoWithPreferredSize(sourcePath, outputPath, preferredSize);
|
|
2270
2271
|
}
|
|
2272
|
+
const sharp = await loadSharp$1();
|
|
2271
2273
|
const frames = await Promise.all(desiredSizes.map(async (size) => {
|
|
2272
2274
|
// Reuse an existing exact-size PNG frame when possible to keep any
|
|
2273
2275
|
// hand-tuned small icon (e.g. a 16x16 with deliberate pixel hinting).
|
|
@@ -2334,6 +2336,9 @@ function buildIcoFromPngBuffers(frames) {
|
|
|
2334
2336
|
return output;
|
|
2335
2337
|
}
|
|
2336
2338
|
|
|
2339
|
+
async function loadSharp() {
|
|
2340
|
+
return (await import('sharp')).default;
|
|
2341
|
+
}
|
|
2337
2342
|
const ICON_CONFIG = {
|
|
2338
2343
|
minFileSize: 100,
|
|
2339
2344
|
supportedFormats: [
|
|
@@ -2354,8 +2359,20 @@ const ICON_CONFIG = {
|
|
|
2354
2359
|
const PLATFORM_CONFIG = {
|
|
2355
2360
|
win: { format: '.ico', sizes: [...WIN_STANDARD_ICO_SIZES] },
|
|
2356
2361
|
linux: { format: '.png', size: 512 },
|
|
2357
|
-
macos: { format: '.icns'
|
|
2362
|
+
macos: { format: '.icns' },
|
|
2358
2363
|
};
|
|
2364
|
+
const MACOS_ICONSET_FILES = [
|
|
2365
|
+
['icon_16x16.png', 16],
|
|
2366
|
+
['icon_16x16@2x.png', 32],
|
|
2367
|
+
['icon_32x32.png', 32],
|
|
2368
|
+
['icon_32x32@2x.png', 64],
|
|
2369
|
+
['icon_128x128.png', 128],
|
|
2370
|
+
['icon_128x128@2x.png', 256],
|
|
2371
|
+
['icon_256x256.png', 256],
|
|
2372
|
+
['icon_256x256@2x.png', 512],
|
|
2373
|
+
['icon_512x512.png', 512],
|
|
2374
|
+
['icon_512x512@2x.png', 1024],
|
|
2375
|
+
];
|
|
2359
2376
|
const API_KEYS = {
|
|
2360
2377
|
logoDev: ['pk_JLLMUKGZRpaG5YclhXaTkg', 'pk_Ph745P8mQSeYFfW2Wk039A'],
|
|
2361
2378
|
brandfetch: ['1idqvJC0CeFSeyp3Yf7', '1idej-yhU_ThggIHFyG'],
|
|
@@ -2414,6 +2431,7 @@ async function preprocessIcon(inputPath) {
|
|
|
2414
2431
|
if (!shouldNormalize) {
|
|
2415
2432
|
return inputPath;
|
|
2416
2433
|
}
|
|
2434
|
+
const sharp = await loadSharp();
|
|
2417
2435
|
const { path: tempDir } = await dir();
|
|
2418
2436
|
const outputPath = path.join(tempDir, 'icon-normalized.png');
|
|
2419
2437
|
await sharp(inputPath).ensureAlpha().png().toFile(outputPath);
|
|
@@ -2431,6 +2449,7 @@ async function preprocessIcon(inputPath) {
|
|
|
2431
2449
|
*/
|
|
2432
2450
|
async function applyMacOSMask(inputPath) {
|
|
2433
2451
|
try {
|
|
2452
|
+
const sharp = await loadSharp();
|
|
2434
2453
|
const { path: tempDir } = await dir();
|
|
2435
2454
|
const outputPath = path.join(tempDir, 'icon-macos-rounded.png');
|
|
2436
2455
|
// 1. Create a 1024x1024 rounded rect mask
|
|
@@ -2474,6 +2493,32 @@ async function applyMacOSMask(inputPath) {
|
|
|
2474
2493
|
return inputPath;
|
|
2475
2494
|
}
|
|
2476
2495
|
}
|
|
2496
|
+
async function generateMacOSIcns(inputPath, outputDir, iconName) {
|
|
2497
|
+
const sharp = await loadSharp();
|
|
2498
|
+
const iconsetPath = path.join(outputDir, `${iconName}.iconset`);
|
|
2499
|
+
const outputPath = path.join(outputDir, `${iconName}${PLATFORM_CONFIG.macos.format}`);
|
|
2500
|
+
await fsExtra.ensureDir(iconsetPath);
|
|
2501
|
+
const source = sharp(inputPath);
|
|
2502
|
+
await Promise.all(MACOS_ICONSET_FILES.map(async ([fileName, size]) => {
|
|
2503
|
+
await source
|
|
2504
|
+
.clone()
|
|
2505
|
+
.resize(size, size, {
|
|
2506
|
+
fit: 'contain',
|
|
2507
|
+
background: ICON_CONFIG.transparentBackground,
|
|
2508
|
+
})
|
|
2509
|
+
.ensureAlpha()
|
|
2510
|
+
.png()
|
|
2511
|
+
.toFile(path.join(iconsetPath, fileName));
|
|
2512
|
+
}));
|
|
2513
|
+
await execa('/usr/bin/iconutil', [
|
|
2514
|
+
'-c',
|
|
2515
|
+
'icns',
|
|
2516
|
+
iconsetPath,
|
|
2517
|
+
'-o',
|
|
2518
|
+
outputPath,
|
|
2519
|
+
]);
|
|
2520
|
+
return outputPath;
|
|
2521
|
+
}
|
|
2477
2522
|
/**
|
|
2478
2523
|
* Converts icon to platform-specific format
|
|
2479
2524
|
*/
|
|
@@ -2488,6 +2533,7 @@ async function convertIconFormat(inputPath, appName) {
|
|
|
2488
2533
|
const iconName = getIconBaseName(appName);
|
|
2489
2534
|
// Generate platform-specific format
|
|
2490
2535
|
if (IS_WIN) {
|
|
2536
|
+
const sharp = await loadSharp();
|
|
2491
2537
|
const icoPath = path.join(platformOutputDir, `${iconName}_256${PLATFORM_CONFIG.win.format}`);
|
|
2492
2538
|
const sourceBuffer = await fsExtra.readFile(processedInputPath);
|
|
2493
2539
|
const frames = await Promise.all(PLATFORM_CONFIG.win.sizes.map(async (size) => {
|
|
@@ -2506,6 +2552,7 @@ async function convertIconFormat(inputPath, appName) {
|
|
|
2506
2552
|
return icoPath;
|
|
2507
2553
|
}
|
|
2508
2554
|
if (IS_LINUX) {
|
|
2555
|
+
const sharp = await loadSharp();
|
|
2509
2556
|
const outputPath = path.join(platformOutputDir, `${iconName}_${PLATFORM_CONFIG.linux.size}${PLATFORM_CONFIG.linux.format}`);
|
|
2510
2557
|
// Ensure we convert to proper PNG format with correct size
|
|
2511
2558
|
await sharp(processedInputPath)
|
|
@@ -2520,11 +2567,7 @@ async function convertIconFormat(inputPath, appName) {
|
|
|
2520
2567
|
}
|
|
2521
2568
|
// macOS
|
|
2522
2569
|
const macIconPath = await applyMacOSMask(processedInputPath);
|
|
2523
|
-
await
|
|
2524
|
-
report: false,
|
|
2525
|
-
icns: { name: iconName, sizes: PLATFORM_CONFIG.macos.sizes },
|
|
2526
|
-
});
|
|
2527
|
-
const outputPath = path.join(platformOutputDir, `${iconName}${PLATFORM_CONFIG.macos.format}`);
|
|
2570
|
+
const outputPath = await generateMacOSIcns(macIconPath, platformOutputDir, iconName);
|
|
2528
2571
|
return (await fsExtra.pathExists(outputPath)) ? outputPath : null;
|
|
2529
2572
|
}
|
|
2530
2573
|
catch (error) {
|
|
@@ -2539,6 +2582,7 @@ async function isLinuxBundleIconReady(iconPath) {
|
|
|
2539
2582
|
return false;
|
|
2540
2583
|
}
|
|
2541
2584
|
try {
|
|
2585
|
+
const sharp = await loadSharp();
|
|
2542
2586
|
const { width, height } = await sharp(iconPath).metadata();
|
|
2543
2587
|
return (width === PLATFORM_CONFIG.linux.size &&
|
|
2544
2588
|
height === PLATFORM_CONFIG.linux.size);
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pake-cli",
|
|
3
|
-
"version": "3.15.
|
|
3
|
+
"version": "3.15.7",
|
|
4
4
|
"description": "๐คฑ๐ป Turn any webpage into a desktop app with one command. ๐คฑ๐ป ไธ้ฎๆๅ
็ฝ้กต็ๆ่ฝป้ๆก้ขๅบ็จใ",
|
|
5
5
|
"engines": {
|
|
6
|
-
"node": ">=20.
|
|
6
|
+
"node": ">=20.9.0"
|
|
7
7
|
},
|
|
8
8
|
"packageManager": "pnpm@10.26.2",
|
|
9
9
|
"bin": {
|
|
@@ -60,7 +60,6 @@
|
|
|
60
60
|
"execa": "^9.6.1",
|
|
61
61
|
"file-type": "^21.3.4",
|
|
62
62
|
"fs-extra": "^11.3.3",
|
|
63
|
-
"icon-gen": "^5.0.0",
|
|
64
63
|
"loglevel": "^1.9.2",
|
|
65
64
|
"ora": "^9.3.0",
|
|
66
65
|
"prompts": "^2.4.2",
|
package/src-tauri/Cargo.lock
CHANGED
|
@@ -2564,13 +2564,14 @@ dependencies = [
|
|
|
2564
2564
|
|
|
2565
2565
|
[[package]]
|
|
2566
2566
|
name = "pake"
|
|
2567
|
-
version = "3.15.
|
|
2567
|
+
version = "3.15.7"
|
|
2568
2568
|
dependencies = [
|
|
2569
2569
|
"block2",
|
|
2570
2570
|
"dispatch",
|
|
2571
2571
|
"objc2",
|
|
2572
2572
|
"objc2-app-kit",
|
|
2573
2573
|
"objc2-foundation",
|
|
2574
|
+
"objc2-web-kit",
|
|
2574
2575
|
"serde",
|
|
2575
2576
|
"serde_json",
|
|
2576
2577
|
"tauri",
|
|
@@ -3044,9 +3045,9 @@ dependencies = [
|
|
|
3044
3045
|
|
|
3045
3046
|
[[package]]
|
|
3046
3047
|
name = "quinn-proto"
|
|
3047
|
-
version = "0.11.
|
|
3048
|
+
version = "0.11.15"
|
|
3048
3049
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3049
|
-
checksum = "
|
|
3050
|
+
checksum = "4fcb935c5bec503c2f0e306bdd3e58bb9029dcb14fa8d9ac76e3a5256ac0763e"
|
|
3050
3051
|
dependencies = [
|
|
3051
3052
|
"bytes",
|
|
3052
3053
|
"getrandom 0.3.4",
|
|
@@ -3422,9 +3423,9 @@ dependencies = [
|
|
|
3422
3423
|
|
|
3423
3424
|
[[package]]
|
|
3424
3425
|
name = "rustls-webpki"
|
|
3425
|
-
version = "0.103.
|
|
3426
|
+
version = "0.103.13"
|
|
3426
3427
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3427
|
-
checksum = "
|
|
3428
|
+
checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e"
|
|
3428
3429
|
dependencies = [
|
|
3429
3430
|
"ring",
|
|
3430
3431
|
"rustls-pki-types",
|
package/src-tauri/Cargo.toml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "pake"
|
|
3
|
-
version = "3.15.
|
|
3
|
+
version = "3.15.7"
|
|
4
4
|
description = "๐คฑ๐ป Turn any webpage into a desktop app with Rust."
|
|
5
5
|
authors = ["Tw93"]
|
|
6
6
|
license = "GPL-3.0-or-later"
|
|
@@ -41,6 +41,11 @@ dispatch = "0.2"
|
|
|
41
41
|
objc2 = "0.6"
|
|
42
42
|
objc2-app-kit = { version = "0.3", features = ["NSApplication", "NSDockTile"] }
|
|
43
43
|
objc2-foundation = { version = "0.3", features = ["NSString"] }
|
|
44
|
+
objc2-web-kit = { version = "0.3", default-features = false, features = [
|
|
45
|
+
"std",
|
|
46
|
+
"WKUserContentController",
|
|
47
|
+
"WKWebViewConfiguration",
|
|
48
|
+
] }
|
|
44
49
|
|
|
45
50
|
[target.'cfg(target_os = "linux")'.dependencies]
|
|
46
51
|
# Used for native WebKitGTK go_back/go_forward on error pages (no page JS).
|
|
@@ -5,6 +5,10 @@ use crate::util::{
|
|
|
5
5
|
};
|
|
6
6
|
#[cfg(target_os = "macos")]
|
|
7
7
|
use dispatch::Queue;
|
|
8
|
+
#[cfg(target_os = "macos")]
|
|
9
|
+
use objc2::MainThreadMarker;
|
|
10
|
+
#[cfg(target_os = "macos")]
|
|
11
|
+
use objc2_web_kit::WKUserContentController;
|
|
8
12
|
#[cfg(target_os = "windows")]
|
|
9
13
|
use std::{os::windows::ffi::OsStrExt, ptr, sync::OnceLock};
|
|
10
14
|
use std::{
|
|
@@ -28,6 +32,24 @@ use tauri::Theme;
|
|
|
28
32
|
#[cfg(target_os = "macos")]
|
|
29
33
|
use tauri::TitleBarStyle;
|
|
30
34
|
|
|
35
|
+
#[cfg(target_os = "macos")]
|
|
36
|
+
fn prepare_macos_new_window_configuration(features: &NewWindowFeatures) -> tauri::Result<()> {
|
|
37
|
+
let mtm = MainThreadMarker::new().ok_or_else(|| {
|
|
38
|
+
std::io::Error::other("macOS new-window configuration must run on the main thread")
|
|
39
|
+
})?;
|
|
40
|
+
// WebKit requires the exact target configuration it supplied to be used
|
|
41
|
+
// for the new page. Replace only the inherited content controller so Wry
|
|
42
|
+
// can register Pake's IPC handler and scripts once on the new webview.
|
|
43
|
+
let controller = unsafe { WKUserContentController::new(mtm) };
|
|
44
|
+
unsafe {
|
|
45
|
+
features
|
|
46
|
+
.opener()
|
|
47
|
+
.target_configuration
|
|
48
|
+
.setUserContentController(&controller);
|
|
49
|
+
}
|
|
50
|
+
Ok(())
|
|
51
|
+
}
|
|
52
|
+
|
|
31
53
|
#[cfg(target_os = "windows")]
|
|
32
54
|
fn build_proxy_browser_arg(url: &Url) -> Option<String> {
|
|
33
55
|
let host = url.host_str()?;
|
|
@@ -594,26 +616,10 @@ fn build_window(
|
|
|
594
616
|
}
|
|
595
617
|
|
|
596
618
|
if let Some(features) = new_window_features {
|
|
597
|
-
// Reuse only opener-provided position/size on macOS; sharing the opener
|
|
598
|
-
// WKWebViewConfiguration triggers duplicate WKScriptMessageHandler
|
|
599
|
-
// registrations on macOS 26+ and crashes the app (issue #1194).
|
|
600
619
|
#[cfg(target_os = "macos")]
|
|
601
|
-
|
|
602
|
-
if let Some(position) = features.position() {
|
|
603
|
-
window_builder = window_builder.position(position.x, position.y);
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
if let Some(size) = features.size() {
|
|
607
|
-
window_builder = window_builder.inner_size(size.width, size.height);
|
|
608
|
-
}
|
|
620
|
+
prepare_macos_new_window_configuration(&features)?;
|
|
609
621
|
|
|
610
|
-
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
#[cfg(not(target_os = "macos"))]
|
|
614
|
-
{
|
|
615
|
-
window_builder = window_builder.window_features(features).focused(true);
|
|
616
|
-
}
|
|
622
|
+
window_builder = window_builder.window_features(features).focused(true);
|
|
617
623
|
}
|
|
618
624
|
|
|
619
625
|
// Capture webview-initiated downloads (blob:, data:, Content-Disposition,
|