html-snapshots 5.11.0 → 6.1.0

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/HISTORY.md CHANGED
@@ -3,6 +3,12 @@ An overview of the [Breaking Changes](#breaking-changes) and [Node Support](#nod
3
3
 
4
4
  ## Breaking Changes
5
5
 
6
+ ### Introduced in v6.0.0
7
+ #### Dropped support for Node 20
8
+ #### Dropped support for Phantomjs
9
+ #### Added Playwright as a secondary browser choice
10
+ #### Added standard AggregateError usage for multi-error reporting
11
+
6
12
  ### Introduced in v5.0.0
7
13
  #### Dropped support for Node 18
8
14
 
package/README.md CHANGED
@@ -7,34 +7,46 @@
7
7
  > Takes html snapshots of your site's crawlable pages when an element you select is rendered.
8
8
 
9
9
  ## Contents
10
- + [Overview](#overview)
11
- + [Getting Started](#getting-started)
12
- + [Grunt Task](https://github.com/localnerve/grunt-html-snapshots)
13
- + [More Information](#more-information)
14
- + [API Reference](#api)
15
- + [Example Usage](#example-usage)
16
- + [Option Reference](#options)
17
- + [Input Options](#input-control-options)
18
- + [Output Options](#output-control-options)
19
- + [Snapshot Options](#snapshot-control-options)
20
- + [Process Options](#process-control-options)
21
- + [Rewrite and Middleware Examples](#example-rewrite-rule)
22
- + [Worker Process and Middleware Article and Examples](/docs/example-heroku-redis.md)
23
- + [License](#license)
10
+ - [html-snapshots](#html-snapshots)
11
+ - [Contents](#contents)
12
+ - [Overview](#overview)
13
+ - [Getting Started](#getting-started)
14
+ - [Installation](#installation)
15
+ - [Grunt Task](#grunt-task)
16
+ - [More Information](#more-information)
17
+ - [Process Model](#process-model)
18
+ - [API](#api)
19
+ - [*Promise* run (options\[, callback\])](#promise-run-options-callback)
20
+ - [Callback](#callback)
21
+ - [Example Usage](#example-usage)
22
+ - [Quick Example](#quick-example)
23
+ - [Options](#options)
24
+ - [Input Control Options](#input-control-options)
25
+ - [Sitemap Only Input Options](#sitemap-only-input-options)
26
+ - [Origin Options](#origin-options)
27
+ - [Output Control Options](#output-control-options)
28
+ - [Snapshot Control Options](#snapshot-control-options)
29
+ - [Process Control Options](#process-control-options)
30
+ - [Example Rewrite Rule](#example-rewrite-rule)
31
+ - [Connect-modrewrite](#connect-modrewrite)
32
+ - [Middleware Example](#middleware-example)
33
+ - [License](#license)
24
34
 
25
35
  ## Overview
26
36
  html-snapshots is a flexible html snapshot library that uses a headless browser to take html snapshots of your webpages served from your site. A snapshot is only taken when a specified selector is detected visible in the output html. This tool is useful when your site is largely ajax content, or an SPA, and you want your dynamic content indexed by search engines.
27
37
 
28
38
  html-snapshots gets urls to process from either a robots.txt, sitemap.xml, or sitemap-index.xml. Alternatively, you can supply an array with completely arbitrary urls, or a line delimited textfile with arbitrary host-relative paths.
29
39
 
40
+ ## Change History
41
+ This is an old project that has evolved since 2013. I've endeavored to keep it easy to use and upgrade. However, before upgrading, please review the release notes and the [history](HISTORY.md) for breaking changes.
42
+
30
43
  ## Getting Started
31
44
 
32
45
  ### Installation
33
- The simplest way to install html-snapshots is to use [npm](http://npmjs.org), just `npm
34
- install html-snapshots` will download html-snapshots and all dependencies.
46
+ The simplest way to install html-snapshots is to use [npm](http://npmjs.org). `npm
47
+ install html-snapshots` will download html-snapshots and all dependencies. To install the browsers required by playwright, you must also run `npx playwright install`. See [Playwright Docs](https://playwright.dev/docs/browsers) for additional details.
35
48
 
36
- ### Gulp Task
37
- This is a node library that just works with gulp as-is.
49
+ By default, html-snapshots uses **Puppeteer** under the hood. You can optionally configure it to use **Playwright** instead by setting the [`browser`](#process-control-options) option to `"playwright"`.
38
50
 
39
51
  ### Grunt Task
40
52
  If you are interested in the grunt task that uses this library, check out [grunt-html-snapshots](http://github.com/localnerve/grunt-html-snapshots).
@@ -45,6 +57,7 @@ Here are some [background and other notes](/docs/notes.md) regarding this projec
45
57
  + [How To Use Without Knowing About Page Content](/docs/notes.md#what-if-i-dont-know-about-the-rendered-page-content)
46
58
  + [Caveats](/docs/notes.md#caveats)
47
59
  + [Support History](HISTORY.md)
60
+ + [Web Automation & Building AI agents](/docs/web-automation-building.md)
48
61
 
49
62
  ### Process Model
50
63
  html-snapshots takes snapshots in parallel, each page getting its own browser process. Each browser process dies after snapshotting one page. You can limit the number of browser processes that can ever run at once with the `processLimit` option. This effectively sets up a process pool for browser instances. The default processLimit is 4 browser instances. When a browser process dies, and another snapshot needs to be taken, a new browser process is spawned to take the vacant slot. This continues until a `processLimit` number of processes are running at once.
@@ -63,7 +76,7 @@ htmlSnapshots.run(options[, callback])
63
76
  // `completed` is an array of paths to the completed snapshots.
64
77
  })
65
78
  .catch(errorObject => {
66
- // `errorObject` is an instance of Error
79
+ // `errorObject` is an instance of Error or AggregateError
67
80
  // `errorObject.completed` is an array of paths to the snapshots that did successfully complete.
68
81
  // `errorObject.notCompleted` is an array of paths to files that DID NOT successfully complete.
69
82
  });
@@ -73,9 +86,9 @@ The callback is optional because the run method returns a Promise that resolves
73
86
 
74
87
  Signature of the optional callback:
75
88
  ```javascript
76
- callback (errorObject, arrayOfPathsToCompletedSnapshots)
89
+ callback (errorOrAggregateErrorObject, arrayOfPathsToCompletedSnapshots)
77
90
  ```
78
- *For the callback, in the error case, the errorObject does not have the new extra properties `completed` and `notCompleted`. However, `arrayOfPathsToCompletedSnapshots` is supplied, and contains the paths to the snapshots that successfully completed.*
91
+ *For the callback, in the error \(or AggregateError\) case, the errorObject does not have the new extra properties `completed` and `notCompleted`. However, `arrayOfPathsToCompletedSnapshots` is supplied, and contains the paths to the snapshots that successfully completed.*
79
92
 
80
93
  ## Example Usage
81
94
  This example reads the pages from a mix of sitemap or sitemap-index files found in the robots.txt and produces snapshots in the ./snapshots directory. In this example, a selector named "#dynamic-content" appears in all pages across the site. Once this selector is visible in a page, the html snapshot is taken and saved to ./snapshots.
@@ -202,7 +215,7 @@ An older (version 0.13.2), more in depth usage example is located in this [artic
202
215
 
203
216
  `"function"` If the value is a function, it is called for every page and passed a single argument that is the url (or path in the case of robots.txt style) found in the input. The function must return a value to use for this option for the page it is given. The value returned for a given page must be a string.
204
217
 
205
- NOTE: By default, selectors must conform to [this spec](http://www.w3.org/TR/selectors-api/#grammar), as they are used by [querySelector](https://developer.mozilla.org/en-US/docs/Web/API/document.querySelector). If you need selectors not supported by this, you must specify the `useJQuery` option, and load jQuery in your page.
218
+ NOTE: By default, selectors must conform to [this spec](http://www.w3.org/TR/selectors-api/#grammar), as they are used by [querySelector](https://developer.mozilla.org/en-US/docs/Web/API/document.querySelector). If you need selectors not supported by this, you must load jQuery in your page and use a custom snapshot script.
206
219
 
207
220
  * **snapshotScript** {String|Object}
208
221
  + default: This library's default snapshot script. Which one is used is determined by the [`browser`](#process-control-options) option.
@@ -212,18 +225,6 @@ An older (version 0.13.2), more in depth usage example is located in this [artic
212
225
 
213
226
  `"string"` If the value is a string, it must an absolute path to a custom script you supply.
214
227
 
215
- + `browser: "phantomjs"`:
216
- html-snapshots will spawn a separate phantomjs process to run your snapshot script and give it the following [arguments](http://phantomjs.org/api/system/property/args.html):
217
- + `system.args[0]` The path to your PhantomJS script.
218
- + `system.args[1]` The output file path.
219
- + `system.args[2]` The url to snapshot.
220
- + `system.args[3]` The selector to watch for to signal page completion.
221
- + `system.args[4]` The overall timeout \(milliseconds\).
222
- + `system.args[5]` The interval \(milliseconds\) to watch for the selector.
223
- + `system.args[6]` A flag indicating jQuery selectors should be supported.
224
- + `system.args[7]` A flag indicating verbose output is desired.
225
- + `system.args[8]` A custom module to load.
226
-
227
228
  + `browser: "puppeteer"`:
228
229
  html-snapshots will spawn your script as a separate process and give it the following arguments:
229
230
  + `process.argv[0]` The path to NodeJS.
@@ -237,11 +238,24 @@ An older (version 0.13.2), more in depth usage example is located in this [artic
237
238
  + `process.argv[8]` A slowMo time \(milliseconds\) to slow the browser down.
238
239
  + `process.argv[9]` Stringified Puppeteer launch options.
239
240
 
241
+ + `browser: "playwright"`:
242
+ html-snapshots will spawn your script as a separate process and give it the following arguments:
243
+ + `process.argv[0]` The path to NodeJS.
244
+ + `process.argv[1]` The path to your snapshot script.
245
+ + `process.argv[2]` The output file path.
246
+ + `process.argv[3]` The url to snapshot.
247
+ + `process.argv[4]` The selector to wait for to signal page completion.
248
+ + `process.argv[5]` The overall timeout \(milliseconds\).
249
+ + `process.argv[6]` The path to a custom NodeJS module that returns a filter function.
250
+ + `process.argv[7]` A debug flag to kick the browser into headed, slowMo mode.
251
+ + `process.argv[8]` A slowMo time \(milliseconds\) to slow the browser down.
252
+ + `process.argv[9]` Stringified Playwright launch options. May include a `browserType` key (`"chromium"`, `"firefox"`, or `"webkit"`). Defaults to `"chromium"`.
253
+
240
254
  `"object"` If an object is supplied, it has the following properties:
241
255
  + `script` This must be one of the following values:
242
- + `"removeScripts"` This runs the default snapshot script with an output filter that removes all script tags are removed from the html snapshot before it is saved.
256
+ + `"removeScripts"` This runs the default snapshot script with an output filter that removes all script tags from the html snapshot before it is saved.
243
257
  + `"customFilter"` This runs the default snapshot script, but allows you to supply any output filter.
244
- + `module` This property is required only if you supplied a value of `"customFilter"` for the `script` property. This must be an absolute path to a PhantomJS module you supply. Your module will be `require`d and called as a function to filter the html snapshot output. Your module's function will receive the entire raw html content as a single input string, and must return the filtered html content.
258
+ + `module` This property is required only if you supplied a value of `"customFilter"` for the `script` property. This must be an absolute path to a NodeJS module you supply. Your module will be `require`d and called as a function to filter the html snapshot output. Your module's function will receive the entire raw html content as a single input string, and must return the filtered html content.
245
259
 
246
260
  customFilter Example:
247
261
  ```javascript
@@ -261,43 +275,14 @@ An older (version 0.13.2), more in depth usage example is located in this [artic
261
275
  A more complete example using custom options is available [here](/examples/custom).
262
276
 
263
277
  * **debug** {Object}
264
- > This options is only supported with the puppeteer browser script.
265
278
  + default: `{ flag: false, slowMo: 500 }`
266
- + Setting the `debug.flag` to true starts chrome in headed mode with devtools open. `debug.slowMo` is a time in milliseconds to reduce browser processing speed (larger numbers slows down chrome more). Recommended use is with a single problem page input using an Array source.
267
-
268
- * **useJQuery** {Boolean|Object|Function}
269
- > This option is only supported with the phantomjs browser script.
270
- + default: `false`
271
- + Specifies to use jQuery selectors to detect when to snapshot a page. Please note that you cannot use these selectors if the page to be snapshotted does not load jQuery itself. To return to the behavior prior to v0.6.x, set this to `true`.
272
-
273
- The value can be one of these *javascript types*:
274
-
275
- `"boolean"` If the value is a boolean, it is used for every page. Note that if it is any scalar type such as "string" or "number", it will be interpreted as a boolean using javascript rules. Coerced string values "true", "yes", and "1" are specifically true, all others are false.
276
-
277
- `"object"` If the value is an object, it is interpreted as key/value pairs where the key must match the url (or path in the case of robots.txt style) found by the input generator. This allows you to specify the use of jQuery for individual pages. The reserved key "__default" allows you to specify a default jQuery usage so you don't have to specify usage for every individual page.
278
-
279
- `"function"` If the value is a function, it is called for every page and passed a single argument that is the url (or path in the case of robots.txt style) found in the input. The function must return a value to use for this option for the page it is given. The value returned for a given page must be a boolean.
280
-
281
- NOTE: You do not *have to* use this option if your page uses jQuery. You only need this if your selector is not supported by [querySelector](https://developer.mozilla.org/en-US/docs/Web/API/document.querySelector). However, if you do use this option, the page being snapshotted must load jQuery itself.
282
-
283
- * **verbose** {Boolean|Object|Function}
284
- > This option is only used with the phantomjs browser script
285
- + default: `false`
286
- + Specifies to turn on extended console output in the PhantomJS process for debugging purposes. Can be applied to all pages, or just specific page(s). It is recommended to do this one page at a time, as the output can be large, and interleaved with parallel processes. See following explanation of types for how to debug just one page, and also [this example](/examples/verbose).
287
-
288
- The value can be one of these *javascript types*:
289
-
290
- `"boolean"` If the value is a boolean, it is used for every page. Note that if it is any scalar type such as "string" or "number", it will be interpreted as a boolean using javascript rules. Coerced string values "true", "yes", and "1" are specifically true, all others are false.
291
-
292
- `"object"` If the value is an object, it is interpreted as key/value pairs where the key must match the url (or path in the case of robots.txt style) found by the input generator. This allows you to specify the use of verbose output for individual pages. The reserved key "__default" allows you to specify the default `verbose` usage so you don't have to specify usage for every individual page.
293
-
294
- `"function"` If the value is a function, it is called for every page and passed a single argument that is the url (or path in the case of robots.txt style) found in the input. The function must return a value to use for this option for the page it is given. The value returned for a given page must be a boolean.
279
+ + Supported with both puppeteer and playwright browser scripts. Setting the `debug.flag` to true starts the browser in headed mode with devtools open (devtools is only supported for chromium-based browsers). `debug.slowMo` is a time in milliseconds to reduce browser processing speed (larger numbers slows down the browser more). Recommended use is with a single problem page input using an Array source.
295
280
 
296
281
  ### Process Control Options
297
282
 
298
283
  * **browser** {String}
299
284
  + default: `"puppeteer"`
300
- + Specifies which browser process to use in the crawl. Can be one of "phantomjs" or "puppeteer".
285
+ + Specifies which browser process to use in the crawl. Can be one of `"puppeteer"` or `"playwright"`.
301
286
 
302
287
  * **timeout** {Number|Object|Function}
303
288
  + default: 10000 \(milliseconds\)
@@ -313,19 +298,14 @@ An older (version 0.13.2), more in depth usage example is located in this [artic
313
298
 
314
299
  * **processLimit** {Number}
315
300
  + default: 4
316
- + Limits the number of child PhantomJS processes that can ever be actively running in parallel. A value of 1 effectively forces the snapshots to be taken in series (only one at a time). Useful if you need to limit the number of processes spawned by this library. Experiment with what works best. One guideline suggests about [4 per CPU](http://stackoverflow.com/questions/9961254/how-to-manage-a-pool-of-phantomjs-instances).
301
+ + Limits the number of child browser processes that can ever be actively running in parallel. A value of 1 effectively forces the snapshots to be taken in series (only one at a time). Useful if you need to limit the number of processes spawned by this library. Experiment with what works best. One guideline suggests about [4 per CPU](http://stackoverflow.com/questions/9961254/how-to-manage-a-pool-of-phantomjs-instances).
317
302
 
318
303
  * **pollInterval** {Number}
319
304
  + default: 500 \(milliseconds\)
320
305
  + Specifies the rate at which html-snapshots checks to see if a browser script has completed. Applies to all pages.
321
306
 
322
- * **checkInterval** {Number}
323
- > This option is only used with the phantomjs browser script
324
- + default: 250 (milliseconds)
325
- + Specifies the rate at which the PhantomJS script checks to see if the selector is visible yet. Applies to all pages.
326
-
327
307
  * **puppeteerLaunchOptions** {Object|Function}
328
- > This options is only used with the puppeteer browser script
308
+ > This option is only used with the puppeteer browser script
329
309
  + default: {}
330
310
  + Specifies launch options to give to Puppeteer. Can specify per page or for all pages. Puppeteer function options (like targetFilter) are not supported. Launch options will override any puppeteer debug options supplied.
331
311
 
@@ -335,46 +315,26 @@ An older (version 0.13.2), more in depth usage example is located in this [artic
335
315
 
336
316
  "`function`" If the value is a function, it is called for every page and passed a single argument that is the url found in the input. The function must return puppeteer launch options to use for the page it is given. The value returned for a given page must be an object to be given directly to `puppeter.launch`.
337
317
 
338
- * **phantomjsOptions** {String|Array|Object|Function}
339
- > This option is only used with the phantomjs browser script
340
- + default: ""
341
- + Specifies options to give to PhantomJS. Can specify per page or for all pages. Since PhantomJS instances run per page, it is possible to specify different PhantomJS options per page. Useful for debugging PhantomJS scripts on a specific page.
342
- For PhantomJS options syntax, checkout the [current options](http://phantomjs.org/api/command-line.html).
343
- Checkout [the source](https://github.com/ariya/phantomjs/blob/master/src/config.cpp#L49) for PhantomJS options coming next.
344
-
318
+ * **playwrightLaunchOptions** {Object|Function}
319
+ > This option is only used with the playwright browser script
320
+ + default: {}
321
+ + Specifies launch options to give to Playwright. Can specify per page or for all pages. The object may include a `browserType` key (`"chromium"`, `"firefox"`, or `"webkit"`) to select which browser engine to use. Defaults to `"chromium"`. Launch options will override any playwright debug options supplied.
322
+
345
323
  The value can be one of these *javascript types*:
346
324
 
347
- `"string"` If the value is a string, it is a single option string used for every page.
348
-
349
- `"array"` If the value is an array, it can contain multiple option strings used for every page.
350
-
351
- `"object"` If the value is an object, it is interpreted as key/value pairs where the key must match the url (or path in the case of robots.txt style) found by the input generator. This allows you to specify PhantomJS options for individual pages. The reserved key "__default" allows you to specify default options so you don't have to specify options for every individual page. The values can be either a string \(for a single option\), or an array \(for multiple options \).
325
+ `"object"` If the value is an object, it can contain any playwright launch options, and is applied for all pages. The object (minus `browserType`) will be given directly to `browserType.launch`.
352
326
 
353
- `"function"` If the value is a function, it is called for every page and passed a single argument that is the url (or path in the case of robots.txt style) found in the input. The function must return a value to use for this option for the page it is given. The value returned for a given page must be either a string or an array.
327
+ "`function`" If the value is a function, it is called for every page and passed a single argument that is the url found in the input. The function must return playwright launch options to use for the page it is given. The value returned for a given page must be an object to be given directly to `browserType.launch`.
354
328
 
355
- Multiple Options Examples:
329
+ Example using Firefox:
356
330
  ```javascript
357
- // option snippet showing multiple options for all pages
358
331
  {
359
- phantomjsOptions: ["--load-images=false", "--ignore-ssl-errors=true"]
360
- }
361
-
362
- // option snippet showing multiple options for one page only (object notation)
363
- {
364
- phantomjsOptions: {
365
- // key must exactly match the page as defined in the input (sitemap, array, robots, etc)
366
- "http://mysite.com/mypage": ["--load-images=false", "--ignore-ssl-errors=true"],
332
+ browser: "playwright",
333
+ playwrightLaunchOptions: {
334
+ browserType: "firefox"
367
335
  }
368
336
  }
369
337
  ```
370
- An example demonstrating how to **debug** a PhantomJS script is available [here](/examples/debug-phantomjs). It also demonstrates per-page option usage.
371
-
372
- * **phantomjs** {String}
373
- > This option is only used with the phantomjs browser script
374
- + default: A package local reference to PhantomJS.
375
- + Specifies the PhantomJS executable to run. Applies to all pages. Override this if you want to supply a path to a different version of PhantomJS. To reference PhantomJS globally in your environment, just use the value, "phantomjs". Remember, it must be found in your environment path to execute.
376
- See [PhantomJS](http://phantomjs.org/) for more information.
377
- Also [PhantomJS 2](https://github.com/ariya/phantomjs/wiki/PhantomJS-2).
378
338
 
379
339
  ## Example Rewrite Rule
380
340
  Here is an example apache rewrite rule for rewriting \_escaped\_fragment\_ requests to the snapshots directory on your server.
@@ -400,4 +360,4 @@ Here is the [article](/docs/example-heroku-redis.md) on how this middleware work
400
360
  ## License
401
361
  This software is free to use under the LocalNerve, LLC MIT license. See the [LICENSE file](/LICENSE) for license text and copyright information.
402
362
 
403
- Third-party open source code used are listed in the [package.json file](/package.json).
363
+ Third-party open source code used are listed in the [package.json file](/package.json).
@@ -9,7 +9,7 @@
9
9
  * Licensed under the MIT license.
10
10
  */
11
11
 
12
- const fs = require("fs").promises;
12
+ const { promises: fs } = require("node:fs");
13
13
 
14
14
  /**
15
15
  * Check if a path exists.
@@ -8,9 +8,8 @@
8
8
  * Licensed under the MIT license.
9
9
  */
10
10
 
11
- const crypto = require("crypto");
11
+ const crypto = require("node:crypto");
12
12
  const AsyncLock = require("async-lock");
13
- const combineErrors = require("combine-errors");
14
13
  const pathExists = require("./exists");
15
14
 
16
15
  const L_WAIT = 10000;
@@ -332,7 +331,9 @@ class Notifier {
332
331
  * @returns {Object} The error property.
333
332
  */
334
333
  getError () {
335
- return this.errors.length > 0 ? combineErrors(this.errors) : undefined;
334
+ return this.errors.length > 0
335
+ ? this.errors.length > 1 ? new AggregateError(this.errors) : this.errors[0]
336
+ : undefined;
336
337
  }
337
338
 
338
339
  /**
@@ -4,6 +4,7 @@
4
4
  * Copyright (c) 2013 - 2025, Alex Grant, LocalNerve, contributors
5
5
  * Licensed under the MIT license.
6
6
  */
7
+ const { parse: legacyUrlParser } = require("node:url"); // eslint-disable-line n/no-deprecated-api
7
8
 
8
9
  /**
9
10
  * Ensures that options at least contains propties and values from must
@@ -26,6 +27,7 @@ function ensure (options, must) {
26
27
 
27
28
  /**
28
29
  * Simple test for url
30
+ * Tests for an absolute url string
29
31
  *
30
32
  * If you can think of a more approriate test for this use case,
31
33
  * please let me know in the issues...
@@ -40,6 +42,34 @@ function isUrl (obj) {
40
42
  return false;
41
43
  }
42
44
 
45
+ /**
46
+ * Parse a string url to a URL object
47
+ * Fallback to legacy parser
48
+ *
49
+ * @param {String} inputUrl - a url to parse.
50
+ */
51
+ function parseUrl (inputUrl) {
52
+ let parsedUrl;
53
+ try {
54
+ if (isUrl(inputUrl)) {
55
+ parsedUrl = new URL(inputUrl);
56
+ } else {
57
+ parsedUrl = new URL(inputUrl, "bogus://bogus");
58
+ if (parsedUrl.protocol === "bogus:") {
59
+ parsedUrl.protocol = "";
60
+ }
61
+ if (parsedUrl.hostname === "bogus") {
62
+ parsedUrl.hostname = "";
63
+ }
64
+ }
65
+ // add legacy auth property
66
+ parsedUrl.auth = `${parsedUrl.username}:${parsedUrl.password}`;
67
+ } catch {
68
+ parsedUrl = legacyUrlParser(inputUrl);
69
+ }
70
+ return parsedUrl;
71
+ }
72
+
43
73
  /**
44
74
  * Simple test for a function
45
75
  *
@@ -194,5 +224,6 @@ module.exports = {
194
224
  isFunction,
195
225
  isObject,
196
226
  once,
227
+ parseUrl,
197
228
  prependMsgToErr
198
229
  };
@@ -4,8 +4,8 @@
4
4
  * Copyright (c) 2013 - 2025 Alex Grant, LocalNerve, contributors
5
5
  * Licensed under the MIT license.
6
6
  */
7
- const fs = require("fs");
8
- const pathLib = require("path");
7
+ const fs = require("node:fs");
8
+ const pathLib = require("node:path");
9
9
  const common = require("../index");
10
10
  const base = require("../../input-generators/_base");
11
11
 
@@ -8,11 +8,10 @@
8
8
  * Licensed under the MIT license.
9
9
  */
10
10
 
11
- const fs = require("fs");
12
- const util = require("util");
13
- const path = require("path");
14
- const urlm = require("url");
15
- const zlib = require("zlib");
11
+ const fs = require("node:fs");
12
+ const util = require("node:util");
13
+ const path = require("node:path");
14
+ const zlib = require("node:zlib");
16
15
  const xml2js = require("xml2js");
17
16
  const smi = require("./sitemap-index");
18
17
  const common = require("../index");
@@ -114,7 +113,7 @@ function parse (options, document, callback) {
114
113
 
115
114
  if (process) {
116
115
  // if sitemap is malformed, just blow up
117
- url = urlm.parse(urlNode.loc[0]);
116
+ url = common.parseUrl(urlNode.loc[0]);
118
117
  if (!base.input(
119
118
  { ...options,
120
119
  ...{