html-snapshots 0.18.2 → 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 +1012 -77
  5. package/examples/custom/package.json +1 -1
  6. package/examples/custom/snapshot.js +8 -10
  7. package/examples/debug-phantomjs/package-lock.json +76 -76
  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 +1379 -78
  11. package/examples/html5rocks/package.json +1 -1
  12. package/examples/html5rocks/snapshot.js +15 -18
  13. package/examples/process-limit/package-lock.json +1379 -78
  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 +1379 -78
  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 +1378 -77
  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 +1380 -78
  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 +6 -6
  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
@@ -7,16 +7,8 @@
7
7
  * Copyright (c) 2013 - 2022 Alex Grant, LocalNerve, contributors
8
8
  * Licensed under the MIT license.
9
9
  */
10
- /* global Promise */
11
-
12
- const fs = require("fs");
13
- const pathLib = require("path");
14
- const _ = require("lodash");
15
- const mkdirp = require("mkdirp");
16
- const xml2js = require("xml2js");
17
10
  const common = require("../common");
18
- const nodeCall = require("../common/node");
19
- const smLib = require("../common/sitemap");
11
+ const { sitemap: sm } = require("../common/sitemap");
20
12
  const base = require("./_base");
21
13
 
22
14
  // The default options
@@ -44,116 +36,6 @@ const sitemapIndex = {
44
36
  }
45
37
  };
46
38
 
47
- /**
48
- * Make sure path exists so a sitemap write can succeed.
49
- *
50
- * @param {String} outputPath - File path and name.
51
- * @param {Function} callback - Completion callback.
52
- */
53
- function prepareWrite (outputPath, callback) {
54
- const path = pathLib.parse(outputPath);
55
- const dir = pathLib.join(path.root, path.dir);
56
- mkdirp(dir).then(() => callback()).catch(callback);
57
- }
58
-
59
- /**
60
- * Parse a sitemap, generate input, and optionally update the local file
61
- * for sitemapPolicy purposes.
62
- * This writes the sitemap files out EVEN IF sitemapPolicy is false.
63
- * The thinking is that it's better/cheaper to do this b/c if sitemapPolicy is
64
- * enabled later, then there is something to compare against, for more savings.
65
- *
66
- * @param {Object} options - Sitemap options.
67
- * @param {Object} options.__sitemapIndex - Sitemap Index options.
68
- * @param {String} document - xml document string.
69
- * @param {Function} callback - A completion callback.
70
- */
71
- function processSitemap (options, document, callback) {
72
- smLib.parse(options, document, err => {
73
- const sitemapIndexOpts = options.__sitemapIndex;
74
- const outputPath = base.outputFile(sitemapIndexOpts, options.source);
75
-
76
- if (!err && sitemapIndexOpts.sitemapOutputDir) {
77
- prepareWrite(outputPath, err => {
78
- if (!err) {
79
- fs.writeFile(outputPath, document, callback);
80
- } else {
81
- callback(common.prependMsgToErr(err, outputPath, true));
82
- }
83
- });
84
- } else {
85
- callback(err);
86
- }
87
- });
88
- }
89
-
90
- /**
91
- * Parse a sitemap index document
92
- * For each qualifying sitemap element, download, parse the sitemap.
93
- * Stops processing if an error occurs.
94
- *
95
- * @param {Object} options - Sitemap options.
96
- * @param {Boolean} options.sitemapPolicy - True if sitemap policy should be used.
97
- * @param {String} document - xml document string.
98
- * @param {Function} callback - A completion callback.
99
- */
100
- function parse (options, document, callback) {
101
- xml2js.parseString(document, {
102
- trim: true,
103
- normalizeTags: true,
104
- normalize: true
105
- }, (err, result) => {
106
- const sitemapUrls = [];
107
- const sitemapIndexOptions = Object.assign({}, options, {
108
- outputPath: undefined
109
- });
110
-
111
- if (!err) {
112
- // Check if we should process each sitemap in the index.
113
- _.forEach(
114
- // if the sitemap index is malformed, just blow up
115
- result.sitemapindex.sitemap,
116
- sitemapNode => {
117
- // optionally ignore current sitemaps by sitemap policy
118
- const shouldProcess = !options.sitemapPolicy ||
119
- !smLib.stillCurrent(sitemapNode, sitemapIndexOptions);
120
-
121
- if (shouldProcess) {
122
- // if sitemap index is malformed, just blow up
123
- sitemapUrls.push(sitemapNode.loc[0]);
124
- }
125
- }
126
- );
127
-
128
- // Edge case message for clarity
129
- if (sitemapUrls.length === 0) {
130
- console.log("[*] No sitemaps qualified for processing");
131
- }
132
-
133
- // Get all the sitemaps, parse them, and generate input for each
134
- Promise.all(sitemapUrls.map(sitemapUrl => {
135
- const sitemapOptions = Object.assign({}, options, {
136
- source: sitemapUrl,
137
- input: "sitemap",
138
- sitemapOutputDir: false,
139
- __sitemapIndex: sitemapIndexOptions
140
- });
141
-
142
- console.log(`[+] Loading the sitemap: '${sitemapUrl}'`);
143
-
144
- return nodeCall(smLib.getUrl, sitemapOptions, processSitemap);
145
- }))
146
- .then(() => {
147
- // Ignore the array of results to this function
148
- callback();
149
- })
150
- .catch(callback);
151
- } else {
152
- callback(err);
153
- }
154
- });
155
- }
156
-
157
39
  /**
158
40
  * generateInput
159
41
  *
@@ -165,11 +47,8 @@ function parse (options, document, callback) {
165
47
  * @param {String} options.source - Sitemap URL or file path.
166
48
  */
167
49
  function generateInput (options) {
168
- return nodeCall(
169
- common.isUrl(options.source) ? smLib.getUrl : smLib.getFile,
170
- options,
171
- parse
172
- )
50
+ const retrieve = common.isUrl(options.source) ? sm.getUrl : sm.getFile;
51
+ return retrieve(options, sm.parse)
173
52
  .catch(err => {
174
53
  options._abort(err);
175
54
  })
@@ -9,8 +9,7 @@
9
9
  */
10
10
 
11
11
  const common = require("../common");
12
- const nodeCall = require("../common/node");
13
- const smLib = require("../common/sitemap");
12
+ const { sitemap: sm } = require("../common/sitemap");
14
13
  const base = require("./_base");
15
14
 
16
15
  // The default options
@@ -48,11 +47,8 @@ const sitemap = {
48
47
  * @returns {Promise} Resolves to undefined on completion.
49
48
  */
50
49
  function generateInput (options) {
51
- return nodeCall(
52
- common.isUrl(options.source) ? smLib.getUrl : smLib.getFile,
53
- options,
54
- smLib.parse
55
- )
50
+ const retrieve = common.isUrl(options.source) ? sm.getUrl : sm.getFile;
51
+ return retrieve(options, sm.parse)
56
52
  .catch(err => {
57
53
  options._abort(err);
58
54
  })
@@ -8,10 +8,9 @@
8
8
  * Licensed under the MIT license.
9
9
  */
10
10
 
11
- const fs = require("fs");
11
+ const fs = require("fs").promises;
12
12
  const base = require("./_base");
13
13
  const common = require("../common");
14
- const nodeCall = require("../common/node");
15
14
 
16
15
  // The default options
17
16
  const defaults = Object.freeze({
@@ -44,10 +43,7 @@ const textfile = {
44
43
  * @returns {Promise} resolves when complete.
45
44
  */
46
45
  function generateInput (options) {
47
- return nodeCall(
48
- fs.readFile,
49
- options.source
50
- )
46
+ return fs.readFile(options.source)
51
47
  .catch(err => {
52
48
  options._abort(err);
53
49
  })
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "html-snapshots",
3
- "version": "0.18.2",
3
+ "version": "0.19.0",
4
4
  "author": {
5
5
  "name": "Alex Grant",
6
6
  "email": "alex@localnerve.com",
7
- "url": "http://localnerve.com"
7
+ "url": "https://www.localnerve.com"
8
8
  },
9
9
  "homepage": "https://github.com/localnerve/html-snapshots",
10
10
  "description": "A selector-based html snapshot tool using PhantomJS that sources sitemap.xml, robots.txt, or arbitrary input",
@@ -24,6 +24,7 @@
24
24
  "test:common": "mocha test/mocha/common/*.js --exit --reporter spec",
25
25
  "test:input-generators": "mocha test/mocha/input-generators/*.js --exit --reporter spec",
26
26
  "test:html-snapshots": "mocha test/mocha/html-snapshots/*.js --exit --reporter spec",
27
+ "test:html-snapshots:debug": "mocha --inspect-brk test/mocha/html-snapshots/*.js --exit --reporter spec",
27
28
  "test:cover": "c8 -- npm test",
28
29
  "validate": "npm ls"
29
30
  },
@@ -52,16 +53,15 @@
52
53
  "lodash": "4.17.21",
53
54
  "mkdirp": "1.0.4",
54
55
  "phantomjs-prebuilt": "2.1.16",
55
- "request": "2.88.2",
56
+ "got": "12.5.0",
56
57
  "rimraf": "3.0.2",
57
58
  "xml2js": "0.4.23"
58
59
  },
59
60
  "devDependencies": {
60
- "coveralls": "3.1.1",
61
- "eslint": "8.14.0",
61
+ "eslint": "8.23.1",
62
62
  "express": "4.18.1",
63
63
  "mocha": "10.0.0",
64
- "c8": "7.11.2",
64
+ "c8": "7.12.0",
65
65
  "precommit-hook": "3.0.0",
66
66
  "server-destroy": "1.0.1",
67
67
  "sitemap-xml": "0.1.0",
@@ -9,7 +9,7 @@
9
9
  * If a global phantomjs is defined, decorates html-snapshots options to specify that global
10
10
  * In some test environments (travis), local phantomjs will not install if a global is found.
11
11
  */
12
- var assert = require("assert");
12
+ const assert = require("assert");
13
13
 
14
14
  // @0.12.0, on Travis-ci phantomjs2 WILL install local WITH the older global.
15
15
  // So reverting back to decorateLocal only.
@@ -19,7 +19,9 @@ var assert = require("assert");
19
19
  function fillAbort (options) {
20
20
  if (!options._abort) {
21
21
  options._abort = function (err) {
22
- assert.fail("test", "failed", err.toString(), "");
22
+ const msg = `[options._abort] called: ${err.toString()}`;
23
+ console.log(`@@@ ${msg}`);
24
+ assert.fail(msg);
23
25
  }
24
26
  }
25
27
  }
@@ -4,41 +4,41 @@
4
4
  * Copyright (c) 2013 - 2022, Alex Grant, LocalNerve, contributors
5
5
  */
6
6
  /* global it */
7
- var assert = require("assert");
8
- var rimraf = require("rimraf").sync;
9
- var utils = require("./utils");
10
- var optHelp = require("../../helpers/options");
11
- var ss = require("../../../lib/html-snapshots");
12
- var robotsTests = require("./robots");
13
-
14
- // missing destructuring, will write postcard...
15
- var timeout = utils.timeout;
16
- var outputDir = utils.outputDir;
17
- var cleanup = utils.cleanup;
18
- var killSpawnedProcesses = utils.killSpawnedProcesses;
19
- var countSpawnedProcesses = utils.countSpawnedProcesses;
20
- var unexpectedError = utils.unexpectedError;
21
- var multiError = utils.multiError;
22
- var checkActualFiles = utils.checkActualFiles;
23
-
24
- var urls = robotsTests.urlCount;
25
- var inputFile = robotsTests.inputFile;
7
+ const assert = require("assert");
8
+ const rimraf = require("rimraf").sync;
9
+ const utils = require("./utils");
10
+ const optHelp = require("../../helpers/options");
11
+ const ss = require("../../../lib/html-snapshots");
12
+ const robotsTests = require("./robots");
13
+
14
+ const {
15
+ timeout,
16
+ outputDir,
17
+ cleanup,
18
+ killSpawnedProcesses,
19
+ countSpawnedProcesses,
20
+ unexpectedError,
21
+ multiError,
22
+ checkActualFiles
23
+ } = utils;
24
+
25
+ const urls = robotsTests.urlCount;
26
26
 
27
27
  function processLimitTests (options) {
28
- var port = options.port;
29
- var pollInterval = 50;
30
- var phantomCount = 0;
31
- var timer;
28
+ const { port, localRobotsFile: inputFile } = options;
29
+ const pollInterval = 50;
30
+ let phantomCount = 0;
31
+ let timer;
32
32
 
33
33
  function completeTest (done, processLimit, e, files) {
34
- var countError = phantomCount ?
35
- new Error(phantomCount + " exceeded processLimit " + processLimit) :
34
+ const countError = phantomCount ?
35
+ new Error(`${phantomCount} exceeded processLimit ${processLimit}`) :
36
36
  undefined;
37
37
 
38
38
  clearInterval(timer);
39
39
 
40
40
  if (files) {
41
- checkActualFiles(files).then(function () {
41
+ checkActualFiles(files).then(() => {
42
42
  cleanup(done, multiError(e, countError));
43
43
  });
44
44
  } else {
@@ -48,8 +48,8 @@ function processLimitTests (options) {
48
48
 
49
49
  return function () {
50
50
  it("should limit as expected", function (done) {
51
- var processLimit = urls - 1;
52
- var complete = completeTest.bind(null, done, processLimit);
51
+ const processLimit = urls - 1;
52
+ const complete = completeTest.bind(null, done, processLimit);
53
53
 
54
54
  if (process.platform === "win32") {
55
55
  assert.ok(true, "Skipping posix compliant tests for processLimit");
@@ -58,15 +58,15 @@ function processLimitTests (options) {
58
58
  rimraf(outputDir);
59
59
 
60
60
  killSpawnedProcesses(function (err) {
61
- var options = {
61
+ const options = {
62
62
  source: inputFile,
63
63
  hostname: "localhost",
64
- port: port,
65
64
  selector: "#dynamic-content",
66
- outputDir: outputDir,
67
65
  outputDirClean: true,
68
- timeout: timeout,
69
- processLimit: processLimit
66
+ outputDir,
67
+ timeout,
68
+ processLimit,
69
+ port
70
70
  };
71
71
 
72
72
  if (err) {
@@ -74,14 +74,14 @@ function processLimitTests (options) {
74
74
  }
75
75
 
76
76
  ss.run(optHelp.decorate(options))
77
- .then(function () {
77
+ .then(() => {
78
78
  complete();
79
79
  })
80
- .catch(function (e) {
80
+ .catch(e => {
81
81
  complete(e || unexpectedError, e.notCompleted);
82
82
  });
83
83
 
84
- timer = setInterval(function () {
84
+ timer = setInterval(() => {
85
85
  countSpawnedProcesses(function (count) {
86
86
  // console.log("@@@ DEBUG @@@ phantom count: "+count);
87
87
  if (count > processLimit) {
@@ -95,8 +95,8 @@ function processLimitTests (options) {
95
95
  });
96
96
 
97
97
  it("should limit to just one process", function (done) {
98
- var processLimit = 1;
99
- var complete = completeTest.bind(null, done, processLimit);
98
+ const processLimit = 1;
99
+ const complete = completeTest.bind(null, done, processLimit);
100
100
 
101
101
  if (process.platform === "win32") {
102
102
  assert.ok(true, "Skipping posix compliant tests for processLimit");
@@ -105,15 +105,15 @@ function processLimitTests (options) {
105
105
  rimraf(outputDir);
106
106
 
107
107
  killSpawnedProcesses(function (err) {
108
- var options = {
108
+ const options = {
109
109
  source: inputFile,
110
110
  hostname: "localhost",
111
- port: port,
112
111
  selector: "#dynamic-content",
113
- outputDir: outputDir,
114
112
  outputDirClean: true,
115
- timeout: timeout,
116
- processLimit: processLimit
113
+ outputDir,
114
+ timeout,
115
+ processLimit,
116
+ port
117
117
  };
118
118
 
119
119
  if (err) {
@@ -121,10 +121,10 @@ function processLimitTests (options) {
121
121
  }
122
122
 
123
123
  ss.run(optHelp.decorate(options))
124
- .then(function () {
124
+ .then(() => {
125
125
  complete();
126
126
  })
127
- .catch(function (e) {
127
+ .catch(e => {
128
128
  complete(e || unexpectedError, e.notCompleted);
129
129
  });
130
130
 
@@ -144,7 +144,5 @@ function processLimitTests (options) {
144
144
  }
145
145
 
146
146
  module.exports = {
147
- testSuite: processLimitTests,
148
- inputFile: inputFile,
149
- urlCount: urls
147
+ testSuite: processLimitTests
150
148
  };