single-file-cli 1.0.26 → 1.0.28

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/args.js CHANGED
@@ -67,6 +67,9 @@ const args = require("yargs")
67
67
  "group-duplicate-images": true,
68
68
  "max-size-duplicate-images": 512 * 1024,
69
69
  "http-header": [],
70
+ "http-proxy-server": "",
71
+ "http-proxy-username": "",
72
+ "http-proxy-password": "",
70
73
  "include-infobar": false,
71
74
  "insert-meta-csp": true,
72
75
  "load-deferred-images": true,
@@ -195,6 +198,12 @@ const args = require("yargs")
195
198
  .number("max-size-duplicate-images")
196
199
  .options("http-header", { description: "Extra HTTP header (puppeteer, jsdom)" })
197
200
  .array("http-header")
201
+ .options("http-proxy-server", { description: "Proxy address (puppeteer)" })
202
+ .string("http-proxy-server")
203
+ .options("http-proxy-username", { description: "HTTP username (puppeteer)" })
204
+ .string("http-proxy-username")
205
+ .options("http-proxy-password", { description: "HTTP password (puppeteer)" })
206
+ .string("http-proxy-password")
198
207
  .options("include-BOM", { description: "Include the UTF-8 BOM into the HTML page" })
199
208
  .boolean("include-BOM")
200
209
  .options("include-infobar", { description: "Include the infobar" })
@@ -259,6 +268,7 @@ args.includeBOM = args.includeBom;
259
268
  args.crawlReplaceURLs = args.crawlReplaceUrls;
260
269
  args.crawlRemoveURLFragment = args.crawlRemoveUrlFragment;
261
270
  args.insertMetaCSP = args.insertMetaCsp;
271
+ args.saveOriginalURLs = args.saveOriginalUrls;
262
272
  if (args.removeScripts) {
263
273
  args.blockScripts = true;
264
274
  }
@@ -37,9 +37,21 @@ exports.initialize = async options => {
37
37
  exports.getPageData = async options => {
38
38
  let page, context;
39
39
  try {
40
- context = await browser.newContext({
40
+ const contextOptions = {
41
41
  bypassCSP: options.browserBypassCSP === undefined || options.browserBypassCSP
42
- });
42
+ };
43
+ if (options.httpProxyServer) {
44
+ contextOptions.proxy = {
45
+ server: options.httpProxyServer
46
+ };
47
+ if (options.httpProxyUsername) {
48
+ contextOptions.proxy.username = options.httpProxyUsername;
49
+ }
50
+ if (options.httpProxyPassword) {
51
+ contextOptions.proxy.password = options.httpProxyPassword;
52
+ }
53
+ }
54
+ context = await browser.newContext(contextOptions);
43
55
  await setContextOptions(context, options);
44
56
  page = await context.newPage();
45
57
  await setPageOptions(page, options);
@@ -90,6 +90,7 @@ async function setPageOptions(page, options) {
90
90
  features: options.emulateMediaFeatures
91
91
  });
92
92
  }
93
+ options.browserWaitUntil = "load";
93
94
  }
94
95
 
95
96
  async function getPageData(page, options) {
@@ -37,9 +37,21 @@ exports.initialize = async options => {
37
37
  exports.getPageData = async options => {
38
38
  let page, context;
39
39
  try {
40
- context = await browser.newContext({
40
+ const contextOptions = {
41
41
  bypassCSP: options.browserBypassCSP === undefined || options.browserBypassCSP
42
- });
42
+ };
43
+ if (options.httpProxyServer) {
44
+ contextOptions.proxy = {
45
+ server: options.httpProxyServer
46
+ };
47
+ if (options.httpProxyUsername) {
48
+ contextOptions.proxy.username = options.httpProxyUsername;
49
+ }
50
+ if (options.httpProxyPassword) {
51
+ contextOptions.proxy.password = options.httpProxyPassword;
52
+ }
53
+ }
54
+ context = await browser.newContext(contextOptions);
43
55
  await setContextOptions(context, options);
44
56
  page = await context.newPage();
45
57
  await setPageOptions(page, options);
@@ -98,6 +98,7 @@ async function setPageOptions(page, options) {
98
98
  // ignored
99
99
  }
100
100
  }
101
+ options.browserWaitUntil = "load";
101
102
  }
102
103
 
103
104
  async function getPageData(browser, page, options) {
@@ -30,7 +30,7 @@ const EXECUTION_CONTEXT_DESTROYED_ERROR = "Execution context was destroyed";
30
30
  const NETWORK_IDLE_STATE = "networkidle0";
31
31
  const NETWORK_STATES = ["networkidle0", "networkidle2", "load", "domcontentloaded"];
32
32
 
33
- let browser;
33
+ let browser, context;
34
34
 
35
35
  exports.initialize = async options => {
36
36
  if (options.browserServer) {
@@ -45,10 +45,15 @@ exports.getPageData = async (options, page) => {
45
45
  const privatePage = !page;
46
46
  try {
47
47
  if (privatePage) {
48
- page = await browser.newPage();
48
+ const contextOptions = {};
49
+ if (options.httpProxyServer) {
50
+ contextOptions.proxyServer = options.httpProxyServer;
51
+ }
52
+ context = await browser.createIncognitoBrowserContext(contextOptions);
53
+ page = await context.newPage();
49
54
  }
50
55
  await setPageOptions(page, options);
51
- return await getPageData(browser, page, options);
56
+ return await getPageData(context || browser, page, options);
52
57
  } finally {
53
58
  if (privatePage && !options.browserDebug) {
54
59
  await page.close();
@@ -109,9 +114,15 @@ async function setPageOptions(page, options) {
109
114
  if (options.emulateMediaFeatures) {
110
115
  await page.emulateMediaFeatures(options.emulateMediaFeatures);
111
116
  }
117
+ if (options.httpProxyServer && (options.httpProxyUsername || options.httpProxyPassword)) {
118
+ await page.authenticate({
119
+ username: options.httpProxyUsername,
120
+ password: options.httpProxyPassword
121
+ });
122
+ }
112
123
  }
113
124
 
114
- async function getPageData(browser, page, options) {
125
+ async function getPageData(context, page, options) {
115
126
  const injectedScript = await scripts.get(options);
116
127
  await page.evaluateOnNewDocument(injectedScript);
117
128
  if (options.browserDebug) {
@@ -124,7 +135,7 @@ async function getPageData(browser, page, options) {
124
135
  const browserWaitUntil = NETWORK_STATES[(NETWORK_STATES.indexOf(options.browserWaitUntil) + 1)];
125
136
  if (browserWaitUntil) {
126
137
  options.browserWaitUntil = browserWaitUntil;
127
- return getPageData(browser, page, options);
138
+ return getPageData(context, page, options);
128
139
  } else {
129
140
  throw error;
130
141
  }
@@ -141,7 +152,7 @@ async function getPageData(browser, page, options) {
141
152
  }, options);
142
153
  } catch (error) {
143
154
  if (error.message && error.message.includes(EXECUTION_CONTEXT_DESTROYED_ERROR)) {
144
- const pageData = await handleJSRedirect(browser, options);
155
+ const pageData = await handleJSRedirect(context, options);
145
156
  if (pageData) {
146
157
  return pageData;
147
158
  } else {
@@ -153,8 +164,8 @@ async function getPageData(browser, page, options) {
153
164
  }
154
165
  }
155
166
 
156
- async function handleJSRedirect(browser, options) {
157
- const pages = await browser.pages();
167
+ async function handleJSRedirect(context, options) {
168
+ const pages = await context.pages();
158
169
  const page = pages[1] || pages[0];
159
170
  try {
160
171
  await pageGoto(page, options);
@@ -166,7 +177,7 @@ async function handleJSRedirect(browser, options) {
166
177
  const url = page.url();
167
178
  if (url != options.url) {
168
179
  options.url = url;
169
- await browser.close();
180
+ await context.close();
170
181
  return exports.getPageData(options);
171
182
  }
172
183
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "single-file-cli",
3
- "version": "1.0.26",
3
+ "version": "1.0.28",
4
4
  "description": "SingleFile CLI",
5
5
  "author": "Gildas Lormeau",
6
6
  "license": "AGPL-3.0-or-later",