single-file-cli 2.0.24 → 2.0.26

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/deno.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@single-file/single-file-cli",
3
- "version": "2.0.24",
3
+ "version": "2.0.26",
4
4
  "description": "SingleFile CLI",
5
5
  "nodeModulesDir": true,
6
6
  "exports": {
package/lib/browser.js CHANGED
@@ -34,7 +34,7 @@ async function launchBrowser(options = {}, indexPath = 0) {
34
34
  const executablePath = options.executablePath || BROWSER_PATHS[build.os][indexPath];
35
35
  const args = Array.from(BROWSER_ARGS);
36
36
  profilePath = await makeTempDir();
37
- if (options.headless) {
37
+ if (options.headless && !options.debug) {
38
38
  args.push("--headless");
39
39
  } else {
40
40
  args.push("--start-maximized");
package/lib/cdp-client.js CHANGED
@@ -34,7 +34,7 @@ const MINIMIZED_WINDOW_STATE = "minimized";
34
34
  const SINGLE_FILE_WORLD_NAME = "singlefile";
35
35
  const EMPTY_PAGE_URL = "about:blank";
36
36
 
37
- export { initialize, getPageData, hasTargets, closeBrowser };
37
+ export { initialize, getPageData, hasPageTargets, closeBrowser };
38
38
 
39
39
  async function initialize(options) {
40
40
  if (options.browserRemoteDebuggingURL) {
@@ -45,11 +45,10 @@ async function initialize(options) {
45
45
  }
46
46
 
47
47
  async function getPageData(options) {
48
- let Browser, Security, Page, Emulation, Fetch, Network, Runtime, Debugger, Target;
49
48
  let targetInfo;
50
49
  try {
51
50
  targetInfo = await CDP.createTarget(EMPTY_PAGE_URL);
52
- ({ Browser, Security, Page, Emulation, Fetch, Network, Runtime, Debugger, Target } = new CDP(targetInfo));
51
+ const { Browser, Security, Page, Emulation, Fetch, Network, Runtime, Debugger } = new CDP(targetInfo);
53
52
  if (options.browserStartMinimized) {
54
53
  const { windowId, bounds } = await Browser.getWindowForTarget({ targetId: targetInfo.id });
55
54
  if (bounds.windowState !== MINIMIZED_WINDOW_STATE) {
@@ -131,13 +130,13 @@ async function getPageData(options) {
131
130
  }
132
131
  throw error;
133
132
  } finally {
134
- if (targetInfo) {
133
+ if (targetInfo && !options.browserDebug) {
135
134
  await CDP.closeTarget(targetInfo.id);
136
135
  }
137
136
  }
138
137
  }
139
138
 
140
- async function hasTargets() {
139
+ async function hasPageTargets() {
141
140
  const targets = await CDP.getTargets();
142
141
  return targets.filter(target => target.type === "page").length > 0;
143
142
  }
@@ -145,18 +144,18 @@ async function hasTargets() {
145
144
  async function loadPage({ Page, Runtime }, options) {
146
145
  await Runtime.enable();
147
146
  await Page.enable();
147
+ const loadTimeoutAbortController = new AbortController();
148
+ const loadTimeoutAbortSignal = loadTimeoutAbortController.signal;
148
149
  try {
149
- const loadTimeoutAbortController = new AbortController();
150
- const loadTimeoutAbortSignal = loadTimeoutAbortController.signal;
151
150
  const [contextId] = await Promise.race([
152
151
  Promise.all([getTopFrameContextId({ Page, Runtime }, options), Page.navigate({ url: options.url })]),
153
152
  waitForLoadTimeout(loadTimeoutAbortSignal, options.browserLoadMaxTime)
154
153
  ]);
154
+ return contextId;
155
+ } finally {
155
156
  if (!loadTimeoutAbortSignal.aborted) {
156
157
  loadTimeoutAbortController.abort();
157
158
  }
158
- return contextId;
159
- } finally {
160
159
  await Runtime.disable();
161
160
  await Page.disable();
162
161
  }
@@ -166,50 +165,50 @@ function getTopFrameContextId({ Page, Runtime }, options) {
166
165
  return new Promise((resolve, reject) => {
167
166
  const FRAME_NAVIGATED_EVENT = "frameNavigated";
168
167
  const CONTEXT_CREATED_EVENT = "executionContextCreated";
169
- const CONTEXT_DESTROYED_EVENT = "executionContextDestroyed";
170
168
  const contextIds = [];
171
- let frameId, navigationAbortController;
169
+ let frameId;
172
170
  Page.addEventListener(FRAME_NAVIGATED_EVENT, onFrameNavigated);
173
171
  Runtime.addEventListener(CONTEXT_CREATED_EVENT, onExecutionContextCreated);
174
- Runtime.addEventListener(CONTEXT_DESTROYED_EVENT, onExecutionContextDestroyed);
175
172
 
176
173
  async function onFrameNavigated({ params }) {
177
- const { frame } = params;
178
- if (!frame.parentId) {
179
- frameId = frame.id;
180
- if (navigationAbortController) {
181
- navigationAbortController.abort();
182
- contextIds.length = 0;
174
+ try {
175
+ const { frame } = params;
176
+ if (!frame.parentId) {
177
+ if (frame.unreachableUrl) {
178
+ reject(new Error("Unreachable URL: " + frame.unreachableUrl));
179
+ } else {
180
+ frameId = frame.id;
181
+ await onTopFrameNavigated();
182
+ }
183
183
  }
184
- navigationAbortController = new AbortController();
185
- await onTopFrameNavigated(navigationAbortController.signal);
184
+ } finally {
185
+ Page.removeEventListener(FRAME_NAVIGATED_EVENT, onFrameNavigated);
186
+ Runtime.removeEventListener(CONTEXT_CREATED_EVENT, onExecutionContextCreated);
186
187
  }
187
188
  }
188
189
 
189
- async function onTopFrameNavigated(navigationSignal) {
190
- await waitForPageReady({ Page }, frameId, options, navigationSignal);
191
- if (!navigationSignal.aborted) {
192
- Page.removeEventListener(FRAME_NAVIGATED_EVENT, onFrameNavigated);
193
- Runtime.removeEventListener(CONTEXT_CREATED_EVENT, onExecutionContextCreated);
194
- Runtime.removeEventListener(CONTEXT_DESTROYED_EVENT, onExecutionContextDestroyed);
195
- let contextId;
196
- if (contextIds.length) {
197
- let contextIdIndex = 0;
198
- do {
199
- if (await testExecutionContext(contextIds[contextIdIndex])) {
200
- contextId = contextIds[contextIdIndex];
201
- }
202
- contextIdIndex++;
203
- } while (contextId === undefined && contextIdIndex < contextIds.length && !navigationSignal.aborted);
204
- }
205
- if (!navigationSignal.aborted) {
206
- if (contextId === undefined) {
207
- reject(new Error("Execution context not found"));
208
- } else {
209
- resolve(contextId);
190
+ async function onTopFrameNavigated() {
191
+ await waitForPageReady({ Page }, frameId, options);
192
+ const contextId = await getContextId();
193
+ if (contextId === undefined) {
194
+ reject(new Error("Execution context not found"));
195
+ } else {
196
+ resolve(contextId);
197
+ }
198
+ }
199
+
200
+ async function getContextId() {
201
+ let contextId;
202
+ if (contextIds.length) {
203
+ let contextIdIndex = 0;
204
+ do {
205
+ if (await testExecutionContext(contextIds[contextIdIndex])) {
206
+ contextId = contextIds[contextIdIndex];
210
207
  }
211
- }
208
+ contextIdIndex++;
209
+ } while (contextId === undefined && contextIdIndex < contextIds.length);
212
210
  }
211
+ return contextId;
213
212
  }
214
213
 
215
214
  function onExecutionContextCreated({ params }) {
@@ -219,14 +218,6 @@ function getTopFrameContextId({ Page, Runtime }, options) {
219
218
  contextIds.push(context.id);
220
219
  }
221
220
  }
222
-
223
- function onExecutionContextDestroyed({ params }) {
224
- const { executionContextId } = params;
225
- const index = contextIds.indexOf(executionContextId);
226
- if (index > -1) {
227
- contextIds.splice(index, 1);
228
- }
229
- }
230
221
  });
231
222
 
232
223
  async function testExecutionContext(contextId) {
@@ -248,6 +239,7 @@ function waitForLoadTimeout(abortSignal, maxDelay) {
248
239
  const ABORT_EVENT = "abort";
249
240
  abortSignal.addEventListener(ABORT_EVENT, onAbort);
250
241
  const timeoutId = setTimeout(() => {
242
+ abortSignal.removeEventListener(ABORT_EVENT, onAbort);
251
243
  const error = new Error("Load timeout");
252
244
  error.code = LOAD_TIMEOUT_ERROR;
253
245
  reject(error);
@@ -261,7 +253,7 @@ function waitForLoadTimeout(abortSignal, maxDelay) {
261
253
  });
262
254
  }
263
255
 
264
- async function waitForPageReady({ Page }, topFrameId, options, navigationSignal) {
256
+ async function waitForPageReady({ Page }, topFrameId, options) {
265
257
  await Page.setLifecycleEventsEnabled({ enabled: true });
266
258
  try {
267
259
  await new Promise(resolve => {
@@ -270,16 +262,14 @@ async function waitForPageReady({ Page }, topFrameId, options, navigationSignal)
270
262
 
271
263
  function onLifecycleEvent({ params }) {
272
264
  const { name, frameId } = params;
273
- if (frameId === topFrameId && (name === options.browserWaitUntil || name === DEFAULT_NETWORK_STATE || navigationSignal.aborted)) {
265
+ if (frameId === topFrameId && (name === options.browserWaitUntil || name === DEFAULT_NETWORK_STATE)) {
274
266
  Page.removeEventListener(LIFE_CYCLE_EVENT, onLifecycleEvent);
275
267
  resolve();
276
268
  }
277
269
  }
278
270
  });
279
271
  } finally {
280
- if (!navigationSignal.aborted) {
281
- await Page.setLifecycleEventsEnabled({ enabled: false });
282
- }
272
+ await Page.setLifecycleEventsEnabled({ enabled: false });
283
273
  }
284
274
  }
285
275
 
@@ -304,7 +294,7 @@ async function waitForDebuggerReady({ Debugger }) {
304
294
  function getBrowserOptions(options) {
305
295
  const browserOptions = {};
306
296
  browserOptions.args = options.browserArgs;
307
- browserOptions.headless = options.browserHeadless && !options.browserDebug;
297
+ browserOptions.headless = options.browserHeadless;
308
298
  browserOptions.executablePath = options.browserExecutablePath;
309
299
  browserOptions.debug = options.browserDebug;
310
300
  browserOptions.disableWebSecurity = options.browserDisableWebSecurity === undefined || options.browserDisableWebSecurity;
package/lib/constants.js CHANGED
@@ -37,20 +37,17 @@ const BROWSER_ARGS = [
37
37
  "--disable-dev-shm-usage",
38
38
  "--disable-extensions",
39
39
  "--disable-features=ImprovedCookieControls,LazyFrameLoading,GlobalMediaControls,DestroyProfileOnBrowserClose,MediaRouter,DialMediaRouteProvider,AcceptCHFrame,AutoExpandDetailsElement,CertificateTransparencyComponentUpdater,AvoidUnnecessaryBeforeUnloadCheckSync,Translate,HttpsUpgrades,PaintHolding",
40
- "--allow-pre-commit-input",
41
40
  "--disable-hang-monitor",
42
41
  "--disable-ipc-flooding-protection",
43
42
  "--disable-popup-blocking",
44
43
  "--disable-prompt-on-repost",
45
44
  "--disable-renderer-backgrounding",
46
45
  "--force-color-profile=srgb",
47
- "--metrics-recording-only",
48
46
  "--no-first-run",
49
47
  "--enable-automation",
50
48
  "--password-store=basic",
51
49
  "--use-mock-keychain",
52
50
  "--no-service-autorun",
53
- "--export-tagged-pdf",
54
51
  "--disable-search-engine-choice-screen",
55
52
  "--enable-use-zoom-for-dsf=false",
56
53
  "--no-sandbox",
package/lib/version.js CHANGED
@@ -1 +1 @@
1
- export const version = "2.0.24";
1
+ export const version = "2.0.26";
package/options.js CHANGED
@@ -103,7 +103,7 @@ const OPTIONS_INFO = {
103
103
  "max-resource-size-enabled": { description: "Enable removal of embedded resources exceeding a given size", type: "boolean" },
104
104
  "max-resource-size": { description: "Maximum size of embedded resources in MB (i.e. images, stylesheets, scripts and iframes)", type: "number", defaultValue: 10 },
105
105
  "move-styles-in-head": { description: "Move style elements outside the head element into the head element", type: "boolean" },
106
- "password": { description: "Password of the zip file", type: "string" },
106
+ "password": { description: "Password of the zip file when using --compress-content or --self-extracting-archive", type: "string" },
107
107
  "remove-frames": { description: "Remove frames", type: "boolean" },
108
108
  "remove-hidden-elements": { description: "Remove HTML elements which are not displayed", type: "boolean", defaultValue: true },
109
109
  "remove-unused-styles": { description: "Remove unused CSS rules and unneeded declarations", type: "boolean", defaultValue: true },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "single-file-cli",
3
- "version": "2.0.24",
3
+ "version": "2.0.26",
4
4
  "description": "SingleFile CLI",
5
5
  "author": "Gildas Lormeau",
6
6
  "engines": {
@@ -151,7 +151,7 @@ async function finish(options) {
151
151
  }
152
152
  }
153
153
  }
154
- if (!options.browserDebug && !options.browserRemoteDebuggingURL && !(await backend.hasTargets())) {
154
+ if (!options.browserDebug && !options.browserRemoteDebuggingURL && !(await backend.hasPageTargets())) {
155
155
  return backend.closeBrowser();
156
156
  }
157
157
  }
@@ -0,0 +1,2 @@
1
+ @echo off
2
+ node "%~dp0\single-file" %*