single-file-cli 2.0.63 → 2.0.65

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,29 @@
1
+ name: Publish Docker image
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ docker:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ -
12
+ name: Set up QEMU
13
+ uses: docker/setup-qemu-action@v3
14
+ -
15
+ name: Set up Docker Buildx
16
+ uses: docker/setup-buildx-action@v3
17
+ -
18
+ name: Login to Docker Hub
19
+ uses: docker/login-action@v3
20
+ with:
21
+ username: ${{ secrets.DOCKER_USERNAME }}
22
+ password: ${{ secrets.DOCKER_TOKEN }}
23
+ -
24
+ name: Build and push
25
+ uses: docker/build-push-action@v6
26
+ with:
27
+ push: true
28
+ tags: ${{ secrets.DOCKER_USERNAME }}/singlefile:latest
29
+ platforms: linux/amd64,linux/arm64doc
package/build.sh CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env bash
2
2
 
3
- deno vendor "npm:single-file-core@1.5.32"
3
+ deno vendor "npm:single-file-core@1.5.35"
4
4
 
5
5
  echo "
6
6
  import { build } from 'npm:esbuild';
package/compile.sh CHANGED
@@ -8,7 +8,7 @@ deno compile --allow-read --allow-write --allow-net --allow-env --allow-run --ex
8
8
  deno compile --allow-read --allow-write --allow-net --allow-env --allow-run --ext=js --output=./dist/single-file-x86_64-apple-darwin --target=x86_64-apple-darwin ./single-file
9
9
  deno compile --allow-read --allow-write --allow-net --allow-env --allow-run --ext=js --output=./dist/single-file-x86_64-linux --target=x86_64-unknown-linux-gnu ./single-file
10
10
  deno compile --allow-read --allow-write --allow-net --allow-env --allow-run --ext=js --output=./dist/single-file-aarch64-linux --target=aarch64-unknown-linux-gnu ./single-file
11
- deno compile --allow-read --allow-write --allow-net --allow-env --allow-run --ext=js --output=./dist/single-file.exe --target=x86_64-pc-windows-msvc ./single-file
11
+ deno compile --allow-read --allow-write --allow-net --allow-env --allow-run --ext=js --output=./dist/single-file.exe --target=x86_64-pc-windows-msvc --icon=./resources/single-file.ico ./single-file
12
12
 
13
13
  dev_id=$(security find-identity -p codesigning -v | grep "Apple Development" | awk '{print $2}')
14
14
  codesign -f -s $dev_id ./dist/single-file-aarch64-apple-darwin
package/deno.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@single-file/single-file-cli",
3
- "version": "2.0.63",
3
+ "version": "2.0.65",
4
4
  "description": "SingleFile CLI",
5
5
  "nodeModulesDir": true,
6
6
  "exports": {
package/lib/cdp-client.js CHANGED
@@ -33,9 +33,9 @@ const MINIMIZED_WINDOW_STATE = "minimized";
33
33
  const SINGLE_FILE_WORLD_NAME = "singlefile";
34
34
  const EMPTY_PAGE_URL = "about:blank";
35
35
  const CAPTURE_SCREENSHOT_FUNCTION_NAME = "captureScreenshot";
36
- const CAPTURE_PDF_FUNCTION_NAME = "capturePdf";
36
+ const PRINT_TO_PDF_FUNCTION_NAME = "printToPDF";
37
37
  const SET_SCREENSHOT_FUNCTION_NAME = "setScreenshot";
38
- const SET_PDF_FUNCTION_NAME = "setPdf";
38
+ const SET_PDF_FUNCTION_NAME = "setPDF";
39
39
  const SET_PAGE_DATA_FUNCTION_NAME = "setPageData";
40
40
  const REDIRECT_STATUS_CODES = [301, 302, 303, 307, 308];
41
41
 
@@ -53,7 +53,15 @@ async function getPageData(options) {
53
53
  let targetInfo;
54
54
  try {
55
55
  targetInfo = await CDP.createTarget(EMPTY_PAGE_URL);
56
- const { Browser, Security, Page, Emulation, Fetch, Network, Runtime, Debugger } = new CDP(targetInfo);
56
+ const consoleMessages = [];
57
+ const { Browser, Security, Page, Emulation, Fetch, Network, Runtime, Debugger, Console } = new CDP(targetInfo);
58
+ if (options.consoleMessagesFile) {
59
+ await Console.enable();
60
+ Console.addEventListener("messageAdded", ({ params }) => {
61
+ const { message } = params;
62
+ consoleMessages.push(message);
63
+ });
64
+ }
57
65
  if (options.browserStartMinimized) {
58
66
  const { windowId, bounds } = await Browser.getWindowForTarget({ targetId: targetInfo.id });
59
67
  if (bounds.windowState !== MINIMIZED_WINDOW_STATE) {
@@ -182,47 +190,34 @@ async function getPageData(options) {
182
190
  loadPage({ Page, Runtime }, options),
183
191
  options.browserDebug ? waitForDebuggerReady({ Debugger }) : Promise.resolve()
184
192
  ]);
185
- if (options.browserWaitDelay) {
186
- await new Promise(resolve => setTimeout(resolve, options.browserWaitDelay));
187
- }
188
193
  await Runtime.addBinding({ name: SET_PAGE_DATA_FUNCTION_NAME, executionContextId: contextId });
189
- const pageDataPromise = new Promise(resolve => {
190
- let pageDataResponse = "";
191
- Runtime.addEventListener("bindingCalled", async ({ params }) => {
192
- if (params.name === SET_PAGE_DATA_FUNCTION_NAME) {
193
- const { payload } = params;
194
- if (payload.length) {
195
- pageDataResponse += payload;
196
- } else {
197
- const result = JSON.parse(pageDataResponse);
198
- if (result.content instanceof Array) {
199
- result.content = new Uint8Array(result.content);
200
- }
201
- resolve(result);
202
- }
203
- }
204
- });
205
- });
206
194
  if (options.embedScreenshot && options.compressContent) {
207
195
  await Runtime.addBinding({ name: CAPTURE_SCREENSHOT_FUNCTION_NAME, executionContextId: contextId });
208
196
  Runtime.addEventListener("bindingCalled", async ({ params }) => {
209
197
  if (params.name === CAPTURE_SCREENSHOT_FUNCTION_NAME) {
210
198
  try {
211
- await onCaptureScreenshot({ Page, Runtime }, contextId);
199
+ let screenshotOptions = { captureBeyondViewport: true };
200
+ if (options.embedScreenshotOptions) {
201
+ try {
202
+ screenshotOptions = JSON.parse(options.embedScreenshotOptions);
203
+ } catch (error) {
204
+ // ignored
205
+ }
206
+ }
207
+ screenshotOptions.format = "png";
208
+ const { data } = await Page.captureScreenshot(screenshotOptions);
209
+ await Runtime.evaluate({ expression: `globalThis.${SET_SCREENSHOT_FUNCTION_NAME}(${JSON.stringify(data)})`, contextId });
212
210
  } catch (error) {
213
- await Runtime.evaluate({
214
- expression: `globalThis.${SET_SCREENSHOT_FUNCTION_NAME}(${JSON.stringify([])})`,
215
- contextId
216
- });
211
+ await Runtime.evaluate({ expression: `globalThis.${SET_SCREENSHOT_FUNCTION_NAME}(${JSON.stringify("")})`, contextId });
217
212
  }
218
213
  }
219
214
  });
220
215
  }
221
216
  if (options.embedPdf) {
222
- await Runtime.addBinding({ name: CAPTURE_PDF_FUNCTION_NAME, executionContextId: contextId });
217
+ await Runtime.addBinding({ name: PRINT_TO_PDF_FUNCTION_NAME, executionContextId: contextId });
223
218
  Runtime.addEventListener("bindingCalled", async ({ params }) => {
224
- if (params.name === CAPTURE_PDF_FUNCTION_NAME) {
225
- let pdfOptions;
219
+ if (params.name === PRINT_TO_PDF_FUNCTION_NAME) {
220
+ let pdfOptions = {};
226
221
  if (options.embedPdfOptions) {
227
222
  try {
228
223
  pdfOptions = JSON.parse(options.embedPdfOptions);
@@ -231,18 +226,36 @@ async function getPageData(options) {
231
226
  }
232
227
  }
233
228
  try {
234
- await onCapturePdf({ Page, Runtime }, contextId, pdfOptions);
229
+ const { data } = await Page.printToPDF(pdfOptions);
230
+ await Runtime.evaluate({ expression: `globalThis.${SET_PDF_FUNCTION_NAME}(${JSON.stringify(data)})`, contextId });
235
231
  } catch (error) {
236
- await Runtime.evaluate({
237
- expression: `globalThis.${SET_PDF_FUNCTION_NAME}ƒƒ(${JSON.stringify([])})`,
238
- contextId
239
- });
232
+ await Runtime.evaluate({ expression: `globalThis.${SET_PDF_FUNCTION_NAME}(${JSON.stringify("")})`, contextId });
240
233
  }
241
234
  }
242
235
  });
243
236
  }
237
+ const pageDataPromise = new Promise(resolve => {
238
+ let pageDataResponse = "";
239
+ Runtime.addEventListener("bindingCalled", async ({ params }) => {
240
+ if (params.name === SET_PAGE_DATA_FUNCTION_NAME) {
241
+ const { payload } = params;
242
+ if (payload.length) {
243
+ pageDataResponse += payload;
244
+ } else {
245
+ const result = JSON.parse(pageDataResponse);
246
+ if (result.content instanceof Array) {
247
+ result.content = new Uint8Array(result.content);
248
+ }
249
+ resolve(result);
250
+ }
251
+ }
252
+ });
253
+ });
254
+ if (options.browserWaitDelay) {
255
+ await new Promise(resolve => setTimeout(resolve, options.browserWaitDelay));
256
+ }
244
257
  const { result } = await Runtime.evaluate({
245
- expression: `(${getPageDataScriptSource.toString()})(${JSON.stringify(options)},${JSON.stringify([SET_SCREENSHOT_FUNCTION_NAME, SET_PDF_FUNCTION_NAME, SET_PAGE_DATA_FUNCTION_NAME])})`,
258
+ expression: `(${getPageDataScriptSource.toString()})(${JSON.stringify(options)},${JSON.stringify([SET_SCREENSHOT_FUNCTION_NAME, SET_PDF_FUNCTION_NAME, SET_PAGE_DATA_FUNCTION_NAME, CAPTURE_SCREENSHOT_FUNCTION_NAME, PRINT_TO_PDF_FUNCTION_NAME])})`,
246
259
  awaitPromise: true,
247
260
  returnByValue: true,
248
261
  contextId
@@ -252,6 +265,10 @@ async function getPageData(options) {
252
265
  throw new Error(description);
253
266
  }
254
267
  const pageData = await pageDataPromise;
268
+ if (options.consoleMessagesFile) {
269
+ await Console.disable();
270
+ pageData.consoleMessages = consoleMessages;
271
+ }
255
272
  Object.assign(pageData, httpInfo);
256
273
  return pageData;
257
274
  } catch (error) {
@@ -270,44 +287,27 @@ async function getPageData(options) {
270
287
  }
271
288
  }
272
289
 
273
- async function onCaptureScreenshot({ Page, Runtime }, contextId) {
274
- const { data } = await Page.captureScreenshot({ format: "png", captureBeyondViewport: true });
275
- const dataURI = "data:image/png;base64," + data;
276
- const screenshotData = Array.from(new Uint8Array(await (await fetch(dataURI)).arrayBuffer()));
277
- await Runtime.evaluate({
278
- expression: `globalThis.${SET_SCREENSHOT_FUNCTION_NAME}(${JSON.stringify(screenshotData)})`,
279
- contextId
280
- });
281
- }
282
-
283
- async function onCapturePdf({ Page, Runtime }, contextId, options = {}) {
284
- const { data } = await Page.printToPDF(options);
285
- const pdfData = Array.from(new Uint8Array(await (await fetch("data:application/pdf;base64," + data)).arrayBuffer()));
286
- await Runtime.evaluate({
287
- expression: `globalThis.${SET_PDF_FUNCTION_NAME}(${JSON.stringify(pdfData)})`,
288
- contextId
289
- });
290
- }
291
-
292
- function getPageDataScriptSource(options, [SET_SCREENSHOT_FUNCTION_NAME, SET_PDF_FUNCTION_NAME, SET_PAGE_DATA_FUNCTION_NAME]) {
293
- if ((options.embedScreenshot && options.compressContent) || options.embedPdf) {
290
+ function getPageDataScriptSource(options, [SET_SCREENSHOT_FUNCTION_NAME, SET_PDF_FUNCTION_NAME, SET_PAGE_DATA_FUNCTION_NAME, CAPTURE_SCREENSHOT_FUNCTION_NAME, PRINT_TO_PDF_FUNCTION_NAME]) {
291
+ if ((options.embedScreenshot || options.embedPdf) && options.compressContent) {
294
292
  let screenshot, pdf;
295
- if (options.embedScreenshot && options.compressContent) {
296
- screenshot = new Promise(resolve => globalThis[SET_SCREENSHOT_FUNCTION_NAME] = resolve);
293
+ if (options.embedScreenshot) {
294
+ screenshot = new Promise(resolve => globalThis[SET_SCREENSHOT_FUNCTION_NAME] = async data =>
295
+ resolve(Array.from(new Uint8Array(await (await fetch("data:image/png;base64," + data)).arrayBuffer()))));
297
296
  }
298
297
  if (options.embedPdf) {
299
- pdf = new Promise(resolve => globalThis[SET_PDF_FUNCTION_NAME] = resolve);
298
+ pdf = new Promise(resolve => globalThis[SET_PDF_FUNCTION_NAME] = async data =>
299
+ resolve(Array.from(new Uint8Array(await (await fetch("data:application/pdf;base64," + data)).arrayBuffer()))));
300
300
  }
301
301
  let pendingCapture;
302
302
  options.onprogress = async event => {
303
303
  if (event.type == event.RESOURCES_INITIALIZING && window == top && !pendingCapture) {
304
304
  pendingCapture = true;
305
- if (globalThis.captureScreenshot) {
306
- globalThis.captureScreenshot("");
305
+ if (globalThis[CAPTURE_SCREENSHOT_FUNCTION_NAME]) {
306
+ globalThis[CAPTURE_SCREENSHOT_FUNCTION_NAME]("");
307
307
  options.embeddedImage = await screenshot;
308
308
  }
309
- if (globalThis.capturePdf) {
310
- globalThis.capturePdf("");
309
+ if (globalThis[PRINT_TO_PDF_FUNCTION_NAME]) {
310
+ globalThis[PRINT_TO_PDF_FUNCTION_NAME]("");
311
311
  options.embeddedPdf = await pdf;
312
312
  }
313
313
  }