pake-cli 2.2.6 → 2.3.1
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 +10 -10
- package/dist/cli.js +80 -23
- package/dist/dev.js +24 -22
- package/dist/dev.js.map +1 -1
- package/package.json +5 -2
- package/src-tauri/.pake/pake.json +29 -0
- package/src-tauri/.pake/tauri.conf.json +75 -0
- package/src-tauri/.pake/tauri.macos.conf.json +29 -0
- package/src-tauri/Cargo.toml +2 -0
- package/src-tauri/icons/figma.icns +0 -0
- package/src-tauri/icons/zbook.icns +0 -0
- package/src-tauri/pake.json +3 -2
- package/src-tauri/src/app/invoke.rs +29 -1
- package/src-tauri/src/app/window.rs +5 -3
- package/src-tauri/src/inject/custom.js +6 -0
- package/src-tauri/src/inject/event.js +96 -77
- package/src-tauri/src/inject/style.js +5 -0
- package/src-tauri/src/main.rs +5 -2
- package/src-tauri/src/util.rs +8 -1
- package/src-tauri/tauri.conf.json +1 -1
- package/dist/.gitkeep +0 -0
- package/dist/about_pake.html +0 -16
- package/dist/cli.dev.js +0 -1055
- package/dist/cli.dev.js.map +0 -1
- package/src-tauri/.cargo/config +0 -14
|
@@ -58,6 +58,10 @@ function externalTargetLink() {
|
|
|
58
58
|
return ['zbook.lol'].indexOf(location.hostname) > -1;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
function externalSelfLink() {
|
|
62
|
+
return ['twitter.com', 'www.zhihu.com'].indexOf(location.hostname) > -1;
|
|
63
|
+
}
|
|
64
|
+
|
|
61
65
|
document.addEventListener('DOMContentLoaded', () => {
|
|
62
66
|
const tauri = window.__TAURI__;
|
|
63
67
|
const appWindow = tauri.window.appWindow;
|
|
@@ -68,6 +72,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
68
72
|
document.body.appendChild(topDom);
|
|
69
73
|
const domEl = document.getElementById('pack-top-dom');
|
|
70
74
|
|
|
75
|
+
domEl.addEventListener('touchstart', () => {
|
|
76
|
+
appWindow.startDragging().then();
|
|
77
|
+
});
|
|
78
|
+
|
|
71
79
|
domEl.addEventListener('mousedown', (e) => {
|
|
72
80
|
e.preventDefault();
|
|
73
81
|
if (e.buttons === 1 && e.detail !== 2) {
|
|
@@ -75,10 +83,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
75
83
|
}
|
|
76
84
|
});
|
|
77
85
|
|
|
78
|
-
domEl.addEventListener('touchstart', () => {
|
|
79
|
-
appWindow.startDragging().then();
|
|
80
|
-
});
|
|
81
|
-
|
|
82
86
|
domEl.addEventListener('dblclick', () => {
|
|
83
87
|
appWindow.isFullscreen().then((fullscreen) => {
|
|
84
88
|
appWindow.setFullscreen(!fullscreen).then();
|
|
@@ -94,7 +98,91 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
94
98
|
}
|
|
95
99
|
});
|
|
96
100
|
|
|
97
|
-
|
|
101
|
+
// Collect blob urls to blob by overriding window.URL.createObjectURL
|
|
102
|
+
function collectUrlToBlobs() {
|
|
103
|
+
const backupCreateObjectURL = window.URL.createObjectURL;
|
|
104
|
+
window.blobToUrlCaches = new Map();
|
|
105
|
+
window.URL.createObjectURL = (blob) => {
|
|
106
|
+
const url = backupCreateObjectURL.call(window.URL, blob);
|
|
107
|
+
window.blobToUrlCaches.set(url, blob);
|
|
108
|
+
return url;
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function convertBlobUrlToBinary(blobUrl) {
|
|
113
|
+
return new Promise((resolve) => {
|
|
114
|
+
const blob = window.blobToUrlCaches.get(blobUrl);
|
|
115
|
+
const reader = new FileReader();
|
|
116
|
+
|
|
117
|
+
reader.readAsArrayBuffer(blob);
|
|
118
|
+
reader.onload = () => {
|
|
119
|
+
resolve(Array.from(new Uint8Array(reader.result)));
|
|
120
|
+
};
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function downloadFromDataUri(dataURI, filename) {
|
|
125
|
+
const byteString = atob(dataURI.split(',')[1]);
|
|
126
|
+
// write the bytes of the string to an ArrayBuffer
|
|
127
|
+
const bufferArray = new ArrayBuffer(byteString.length);
|
|
128
|
+
|
|
129
|
+
// create a view into the buffer
|
|
130
|
+
const binary = new Uint8Array(bufferArray);
|
|
131
|
+
|
|
132
|
+
// set the bytes of the buffer to the correct values
|
|
133
|
+
for (let i = 0; i < byteString.length; i++) {
|
|
134
|
+
binary[i] = byteString.charCodeAt(i);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// write the ArrayBuffer to a binary, and you're done
|
|
138
|
+
invoke('download_file_by_binary', {
|
|
139
|
+
params: {
|
|
140
|
+
filename,
|
|
141
|
+
binary: Array.from(binary),
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function downloadFromBlobUrl(blobUrl, filename) {
|
|
147
|
+
convertBlobUrlToBinary(blobUrl).then((binary) => {
|
|
148
|
+
invoke('download_file_by_binary', {
|
|
149
|
+
params: {
|
|
150
|
+
filename,
|
|
151
|
+
binary,
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// detect blob download by createElement("a")
|
|
158
|
+
function detectDownloadByCreateAnchor() {
|
|
159
|
+
const createEle = document.createElement;
|
|
160
|
+
document.createElement = (el) => {
|
|
161
|
+
if (el !== 'a') return createEle.call(document, el);
|
|
162
|
+
const anchorEle = createEle.call(document, el);
|
|
163
|
+
|
|
164
|
+
// use addEventListener to avoid overriding the original click event.
|
|
165
|
+
anchorEle.addEventListener('click', (e) => {
|
|
166
|
+
const url = anchorEle.href;
|
|
167
|
+
const filename = anchorEle.download || getFilenameFromUrl(url);
|
|
168
|
+
if (window.blobToUrlCaches.has(url)) {
|
|
169
|
+
downloadFromBlobUrl(url, filename);
|
|
170
|
+
// case: download from dataURL -> convert dataURL ->
|
|
171
|
+
} else if (url.startsWith('data:')) {
|
|
172
|
+
downloadFromDataUri(url, filename);
|
|
173
|
+
} else if (!externalSelfLink()) {
|
|
174
|
+
handleExternalLink(e, url);
|
|
175
|
+
}
|
|
176
|
+
}, true);
|
|
177
|
+
|
|
178
|
+
return anchorEle;
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const isExternalLink = (link) => window.location.host !== link.host;
|
|
183
|
+
// process special download protocol['data:','blob:']
|
|
184
|
+
const isSpecialDownload = (url) => ['blob', 'data'].some(protocol => url.startsWith(protocol));
|
|
185
|
+
|
|
98
186
|
const isDownloadRequired = (url, anchorElement, e) =>
|
|
99
187
|
anchorElement.download || e.metaKey || e.ctrlKey || isDownloadLink(url);
|
|
100
188
|
|
|
@@ -111,18 +199,19 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
111
199
|
const detectAnchorElementClick = (e) => {
|
|
112
200
|
const anchorElement = e.target.closest('a');
|
|
113
201
|
if (anchorElement && anchorElement.href) {
|
|
202
|
+
anchorElement.target = '_self';
|
|
114
203
|
const hrefUrl = new URL(anchorElement.href);
|
|
115
204
|
const absoluteUrl = hrefUrl.href;
|
|
116
205
|
let filename = anchorElement.download || getFilenameFromUrl(absoluteUrl);
|
|
117
206
|
|
|
118
207
|
// Handling external link redirection.
|
|
119
|
-
if (isExternalLink(absoluteUrl
|
|
208
|
+
if (isExternalLink(absoluteUrl) && (['_blank', '_new'].includes(anchorElement.target) || externalTargetLink())) {
|
|
120
209
|
handleExternalLink(e, absoluteUrl);
|
|
121
210
|
return;
|
|
122
211
|
}
|
|
123
212
|
|
|
124
213
|
// Process download links for Rust to handle.
|
|
125
|
-
if (isDownloadRequired(absoluteUrl, anchorElement, e) && !externalDownLoadLink()) {
|
|
214
|
+
if (isDownloadRequired(absoluteUrl, anchorElement, e) && !externalDownLoadLink() && !isSpecialDownload(absoluteUrl)) {
|
|
126
215
|
handleDownloadLink(e, absoluteUrl, filename);
|
|
127
216
|
}
|
|
128
217
|
}
|
|
@@ -176,73 +265,3 @@ function getFilenameFromUrl(url) {
|
|
|
176
265
|
const urlPath = new URL(url).pathname;
|
|
177
266
|
return urlPath.substring(urlPath.lastIndexOf('/') + 1);
|
|
178
267
|
}
|
|
179
|
-
|
|
180
|
-
// Collect blob urls to blob by overriding window.URL.createObjectURL
|
|
181
|
-
function collectUrlToBlobs() {
|
|
182
|
-
const backupCreateObjectURL = window.URL.createObjectURL;
|
|
183
|
-
window.blobToUrlCaches = new Map();
|
|
184
|
-
window.URL.createObjectURL = (blob) => {
|
|
185
|
-
const url = backupCreateObjectURL.call(window.URL, blob);
|
|
186
|
-
window.blobToUrlCaches.set(url, blob);
|
|
187
|
-
return url;
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
function convertBlobUrlToBinary(blobUrl) {
|
|
192
|
-
return new Promise((resolve) => {
|
|
193
|
-
const blob = window.blobToUrlCaches.get(blobUrl);
|
|
194
|
-
const reader = new FileReader();
|
|
195
|
-
|
|
196
|
-
reader.readAsArrayBuffer(blob);
|
|
197
|
-
reader.onload = () => {
|
|
198
|
-
resolve(reader.result);
|
|
199
|
-
};
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
async function downloadFromBlobUrl(blobUrl, filename) {
|
|
204
|
-
try {
|
|
205
|
-
const tauri = window.__TAURI__;
|
|
206
|
-
const binary = await convertBlobUrlToBinary(blobUrl);
|
|
207
|
-
|
|
208
|
-
await tauri.fs.writeBinaryFile(filename, binary, {
|
|
209
|
-
dir: tauri.fs.BaseDirectory.Download,
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
const lang = getSystemLanguage();
|
|
213
|
-
window.pakeToast(lang === 'en' ? 'Download successful, saved to download directory~' : '下载成功,已保存到下载目录~');
|
|
214
|
-
} catch (error) {
|
|
215
|
-
console.error('Error downloading from Blob URL:', error);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
// detect blob download by createElement("a")
|
|
221
|
-
function detectDownloadByCreateAnchor() {
|
|
222
|
-
const originalCreateElement = document.createElement;
|
|
223
|
-
|
|
224
|
-
document.createElement = function(el, ...args) {
|
|
225
|
-
const element = originalCreateElement.call(this, el, ...args);
|
|
226
|
-
|
|
227
|
-
if (el === 'a') {
|
|
228
|
-
element.addEventListener('click', (event) => {
|
|
229
|
-
const url = element.href;
|
|
230
|
-
if (window.blobToUrlCaches.has(url)) {
|
|
231
|
-
// Prevent default 'click' event if a blob URL is detected
|
|
232
|
-
event.preventDefault();
|
|
233
|
-
const filename = element.download || getFilenameFromUrl(url);
|
|
234
|
-
downloadFromBlobUrl(url, filename);
|
|
235
|
-
}
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
return element;
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
// Determine the language of the current system.
|
|
245
|
-
function getSystemLanguage() {
|
|
246
|
-
const lang = navigator.language.substr(0, 2);
|
|
247
|
-
return lang === 'ch' ? 'ch' : 'en';
|
|
248
|
-
}
|
|
@@ -180,6 +180,11 @@ window.addEventListener('DOMContentLoaded', _event => {
|
|
|
180
180
|
visibility: hidden !important;
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
+
#__next > div.overflow-hidden.w-full.h-full .absolute.bottom-0.left-0.w-full > div.text-center.text-xs {
|
|
184
|
+
visibility: hidden !important;
|
|
185
|
+
height: 0px !important;
|
|
186
|
+
}
|
|
187
|
+
|
|
183
188
|
#react-root [data-testid="primaryColumn"] > div > div {
|
|
184
189
|
position: relative !important;
|
|
185
190
|
}
|
package/src-tauri/src/main.rs
CHANGED
|
@@ -7,7 +7,7 @@ mod app;
|
|
|
7
7
|
mod util;
|
|
8
8
|
|
|
9
9
|
use app::{invoke, menu, window};
|
|
10
|
-
use invoke::download_file;
|
|
10
|
+
use invoke::{download_file, download_file_by_binary};
|
|
11
11
|
use menu::{get_menu, menu_event_handle};
|
|
12
12
|
use tauri_plugin_window_state::Builder as windowStatePlugin;
|
|
13
13
|
use util::{get_data_dir, get_pake_config};
|
|
@@ -41,7 +41,10 @@ pub fn run_app() {
|
|
|
41
41
|
|
|
42
42
|
tauri_app
|
|
43
43
|
.plugin(windowStatePlugin::default().build())
|
|
44
|
-
.invoke_handler(tauri::generate_handler![
|
|
44
|
+
.invoke_handler(tauri::generate_handler![
|
|
45
|
+
download_file,
|
|
46
|
+
download_file_by_binary
|
|
47
|
+
])
|
|
45
48
|
.setup(|app| {
|
|
46
49
|
let _window = get_window(app, pake_config, data_dir);
|
|
47
50
|
// Prevent initial shaking
|
package/src-tauri/src/util.rs
CHANGED
|
@@ -4,9 +4,16 @@ use std::path::PathBuf;
|
|
|
4
4
|
use tauri::{api, Config, Window};
|
|
5
5
|
|
|
6
6
|
pub fn get_pake_config() -> (PakeConfig, Config) {
|
|
7
|
+
#[cfg(feature = "cli-build")]
|
|
8
|
+
let pake_config: PakeConfig = serde_json::from_str(include_str!("../.pake/pake.json"))
|
|
9
|
+
.expect("Failed to parse pake config");
|
|
10
|
+
#[cfg(not(feature = "cli-build"))]
|
|
7
11
|
let pake_config: PakeConfig =
|
|
8
12
|
serde_json::from_str(include_str!("../pake.json")).expect("Failed to parse pake config");
|
|
9
|
-
|
|
13
|
+
#[cfg(feature = "cli-build")]
|
|
14
|
+
let tauri_config: Config = serde_json::from_str(include_str!("../.pake/tauri.conf.json"))
|
|
15
|
+
.expect("Failed to parse tauri config");
|
|
16
|
+
#[cfg(not(feature = "cli-build"))]
|
|
10
17
|
let tauri_config: Config = serde_json::from_str(include_str!("../tauri.conf.json"))
|
|
11
18
|
.expect("Failed to parse tauri config");
|
|
12
19
|
|
package/dist/.gitkeep
DELETED
|
File without changes
|
package/dist/about_pake.html
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<title>Document</title>
|
|
7
|
-
</head>
|
|
8
|
-
<body>
|
|
9
|
-
<h5>Welcome from Pake!</h5>
|
|
10
|
-
<p>version: 1.0.9</p>
|
|
11
|
-
<a href="https://github.com/tw93/Pake">Project link</a><br>
|
|
12
|
-
<a href="https://github.com/tw93/Pake/discussions">Discussions</a><br>
|
|
13
|
-
<a href="https://github.com/tw93/Pake/issues" >Issues</a><br>
|
|
14
|
-
<p>LICENSE: MIT</p>
|
|
15
|
-
</body>
|
|
16
|
-
</html>
|