html-snapshots 0.18.3 → 0.19.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.
Files changed (65) hide show
  1. package/.eslintrc.json +4 -5
  2. package/README.md +73 -68
  3. package/examples/custom/myFilter.js +2 -2
  4. package/examples/custom/package-lock.json +939 -4
  5. package/examples/custom/package.json +1 -1
  6. package/examples/custom/snapshot.js +8 -10
  7. package/examples/debug-phantomjs/package-lock.json +6 -6
  8. package/examples/debug-phantomjs/package.json +1 -1
  9. package/examples/debug-phantomjs/snapshot.js +12 -14
  10. package/examples/html5rocks/package-lock.json +1306 -5
  11. package/examples/html5rocks/package.json +1 -1
  12. package/examples/html5rocks/snapshot.js +15 -18
  13. package/examples/process-limit/package-lock.json +1306 -5
  14. package/examples/process-limit/package.json +1 -1
  15. package/examples/process-limit/snapshot.js +8 -10
  16. package/examples/simple-promise/package-lock.json +1306 -5
  17. package/examples/simple-promise/package.json +1 -1
  18. package/examples/simple-promise/snapshot.js +6 -8
  19. package/examples/sitemap-index/package-lock.json +1306 -5
  20. package/examples/sitemap-index/package.json +1 -1
  21. package/examples/sitemap-index/snapshot.js +6 -6
  22. package/examples/utils/index.js +2 -4
  23. package/examples/verbose/package-lock.json +1307 -5
  24. package/examples/verbose/package.json +1 -1
  25. package/examples/verbose/snapshot.js +11 -14
  26. package/lib/async/index.js +0 -1
  27. package/lib/common/index.js +1 -1
  28. package/lib/common/sitemap/index.js +16 -0
  29. package/lib/common/sitemap/sitemap-collection.js +94 -0
  30. package/lib/common/sitemap/sitemap-index.js +68 -0
  31. package/lib/common/{sitemap.js → sitemap/sitemap.js} +68 -57
  32. package/lib/html-snapshots.js +0 -1
  33. package/lib/input-generators/array.js +0 -1
  34. package/lib/input-generators/robots.js +98 -58
  35. package/lib/input-generators/sitemap-index.js +3 -124
  36. package/lib/input-generators/sitemap.js +3 -7
  37. package/lib/input-generators/textfile.js +2 -6
  38. package/package.json +5 -4
  39. package/test/helpers/options.js +4 -2
  40. package/test/mocha/html-snapshots/process-limit.js +46 -48
  41. package/test/mocha/html-snapshots/robots.js +156 -138
  42. package/test/mocha/html-snapshots/server/test_robots.txt +13 -0
  43. package/test/mocha/html-snapshots/server/test_robots_sitemap.txt +15 -0
  44. package/test/mocha/html-snapshots/server/test_robots_sitemap.xml +22 -0
  45. package/test/mocha/html-snapshots/sitemap-index.js +58 -57
  46. package/test/mocha/html-snapshots/snapshot-scripts.js +55 -54
  47. package/test/mocha/html-snapshots/test.js +16 -16
  48. package/test/mocha/html-snapshots/test_robots.txt +0 -2
  49. package/test/mocha/html-snapshots/utils.js +0 -1
  50. package/test/mocha/input-generators/server/test_robots.txt +0 -2
  51. package/test/mocha/input-generators/server/test_robots_bad.txt +0 -2
  52. package/test/mocha/input-generators/server/test_robots_sitemap.txt +17 -0
  53. package/test/mocha/input-generators/server/test_robots_sitemap_bad.txt +17 -0
  54. package/test/mocha/input-generators/server/test_robots_sitemap_multi.txt +18 -0
  55. package/test/mocha/input-generators/server/test_sitemap_index_empty.xml +3 -0
  56. package/test/mocha/input-generators/server/test_sitemap_index_malformed.xml +2 -0
  57. package/test/mocha/input-generators/sitemap-index.js +65 -9
  58. package/test/mocha/input-generators/test.js +276 -280
  59. package/test/mocha/input-generators/test_robots.txt +0 -2
  60. package/test/mocha/input-generators/test_robots_bad.txt +0 -2
  61. package/test/mocha/input-generators/test_robots_sitemap.txt +17 -0
  62. package/test/mocha/input-generators/test_robots_sitemap_bad.txt +17 -0
  63. package/test/mocha/input-generators/test_robots_sitemap_multi.txt +18 -0
  64. package/lib/common/node.js +0 -26
  65. package/test/mocha/common/node.js +0 -100
package/.eslintrc.json CHANGED
@@ -1,12 +1,11 @@
1
1
  {
2
2
  "parserOptions": {
3
- "ecmaVersion": 6,
4
- "ecmaFeatures": {
5
- "impliedStrict": true
6
- }
3
+ "ecmaVersion": 2020,
4
+ "sourceType": "module"
7
5
  },
8
6
  "env": {
9
- "node": true
7
+ "node": true,
8
+ "es2020": true
10
9
  },
11
10
  "extends": [
12
11
  "eslint:recommended"
package/README.md CHANGED
@@ -35,9 +35,9 @@
35
35
  + [License](#license)
36
36
 
37
37
  ## Overview
38
- html-snapshots is a flexible html snapshot library that uses PhantomJS 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.
38
+ 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.
39
39
 
40
- html-snapshots gets urls to process from either a robots.txt or sitemap.xml. Alternatively, you can supply an array with completely arbitrary urls, or a line delimited textfile with arbitrary host-relative paths.
40
+ 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.
41
41
 
42
42
  ## Getting Started
43
43
 
@@ -58,7 +58,7 @@ Here are some [background and other notes](/docs/notes.md) regarding this projec
58
58
  + [Caveats](/docs/notes.md#caveats)
59
59
 
60
60
  ### Process Model
61
- html-snapshots takes snapshots in parallel, each page getting its own PhantomJS process. Each PhantomJS process dies after snapshotting one page. You can limit the number of PhantomJS processes that can ever run at once with the `processLimit` option. This effectively sets up a process pool for PhantomJS instances. The default processLimit is 4 PhantomJS instances. When a PhantomJS process dies, and another snapshot needs to be taken, a new PhantomJS process is spawned to take the vacant slot. This continues until a `processLimit` number of processes are running at once.
61
+ 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.
62
62
 
63
63
  ### Node Support Tags
64
64
  `v0.13.2 ` Node 0.12 (or less)
@@ -70,6 +70,10 @@ html-snapshots takes snapshots in parallel, each page getting its own PhantomJS
70
70
 
71
71
  ### Breaking Changes
72
72
 
73
+ #### Introduced in v0.19.x
74
+ ##### Robots Input
75
+ Robots.txt files are now searched for `Sitemap` directive(s) **first** for sitemap/sitemapIndex files. If those directives are found, those directives are used to drive the crawl of the site alone. If no Sitemap directives are found, htmlSnapshots reverts back to using `Allow` directives. If no `Sitemap` directive is found, this is a non-breaking change.
76
+
73
77
  #### Introduced in v0.18.x
74
78
  ##### Dropped support for Node 10 & 12.
75
79
 
@@ -98,13 +102,13 @@ The api is just one `run` method that returns a Promise.
98
102
  A method that takes [options](#options) and an optional callback. Returns a Promise.
99
103
  **Syntax:**
100
104
  ```javascript
101
- var htmlSnapshots = require('html-snapshots');
105
+ const htmlSnapshots = require('html-snapshots');
102
106
 
103
- htmlSnapshots.run (options[, callback])
104
- .then(function (completed) {
107
+ htmlSnapshots.run(options[, callback])
108
+ .then(completed => {
105
109
  // `completed` is an array of paths to the completed snapshots.
106
110
  })
107
- .catch(function (errorObject) {
111
+ .catch(errorObject => {
108
112
  // `errorObject` is an instance of Error
109
113
  // `errorObject.completed` is an array of paths to the snapshots that did successfully complete.
110
114
  // `errorObject.notCompleted` is an array of paths to files that DID NOT successfully complete.
@@ -128,18 +132,18 @@ An older (version 0.13.2), more in depth usage example is located in this [artic
128
132
 
129
133
  ### Simple example
130
134
  ```javascript
131
- var htmlSnapshots = require('html-snapshots');
135
+ const htmlSnapshots = require('html-snapshots');
132
136
  htmlSnapshots.run({
133
- source: "/path/to/robots.txt",
134
- hostname: "exampledomain.com",
135
- outputDir: "./snapshots",
137
+ source: '/path/to/robots.txt',
138
+ hostname: 'exampledomain.com',
139
+ outputDir: './snapshots',
136
140
  outputDirClean: true,
137
- selector: "#dynamic-content"
141
+ selector: '#dynamic-content'
138
142
  })
139
- .then(function (completed) {
143
+ .then(completed => {
140
144
  // completed is an array of full file paths to the completed snapshots.
141
145
  })
142
- .catch(function (error) {
146
+ .catch(error => {
143
147
  // error is an Error instance.
144
148
  // error.completed is an array of snapshot file paths that were completed.
145
149
  // error.notCompleted is an array of file paths that did NOT complete.
@@ -149,25 +153,25 @@ This reads the urls from your robots.txt and produces snapshots in the ./snapsho
149
153
 
150
154
  ### Example - Per page selectors and timeouts
151
155
  ```javascript
152
- var htmlSnapshots = require('html-snapshots');
156
+ const htmlSnapshots = require('html-snapshots');
153
157
  htmlSnapshots.run({
154
- input: "sitemap",
155
- source: "/path/to/sitemap.xml",
156
- outputDir: "./snapshots",
158
+ input: 'sitemap',
159
+ source: '/path/to/sitemap.xml',
160
+ outputDir: './snapshots',
157
161
  outputDirClean: true,
158
162
  selector: {
159
- "http://mysite.com": "#home-content",
160
- "__default": "#dynamic-content"
163
+ 'http://mysite.com': '#home-content',
164
+ '__default': '#dynamic-content'
161
165
  },
162
166
  timeout: {
163
- "http://mysite.com/superslowpage": 20000,
164
- "__default": 10000
167
+ 'http://mysite.com/superslowpage': 20000,
168
+ '__default': 10000
165
169
  }
166
170
  })
167
- .then(function (completed) {
171
+ .then(completed => {
168
172
  // completed is an array of full file paths to the completed snapshots.
169
173
  })
170
- .catch(function (error) {
174
+ .catch(error => {
171
175
  // error is an Error instance.
172
176
  // error.completed is an array of snapshot file paths that were completed.
173
177
  // error.notCompleted is an array of file paths that did NOT complete.
@@ -177,22 +181,22 @@ This reads the urls from your sitemap.xml and produces snapshots in the ./snapsh
177
181
 
178
182
  ### Example - Per page special output paths
179
183
  ```javascript
180
- var htmlSnapshots = require('html-snapshots');
184
+ const htmlSnapshots = require('html-snapshots');
181
185
  htmlSnapshots.run({
182
- input: "sitemap",
183
- source: "/path/to/sitemap.xml",
184
- outputDir: "./snapshots",
186
+ input: 'sitemap',
187
+ source: '/path/to/sitemap.xml',
188
+ outputDir: './snapshots',
185
189
  outputDirClean: true,
186
190
  outputPath: {
187
- "http://mysite.com/services/?page=1": "services/page/1",
188
- "http://mysite.com/services/?page=2": "services/page/2"
191
+ 'http://mysite.com/services/?page=1': 'services/page/1',
192
+ 'http://mysite.com/services/?page=2': 'services/page/2'
189
193
  },
190
- selector: "#dynamic-content"
194
+ selector: '#dynamic-content'
191
195
  })
192
- .then(function (completed) {
196
+ .then(completed => {
193
197
  // completed is an array of full file paths to the completed snapshots.
194
198
  })
195
- .catch(function (error) {
199
+ .catch(error => {
196
200
  // error is an Error instance.
197
201
  // error.completed is an array of snapshot file paths that were completed.
198
202
  // error.notCompleted is an array of file paths that did NOT complete.
@@ -202,25 +206,25 @@ This example implies there are a couple of pages with query strings in sitemap.x
202
206
 
203
207
  ### Example - Per page selectors and jQuery
204
208
  ```javascript
205
- var htmlSnapshots = require('html-snapshots');
209
+ const htmlSnapshots = require('html-snapshots');
206
210
  htmlSnapshots.run({
207
- source: "/path/to/robots.txt",
208
- hostname: "mysite.com",
209
- outputDir: "./snapshots",
211
+ source: '/path/to/robots.txt',
212
+ hostname: 'mysite.com',
213
+ outputDir: './snapshots',
210
214
  outputDirClean: true,
211
215
  selector: {
212
- "__default": "#dynamic-content",
213
- "/jqpage": "A-Selector-Not-Supported-By-querySelector"
216
+ '__default': '#dynamic-content',
217
+ '/jqpage': 'A-Selector-Not-Supported-By-querySelector'
214
218
  },
215
219
  useJQuery: {
216
- "/jqpage": true,
217
- "__default": false
220
+ '/jqpage': true,
221
+ '__default': false
218
222
  }
219
223
  })
220
- .then(function (completed) {
224
+ .then(completed => {
221
225
  // completed is an array of full file paths to the completed snapshots.
222
226
  })
223
- .catch(function (error) {
227
+ .catch(error => {
224
228
  // error is an Error instance.
225
229
  // error.completed is an array of snapshot file paths that were completed.
226
230
  // error.notCompleted is an array of file paths that did NOT complete.
@@ -230,18 +234,18 @@ This reads the urls from your robots.txt and produces snapshots in the ./snapsho
230
234
 
231
235
  ### Example - Array
232
236
  ```javascript
233
- var htmlSnapshots = require('html-snapshots');
237
+ const htmlSnapshots = require('html-snapshots');
234
238
  htmlSnapshots.run({
235
- input: "array",
236
- source: ["http://mysite.com", "http://mysite.com/contact", "http://mysite.com:82/special"],
237
- outputDir: "./snapshots",
239
+ input: 'array',
240
+ source: ['http://mysite.com', 'http://mysite.com/contact', 'http://mysite.com:82/special'],
241
+ outputDir: './snapshots',
238
242
  outputDirClean: true,
239
- selector: "#dynamic-content"
243
+ selector: '#dynamic-content'
240
244
  })
241
- .then(function (completed) {
245
+ .then(completed => {
242
246
  // completed is an array of full file paths to the completed snapshots.
243
247
  })
244
- .catch(function (error) {
248
+ .catch(error => {
245
249
  // error is an Error instance.
246
250
  // error.completed is an array of snapshot file paths that were completed.
247
251
  // error.notCompleted is an array of file paths that did NOT complete.
@@ -251,29 +255,29 @@ Generates snapshots for "/", "/contact", and "/special" from mysite.com. "/speci
251
255
 
252
256
  ### Example - Remote robots.txt, remove script tags from html snapshots
253
257
  ```javascript
254
- var assert = require("assert");
255
- var fs = require("fs");
256
- var htmlSnapshots = require("html-snapshots");
258
+ const assert = require('assert');
259
+ const fs = require('fs');
260
+ const htmlSnapshots = require('html-snapshots');
257
261
 
258
262
  htmlSnapshots.run({
259
- source: "http://localhost/robots.txt",
260
- hostname: "localhost",
261
- outputDir: "./snapshots",
263
+ source: 'http://localhost/robots.txt',
264
+ hostname: 'localhost',
265
+ outputDir: './snapshots',
262
266
  outputDirClean: true,
263
- selector: "#dynamic-content",
267
+ selector: '#dynamic-content',
264
268
  snapshotScript: {
265
- script: "removeScripts"
269
+ script: 'removeScripts'
266
270
  }
267
271
  })
268
- .then(function (completed) {
269
- completed.forEach(function (snapshotFile) {
270
- var content = fs.readFileSync(snapshotFile, { encoding: "utf8"});
272
+ .then(completed => {
273
+ completed.forEach(snapshotFile => {
274
+ const content = fs.readFileSync(snapshotFile, { encoding: 'utf8'});
271
275
  assert.equal(false, /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi.test(content));
272
276
  });
273
277
  // It didn't throw b/c there are no script tags in the html snapshots
274
278
  console.log('stripped all script tags as expected');
275
279
  })
276
- .catch(function (error) {
280
+ .catch(error => {
277
281
  // error is an Error instance.
278
282
  // error.completed is an array of snapshot file paths that were completed.
279
283
  // error.notCompleted is an array of file paths that did NOT complete.
@@ -295,14 +299,14 @@ Removes all script tags from the output of the html snapshot. Custom filters are
295
299
  + `"sitemap"` Supply urls from a local or remote sitemap.xml file. Gzipped sitemaps are supported.
296
300
  + `"sitemap-index"` Supply urls from a local or remote sitemap-index.xml file. Gzipped sitemap indexes are supported.
297
301
  + `"array"`, supply arbitrary urls from a javascript array.
298
- + `"robots"` Supply urls from a local or remote robots.txt file. Robots.txt files with wildcards are NOT supported - Use "sitemap" instead.
302
+ + `"robots"` Supply urls from a local or remote robots.txt file. Robots.txt is first scanned for `Sitemap` directives. If found, those are used to drive the crawl. Otherwise, `Allow` directives are used in conjunction with [origin options](#origin-options).
299
303
  + `"textfile"` Supply urls from a local line-oriented text file in the style of robots.txt
300
304
 
301
305
  + `source`
302
306
  + default: `"./robots.txt"`, `"./sitemap.xml"`, `"./sitemap-index.xml"`, `"./line.txt"`, or `[]`, depending on the input generator.
303
307
  + Specifies the input source. This must be a valid array or the location of a robots, text, or sitemap file for the corresponding input generator. robots.txt, sitemap.xml(.gz), sitemap-index.xml(.gz) can be local or remote. However, for the array input generator, this must be an array of urls.
304
308
 
305
- ##### Sitemap/Sitemap-Index Only Input Options
309
+ ##### Robots.txt-With-Sitemap-Directives/Sitemap/Sitemap-Index Only Input Options
306
310
 
307
311
  + `sitemapPolicy`
308
312
  + default: `false`
@@ -322,7 +326,8 @@ Removes all script tags from the output of the html snapshot. Custom filters are
322
326
 
323
327
  The [examples](/examples) directory contains [sitemap-index](/examples/sitemap-index) and [sitemap](/examples/custom) usage examples.
324
328
 
325
- ##### Robots and Textfile Only Input Options
329
+ ##### Origin Options
330
+ > Origin options are only useful for Robots.txt files that use `Allow` directives and Textfile input types.
326
331
 
327
332
  + `hostname`
328
333
  + default: `"localhost"`
@@ -422,14 +427,14 @@ Removes all script tags from the output of the html snapshot. Custom filters are
422
427
  // option snippet showing snapshotScript object with "customFilter":
423
428
  {
424
429
  snapshotScript: {
425
- script: "customFilter",
426
- module: "/path/to/myFilter.js"
430
+ script: 'customFilter',
431
+ module: '/path/to/myFilter.js'
427
432
  }
428
433
  }
429
434
 
430
435
  // in myFilter.js:
431
436
  module.exports = function(content) {
432
- return content.replace(/someregex/g, "somereplacement"); // remove or replace anything
437
+ return content.replace(/someregex/g, 'somereplacement'); // remove or replace anything
433
438
  }
434
439
  ```
435
440
  A more complete example using custom options is available [here](/examples/custom).
@@ -5,7 +5,7 @@
5
5
  * Processes the snapshot output before it is finalized.
6
6
  */
7
7
  module.exports = function(content) {
8
- var filterVersion = "1.0-20141123";
8
+ var filterVersion = "1.0-20220921";
9
9
 
10
10
  return content
11
11
  // remove all script tags
@@ -15,7 +15,7 @@ module.exports = function(content) {
15
15
  // remove all link tags
16
16
  .replace(/<link\s.*?(\/)?>/gi, "")
17
17
  // replace select words
18
- .replace(/\bWordpress\b/ig, "myReplacement")
18
+ .replace(/\bSitemaps\b/ig, "Replaced-Sitemaps")
19
19
  // add an attribute to the body for tracking and identification
20
20
  .replace(/<body\b/i, "<body data-snapshot-filter=\""+filterVersion+"\" ")
21
21
  ;