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 +1 -1
- package/lib/browser.js +1 -1
- package/lib/cdp-client.js +46 -56
- package/lib/constants.js +0 -3
- package/lib/version.js +1 -1
- package/options.js +1 -1
- package/package.json +1 -1
- package/single-file-cli-api.js +1 -1
- package/single-file-node.bat +2 -0
package/deno.json
CHANGED
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,
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
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
|
-
|
|
185
|
-
|
|
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(
|
|
190
|
-
await waitForPageReady({ Page }, frameId, options
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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.
|
|
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
package/single-file-cli-api.js
CHANGED
|
@@ -151,7 +151,7 @@ async function finish(options) {
|
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
|
-
if (!options.browserDebug && !options.browserRemoteDebuggingURL && !(await backend.
|
|
154
|
+
if (!options.browserDebug && !options.browserRemoteDebuggingURL && !(await backend.hasPageTargets())) {
|
|
155
155
|
return backend.closeBrowser();
|
|
156
156
|
}
|
|
157
157
|
}
|