html-snapshots 5.10.0 → 6.0.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/.nvmrc +1 -0
- package/HISTORY.md +6 -0
- package/README.md +66 -106
- package/eslint.config.js +9 -8
- package/lib/async/exists.js +1 -1
- package/lib/async/index.js +4 -3
- package/lib/common/sitemap/sitemap-collection.js +2 -2
- package/lib/common/sitemap/sitemap.js +5 -5
- package/lib/html-snapshots.js +41 -78
- package/lib/input-generators/_base.js +10 -9
- package/lib/input-generators/array.js +1 -1
- package/lib/input-generators/index.js +2 -2
- package/lib/input-generators/robots.js +1 -1
- package/lib/input-generators/textfile.js +2 -2
- package/lib/playwright/index.js +125 -0
- package/lib/playwright/removeScripts.js +11 -0
- package/lib/puppeteer/index.js +7 -7
- package/lib/puppeteer/removeScripts.js +1 -1
- package/package.json +23 -31
- package/lib/phantom/customFilter.js +0 -24
- package/lib/phantom/default.js +0 -21
- package/lib/phantom/modules/cli.js +0 -100
- package/lib/phantom/modules/detectors.js +0 -48
- package/lib/phantom/modules/globals.js +0 -43
- package/lib/phantom/modules/selectorDetect.js +0 -108
- package/lib/phantom/modules/verbose.js +0 -71
- package/lib/phantom/removeScripts.js +0 -30
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
* Licensed under the MIT license.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
const EventEmitter = require("events")
|
|
11
|
-
const path = require("path");
|
|
12
|
-
const urlm = require("url");
|
|
10
|
+
const { EventEmitter } = require("node:events");
|
|
11
|
+
const path = require("node:path");
|
|
12
|
+
const urlm = require("node:url");
|
|
13
13
|
const common = require("../common");
|
|
14
14
|
|
|
15
15
|
// Defaults for this module
|
|
@@ -25,7 +25,7 @@ const defaults = Object.freeze({
|
|
|
25
25
|
checkInterval: 250,
|
|
26
26
|
useJQuery: false,
|
|
27
27
|
verbose: false,
|
|
28
|
-
|
|
28
|
+
playwrightLaunchOptions: {},
|
|
29
29
|
puppeteerLaunchOptions: {},
|
|
30
30
|
debug: {
|
|
31
31
|
flag: "false",
|
|
@@ -116,7 +116,8 @@ function prepOptions (options, listener) {
|
|
|
116
116
|
|
|
117
117
|
// Prep single, global object options for normalization.
|
|
118
118
|
[
|
|
119
|
-
"puppeteerLaunchOptions"
|
|
119
|
+
"puppeteerLaunchOptions",
|
|
120
|
+
"playwrightLaunchOptions"
|
|
120
121
|
]
|
|
121
122
|
.forEach((optionName) => {
|
|
122
123
|
prepSingleObjectOptions(optionName, options);
|
|
@@ -126,7 +127,7 @@ function prepOptions (options, listener) {
|
|
|
126
127
|
// The certain arguments are per-page options.
|
|
127
128
|
// However, outputPath is a special case
|
|
128
129
|
[
|
|
129
|
-
"selector", "timeout", "useJQuery", "verbose", "
|
|
130
|
+
"selector", "timeout", "useJQuery", "verbose", "playwrightLaunchOptions",
|
|
130
131
|
"puppeteerLaunchOptions"
|
|
131
132
|
]
|
|
132
133
|
.forEach((perPageOption) => {
|
|
@@ -254,7 +255,7 @@ module.exports = {
|
|
|
254
255
|
* @param {Number} options.checkInterval - The millisecond resolute poll interval.
|
|
255
256
|
* @param {Function} options.userJQuery - Produces a jquery bool given a page url.
|
|
256
257
|
* @param {Function} options.verbose - Produces a verbose bool given a page url.
|
|
257
|
-
* @param {Function} options.
|
|
258
|
+
* @param {Function} options.playwrightLaunchOptions - Produces playwright launch options given a page url.
|
|
258
259
|
* @param {Function} options.puppeteerLaunchOptions - Produces puppeteer launch options given a page url.
|
|
259
260
|
* @param {Object} options.debug - Produces debug options given a page url.
|
|
260
261
|
* @param {Function} options._inputEmitter - The EventEmitter to generate input.
|
|
@@ -288,8 +289,8 @@ module.exports = {
|
|
|
288
289
|
useJQuery: options.useJQuery(page),
|
|
289
290
|
// map the input page to a verbose flag
|
|
290
291
|
verbose: options.verbose(page),
|
|
291
|
-
// map the input page to
|
|
292
|
-
|
|
292
|
+
// map the input page to playwright launch options
|
|
293
|
+
playwrightLaunchOptions: options.playwrightLaunchOptions(page),
|
|
293
294
|
// map the input page to puppeteer launch options
|
|
294
295
|
puppeteerLaunchOptions: options.puppeteerLaunchOptions(page),
|
|
295
296
|
// useful for puppeteer testing, debugging
|
|
@@ -28,7 +28,7 @@ module.exports = {
|
|
|
28
28
|
|
|
29
29
|
if (input) {
|
|
30
30
|
input = (""+input).replace(" ", "").toLowerCase();
|
|
31
|
-
hasInput = input && input.charAt(0) !==
|
|
31
|
+
hasInput = input && input.charAt(0) !== "_" && input !== "index";
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
try {
|
|
@@ -36,7 +36,7 @@ module.exports = {
|
|
|
36
36
|
result = require( "./" + input);
|
|
37
37
|
}
|
|
38
38
|
} catch (e) {
|
|
39
|
-
console.error(
|
|
39
|
+
console.error(`Input generator load failed '${input}'`, e);
|
|
40
40
|
/* return the "null" generator on error */
|
|
41
41
|
}
|
|
42
42
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* Licensed under the MIT license.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
const fs = require("fs")
|
|
11
|
+
const { promises: fs } = require("node:fs");
|
|
12
12
|
const common = require("../common");
|
|
13
13
|
const { sitemapCollection: smc } = require("../common/sitemap");
|
|
14
14
|
const base = require("./_base");
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* Licensed under the MIT license.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
const fs = require("fs")
|
|
11
|
+
const { promises: fs } = require("node:fs");
|
|
12
12
|
const base = require("./_base");
|
|
13
13
|
const common = require("../common");
|
|
14
14
|
|
|
@@ -50,7 +50,7 @@ function generateInput (options) {
|
|
|
50
50
|
.then(data => {
|
|
51
51
|
if (data) {
|
|
52
52
|
let error;
|
|
53
|
-
data.toString().split(
|
|
53
|
+
data.toString().split("\n").every(line => {
|
|
54
54
|
const page = line.replace(/^\s+|\s+$/g, "");
|
|
55
55
|
|
|
56
56
|
if (!base.input(options, page)) {
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
#!/usr/bin/env -S node --unhandled-rejections=strict
|
|
2
|
+
/**
|
|
3
|
+
* playwright process entry point
|
|
4
|
+
*
|
|
5
|
+
* Command line arguments:
|
|
6
|
+
* 0 - /path/to/node
|
|
7
|
+
* 1 - *this script*
|
|
8
|
+
* 2 - outputFile
|
|
9
|
+
* 3 - url
|
|
10
|
+
* 4 - selector
|
|
11
|
+
* [5] - timeout
|
|
12
|
+
* [6] - filter
|
|
13
|
+
* [7] - debug
|
|
14
|
+
* [8] - slowMo
|
|
15
|
+
* [9] - arbitrary launchOptions (JSON)
|
|
16
|
+
*
|
|
17
|
+
* launchOptions may include a `browserType` key ("chromium" | "firefox" | "webkit")
|
|
18
|
+
* to select the browser engine. Defaults to "chromium".
|
|
19
|
+
*
|
|
20
|
+
* Copyright (c) 2013 - 2025 Alex Grant, LocalNerve, contributors
|
|
21
|
+
* Licensed under the MIT license.
|
|
22
|
+
*/
|
|
23
|
+
const path = require("node:path");
|
|
24
|
+
const { promises: fs } = require("node:fs");
|
|
25
|
+
const playwright = require("playwright");
|
|
26
|
+
|
|
27
|
+
if (process.argv.length < 5) {
|
|
28
|
+
throw Error(`playwright script '${
|
|
29
|
+
process.argv[1]
|
|
30
|
+
}' expected these arguments:\n\
|
|
31
|
+
OUTPUTFILE URL SELECTOR [TIMEOUT FILTER DEBUG SLOWMO LAUNCHOPTIONS]`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const launchOpts = process.argv[9] ? JSON.parse(process.argv[9]) : null;
|
|
35
|
+
|
|
36
|
+
// browserType is a playwright concern, not a launch option — extract it before
|
|
37
|
+
// passing the rest through to playwright.launch()
|
|
38
|
+
const { browserType: browserTypeKey = "chromium", ...extraLaunchOpts } = launchOpts ?? {};
|
|
39
|
+
|
|
40
|
+
if (!["chromium", "firefox", "webkit"].includes(browserTypeKey)) {
|
|
41
|
+
throw Error(`playwright script: unsupported browserType '${browserTypeKey}'. \
|
|
42
|
+
Must be one of: chromium, firefox, webkit`);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const options = {
|
|
46
|
+
outputFile: process.argv[2],
|
|
47
|
+
url: process.argv[3],
|
|
48
|
+
selector: process.argv[4],
|
|
49
|
+
timeout: process.argv[5] ? parseInt(process.argv[5], 10) : 10000,
|
|
50
|
+
filter: process.argv[6] && process.argv[6] !== "false" ? process.argv[6] : null,
|
|
51
|
+
debug: process.argv[7] && process.argv[7].toLowerCase() === "true",
|
|
52
|
+
slowMo: process.argv[8] ? parseInt(process.argv[8], 10) : 500,
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const launchOptions = {
|
|
56
|
+
...(options.debug ? {
|
|
57
|
+
headless: false,
|
|
58
|
+
slowMo: options.slowMo,
|
|
59
|
+
devtools: browserTypeKey === "chromium" // devtools only supported in chromium
|
|
60
|
+
} : {
|
|
61
|
+
headless: true
|
|
62
|
+
}),
|
|
63
|
+
...extraLaunchOpts
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Run the snapshot script.
|
|
68
|
+
*
|
|
69
|
+
* @returns {Promise<string>} on completion
|
|
70
|
+
*/
|
|
71
|
+
async function run () {
|
|
72
|
+
let timeLeft, browser;
|
|
73
|
+
const start = Date.now();
|
|
74
|
+
|
|
75
|
+
timeLeft = options.timeout - 200; // leave some room for reporting
|
|
76
|
+
if (timeLeft < 0) timeLeft = 0;
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
const filter =
|
|
80
|
+
options.filter ? require(options.filter) : passthru => passthru;
|
|
81
|
+
|
|
82
|
+
const browserType = playwright[browserTypeKey];
|
|
83
|
+
browser = await browserType.launch(launchOptions);
|
|
84
|
+
const page = await browser.newPage();
|
|
85
|
+
|
|
86
|
+
await page.goto(options.url, {
|
|
87
|
+
timeout: timeLeft
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
timeLeft -= (Date.now() - start);
|
|
91
|
+
if (timeLeft < 0) timeLeft = 0;
|
|
92
|
+
|
|
93
|
+
await fs.mkdir(path.dirname(options.outputFile), {
|
|
94
|
+
recursive: true
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
await page.waitForSelector(options.selector, {
|
|
98
|
+
state: "visible",
|
|
99
|
+
timeout: timeLeft
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const content = await page.content();
|
|
103
|
+
await fs.writeFile(options.outputFile, filter(content));
|
|
104
|
+
const elapsed = Date.now() - start;
|
|
105
|
+
|
|
106
|
+
await browser.close();
|
|
107
|
+
|
|
108
|
+
return `snapshot for ${options.url} finished in ${elapsed} ms\n\
|
|
109
|
+
written to ${options.outputFile}`;
|
|
110
|
+
} catch (e) {
|
|
111
|
+
const err = new Error(`failed to snapshot ${options.url}`, {
|
|
112
|
+
cause: e
|
|
113
|
+
});
|
|
114
|
+
if (browser) {
|
|
115
|
+
browser.close().finally(() => {
|
|
116
|
+
throw err;
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
throw err;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
run().then(console.log).catch(e => {
|
|
124
|
+
throw e;
|
|
125
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remove all script tags from content
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2013 - 2025 Alex Grant, LocalNerve, contributors
|
|
5
|
+
* Licensed under the MIT license.
|
|
6
|
+
*/
|
|
7
|
+
function removeScriptTags (content) {
|
|
8
|
+
return content.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, "");
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
module.exports = removeScriptTags;
|
package/lib/puppeteer/index.js
CHANGED
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
* Copyright (c) 2013 - 2025 Alex Grant, LocalNerve, contributors
|
|
18
18
|
* Licensed under the MIT license.
|
|
19
19
|
*/
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
const
|
|
20
|
+
const path = require("node:path");
|
|
21
|
+
const { promises: fs } = require("node:fs");
|
|
22
|
+
const puppeteer = require("puppeteer");
|
|
23
23
|
|
|
24
24
|
if (process.argv.length < 5) {
|
|
25
25
|
throw Error(`puppeteer script '${
|
|
@@ -33,8 +33,8 @@ const options = {
|
|
|
33
33
|
url: process.argv[3],
|
|
34
34
|
selector: process.argv[4],
|
|
35
35
|
timeout: process.argv[5] ? parseInt(process.argv[5], 10) : 10000,
|
|
36
|
-
filter: process.argv[6] && process.argv[6] !==
|
|
37
|
-
debug: process.argv[7] && process.argv[7].toLowerCase() ===
|
|
36
|
+
filter: process.argv[6] && process.argv[6] !== "false" ? process.argv[6] : null,
|
|
37
|
+
debug: process.argv[7] && process.argv[7].toLowerCase() === "true" ? true : false,
|
|
38
38
|
slowMo: process.argv[8] ? parseInt(process.argv[8], 10) : 500,
|
|
39
39
|
launchOpts: process.argv[9] ? JSON.parse(process.argv[9]) : null
|
|
40
40
|
};
|
|
@@ -44,7 +44,7 @@ const launchOptions = {
|
|
|
44
44
|
slowMo: options.slowMo,
|
|
45
45
|
devtools: true
|
|
46
46
|
} : {
|
|
47
|
-
headless:
|
|
47
|
+
headless: true
|
|
48
48
|
}),
|
|
49
49
|
...(options.launchOpts ?? {})
|
|
50
50
|
};
|
|
@@ -79,7 +79,7 @@ async function run () {
|
|
|
79
79
|
});
|
|
80
80
|
|
|
81
81
|
await page.waitForSelector(options.selector, {
|
|
82
|
-
|
|
82
|
+
visible: true,
|
|
83
83
|
timeout: timeLeft
|
|
84
84
|
});
|
|
85
85
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Licensed under the MIT license.
|
|
6
6
|
*/
|
|
7
7
|
function removeScriptTags (content) {
|
|
8
|
-
return content.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
|
|
8
|
+
return content.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, "");
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
module.exports = removeScriptTags;
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "html-snapshots",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "Alex Grant",
|
|
6
6
|
"email": "alex@localnerve.com",
|
|
7
7
|
"url": "https://www.localnerve.com"
|
|
8
8
|
},
|
|
9
9
|
"homepage": "https://github.com/localnerve/html-snapshots",
|
|
10
|
-
"description": "A selector-based html snapshot tool using Puppeteer or
|
|
10
|
+
"description": "A selector-based html snapshot tool using Puppeteer or Playwright that sources sitemap.xml, robots.txt, or arbitrary input",
|
|
11
11
|
"contributors": [
|
|
12
12
|
{
|
|
13
13
|
"name": "Alex Grant",
|
|
@@ -19,20 +19,22 @@
|
|
|
19
19
|
},
|
|
20
20
|
"scripts": {
|
|
21
21
|
"lint": "eslint .",
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"test
|
|
26
|
-
"
|
|
27
|
-
"test:
|
|
28
|
-
"
|
|
29
|
-
"test:
|
|
30
|
-
"
|
|
31
|
-
"test:
|
|
32
|
-
"
|
|
33
|
-
"test:
|
|
34
|
-
"
|
|
35
|
-
"
|
|
22
|
+
"_cleancov": "node -e \"const fs=require('fs');fs.rmSync('coverage',{recursive:true,force:true});fs.mkdirSync('coverage',{recursive:true})\"",
|
|
23
|
+
"_test": "node --test --experimental-test-coverage --test-reporter=spec --test-reporter-destination=stdout --test-reporter=lcov --test-reporter-destination=\"coverage/lcov.info\"",
|
|
24
|
+
"pretest": "npm run _cleancov",
|
|
25
|
+
"test": "npm run _test -- --test-coverage-exclude=\"test/**\" --test-concurrency=1 \"test/suites/**/*.spec.js\"",
|
|
26
|
+
"pretest:24": "npm run _cleancov",
|
|
27
|
+
"test:24": "npm run _test -- --test-coverage-exclude=\"test/**\" --test-isolation=none \"test/suites/**/*.spec.js\"",
|
|
28
|
+
"pretest:async": "npm run _cleancov",
|
|
29
|
+
"test:async": "npm run _test -- \"test/suites/async/*.spec.js\" --test-coverage-exclude=\"test/**\"",
|
|
30
|
+
"pretest:common": "npm run _cleancov",
|
|
31
|
+
"test:common": "npm run _test -- \"test/suites/common/*.spec.js\" --test-coverage-exclude=\"test/**\"",
|
|
32
|
+
"pretest:browsers": "npm run _cleancov",
|
|
33
|
+
"test:browsers": "npm run _test -- \"test/suites/browsers/*.spec.js\" --test-coverage-exclude=\"test/**\"",
|
|
34
|
+
"pretest:input-generators": "npm run _cleancov",
|
|
35
|
+
"test:input-generators": "npm run _test -- \"test/suites/input-generators/*.spec.js\" --test-coverage-exclude=\"test/**\"",
|
|
36
|
+
"pretest:html-snapshots": "npm run _cleancov",
|
|
37
|
+
"test:html-snapshots": "node --test --experimental-test-coverage --test-reporter=spec --test-reporter-destination=stdout --test-reporter=lcov --test-reporter-destination=\"coverage/lcov.info\" \"test/suites/html-snapshots/*.spec.js\" --test-coverage-exclude=\"test/**\""
|
|
36
38
|
},
|
|
37
39
|
"main": "./lib/html-snapshots",
|
|
38
40
|
"repository": {
|
|
@@ -52,30 +54,20 @@
|
|
|
52
54
|
"dependencies": {
|
|
53
55
|
"async": "3.2.6",
|
|
54
56
|
"async-lock": "1.4.1",
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"puppeteer": "^24.42.0",
|
|
57
|
+
"playwright": "1.60.0",
|
|
58
|
+
"puppeteer": "25.1.0",
|
|
58
59
|
"xml2js": "0.6.2"
|
|
59
60
|
},
|
|
60
61
|
"devDependencies": {
|
|
61
|
-
"eslint": "^10.2.1",
|
|
62
62
|
"@eslint/js": "^10.0.1",
|
|
63
|
-
"
|
|
63
|
+
"eslint": "^10.4.1",
|
|
64
64
|
"express": "^5.2.1",
|
|
65
|
-
"
|
|
66
|
-
"c8": "^11.0.0",
|
|
65
|
+
"globals": "^17.6.0",
|
|
67
66
|
"server-destroy": "^1.0.1",
|
|
68
67
|
"sitemap-xml": "^0.1.0"
|
|
69
68
|
},
|
|
70
|
-
"overrides": {
|
|
71
|
-
"request": "npm:@cypress/request@3.0.10",
|
|
72
|
-
"diff": "^9.0.0",
|
|
73
|
-
"glob": "^13.0.6",
|
|
74
|
-
"serialize-javascript": "^7.0.5",
|
|
75
|
-
"brace-expansion": "^5.0.5"
|
|
76
|
-
},
|
|
77
69
|
"license": "MIT",
|
|
78
70
|
"engines": {
|
|
79
|
-
"node": ">=
|
|
71
|
+
"node": ">=22"
|
|
80
72
|
}
|
|
81
73
|
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* customFilter.js
|
|
3
|
-
*
|
|
4
|
-
* Produce a single snapshot for a web page.
|
|
5
|
-
* Snapshot taken when selector is(:visible).
|
|
6
|
-
* Applies a custom filter to the snapshot output.
|
|
7
|
-
*
|
|
8
|
-
* This is a phantomJS script that runs in phantomjs.
|
|
9
|
-
*
|
|
10
|
-
* Copyright (c) 2013 - 2025 Alex Grant, LocalNerve, contributors
|
|
11
|
-
* Licensed under the MIT license.
|
|
12
|
-
*/
|
|
13
|
-
var selectorDetect = require("./modules/selectorDetect");
|
|
14
|
-
var cli = require("./modules/cli");
|
|
15
|
-
var detectors = require("./modules/detectors");
|
|
16
|
-
|
|
17
|
-
var options = cli.selector();
|
|
18
|
-
var customFilter = require(options.module);
|
|
19
|
-
|
|
20
|
-
selectorDetect(
|
|
21
|
-
options,
|
|
22
|
-
options.useJQuery ? detectors.jquerySelector : detectors.querySelector,
|
|
23
|
-
customFilter
|
|
24
|
-
);
|
package/lib/phantom/default.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* default.js
|
|
3
|
-
*
|
|
4
|
-
* Produce a single snapshot for a web page.
|
|
5
|
-
* Snapshot taken when a selector is detected visible.
|
|
6
|
-
*
|
|
7
|
-
* This is a phantomJS script that runs in phantomjs.
|
|
8
|
-
*
|
|
9
|
-
* Copyright (c) 2013 - 2025 Alex Grant, LocalNerve, contributors
|
|
10
|
-
* Licensed under the MIT license.
|
|
11
|
-
*/
|
|
12
|
-
var selectorDetect = require("./modules/selectorDetect");
|
|
13
|
-
var cli = require("./modules/cli");
|
|
14
|
-
var detectors = require("./modules/detectors");
|
|
15
|
-
|
|
16
|
-
var options = cli.selector();
|
|
17
|
-
|
|
18
|
-
selectorDetect(
|
|
19
|
-
options,
|
|
20
|
-
options.useJQuery ? detectors.jquerySelector : detectors.querySelector
|
|
21
|
-
);
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* cli.js
|
|
3
|
-
*
|
|
4
|
-
* Handles phantomjs command line interface.
|
|
5
|
-
* Reads the command line arguments and returns options.
|
|
6
|
-
*
|
|
7
|
-
* This is a module for a phantomJS script that runs in phantomjs.
|
|
8
|
-
*
|
|
9
|
-
* Copyright (c) 2013 - 2025 Alex Grant, LocalNerve, contributors
|
|
10
|
-
* Licensed under the MIT license.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
var system = require("system");
|
|
14
|
-
var globals = require("./globals");
|
|
15
|
-
|
|
16
|
-
module.exports = {
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* command line argument handling for selector based snapshot scripts
|
|
20
|
-
* args: PHANTOM_SCRIPT OUTPUTFILE URL SELECTOR [TIMEOUT INTERVAL USEJQUERY FILTER]
|
|
21
|
-
*/
|
|
22
|
-
selector: function () {
|
|
23
|
-
|
|
24
|
-
var options = {};
|
|
25
|
-
var defaults = {
|
|
26
|
-
|
|
27
|
-
// outputFile (required)
|
|
28
|
-
// The file to write the snapshot to
|
|
29
|
-
// encoding is the same as served from url
|
|
30
|
-
outputFile: "snapshot.html",
|
|
31
|
-
|
|
32
|
-
// url (required)
|
|
33
|
-
// The url to produce the snapshot from
|
|
34
|
-
url: "http://localhost/",
|
|
35
|
-
|
|
36
|
-
// selector (required)
|
|
37
|
-
// The selector to wait for before taking the snapshot
|
|
38
|
-
// When the selector is visible, this defines document readiness
|
|
39
|
-
selector: "body",
|
|
40
|
-
|
|
41
|
-
// timeout (optional)
|
|
42
|
-
// The maximum amount of time (ms) to wait before giving up on the snapshot
|
|
43
|
-
timeout: 10000,
|
|
44
|
-
|
|
45
|
-
// checkInterval (optional)
|
|
46
|
-
// The frequency (ms) to check for document readiness
|
|
47
|
-
checkInterval: 250,
|
|
48
|
-
|
|
49
|
-
// useJQuery (optional)
|
|
50
|
-
// flag to indicate use jQuery selector or not. jQuery must already exist in page.
|
|
51
|
-
useJQuery: false,
|
|
52
|
-
|
|
53
|
-
// verbose (optional)
|
|
54
|
-
// flag to indicate verbose output is desired.
|
|
55
|
-
verbose: false
|
|
56
|
-
|
|
57
|
-
// module (optional)
|
|
58
|
-
// An external module to load
|
|
59
|
-
// (default undefined)
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
if (system.args.length < 4) {
|
|
63
|
-
globals.exit(3, "phantomjs script '"+system.args[0]+"' expected these arguments: OUTPUTFILE URL SELECTOR [TIMEOUT INTERVAL JQUERY MODULE]");
|
|
64
|
-
} else {
|
|
65
|
-
|
|
66
|
-
options.outputFile = system.args[1];
|
|
67
|
-
options.url = system.args[2];
|
|
68
|
-
options.selector = system.args[3];
|
|
69
|
-
if (system.args[4]) {
|
|
70
|
-
options.timeout = parseInt(system.args[4], 10);
|
|
71
|
-
}
|
|
72
|
-
if (system.args[5]) {
|
|
73
|
-
options.checkInterval = parseInt(system.args[5], 10);
|
|
74
|
-
}
|
|
75
|
-
if (system.args[6]) {
|
|
76
|
-
var useJQuery = system.args[6].toLowerCase();
|
|
77
|
-
options.useJQuery =
|
|
78
|
-
(useJQuery === "true" || useJQuery === "yes" || useJQuery === "1");
|
|
79
|
-
}
|
|
80
|
-
if (system.args[7]) {
|
|
81
|
-
var verbose = system.args[7].toLowerCase();
|
|
82
|
-
options.verbose =
|
|
83
|
-
(verbose === "true" || verbose === "yes" || verbose === "1");
|
|
84
|
-
}
|
|
85
|
-
if (system.args[8] && system.args[8] !== "undefined") {
|
|
86
|
-
options.module = system.args[8];
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// ensure defaults, replaces false with false in two cases (useJQuery, verbose)
|
|
90
|
-
Object.keys(defaults).forEach(function(prop) {
|
|
91
|
-
if (!options[prop]) {
|
|
92
|
-
options[prop] = defaults[prop];
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
return options;
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
};
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* detectors.js
|
|
3
|
-
*
|
|
4
|
-
* A collection of detector functions that detect when a page is ready for a snapshot.
|
|
5
|
-
*
|
|
6
|
-
* The detector functions are run in PhantomJS page.evaluate in the context of a webpage,
|
|
7
|
-
* in a sandboxed execution context.
|
|
8
|
-
* Other special rules apply: http://phantomjs.org/api/webpage/method/evaluate.html
|
|
9
|
-
*
|
|
10
|
-
* The detector functions return true when the page is ready, false if not.
|
|
11
|
-
*
|
|
12
|
-
* This is a module for a phantomJS script that runs in phantomjs.
|
|
13
|
-
*
|
|
14
|
-
* Copyright (c) 2013 - 2025 Alex Grant, LocalNerve, contributors
|
|
15
|
-
* Licensed under the MIT license.
|
|
16
|
-
*/
|
|
17
|
-
/* global document, $ */
|
|
18
|
-
module.exports = {
|
|
19
|
-
|
|
20
|
-
// Use plain Web API detection, with standard selectors
|
|
21
|
-
// https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Getting_Started/Selectors
|
|
22
|
-
// Returns true on element visibility
|
|
23
|
-
querySelector: function(options) {
|
|
24
|
-
var result = false;
|
|
25
|
-
var el = document.querySelector(options.selector);
|
|
26
|
-
|
|
27
|
-
if (el) {
|
|
28
|
-
// el must be an HTMLElement that is visible
|
|
29
|
-
result = el.offsetWidth && el.offsetHeight;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return result;
|
|
33
|
-
},
|
|
34
|
-
|
|
35
|
-
// Use JQuery selectors
|
|
36
|
-
// Returns true on element visibility
|
|
37
|
-
jquerySelector: function(options) {
|
|
38
|
-
var result = false;
|
|
39
|
-
|
|
40
|
-
if (typeof $ !== "undefined") {
|
|
41
|
-
// the definition of document readiness is visibility
|
|
42
|
-
result = $(options.selector).is(":visible");
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return result;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
};
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* globals.js
|
|
3
|
-
*
|
|
4
|
-
* Globals and module utilities.
|
|
5
|
-
*
|
|
6
|
-
* This is a module for a phantomJS script that runs in phantomjs.
|
|
7
|
-
*
|
|
8
|
-
* Copyright (c) 2013 - 2025 Alex Grant, LocalNerve, contributors
|
|
9
|
-
* Licensed under the MIT license.
|
|
10
|
-
*/
|
|
11
|
-
/* global phantom */
|
|
12
|
-
/**
|
|
13
|
-
* Exit phantomJS
|
|
14
|
-
*/
|
|
15
|
-
function _exit(code, msg) {
|
|
16
|
-
if (code !== 0) {
|
|
17
|
-
console.error(msg);
|
|
18
|
-
} else {
|
|
19
|
-
console.log(msg);
|
|
20
|
-
}
|
|
21
|
-
phantom.exit(code);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Global error handler
|
|
26
|
-
*/
|
|
27
|
-
phantom.onError = function(msg, trace) {
|
|
28
|
-
var msgStack = ["PhantomJS error: " + msg];
|
|
29
|
-
if (trace && trace.length) {
|
|
30
|
-
msgStack.push("Trace:");
|
|
31
|
-
trace.forEach(function(t) {
|
|
32
|
-
msgStack.push(" -> " + (t.file || t.sourceURL) + ": " + t.line + (t.function ? " (in function " + t.function +")" : ""));
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
// Don't call _exit from here, causes strange crash w/linux rebuilt binary.
|
|
36
|
-
// https://github.com/ariya/phantomjs/issues/14132
|
|
37
|
-
console.log(msgStack.join("\n"));
|
|
38
|
-
phantom.exit(-1);
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
module.exports = {
|
|
42
|
-
exit: _exit
|
|
43
|
-
};
|