pagean 15.6.6 → 16.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/README.md CHANGED
@@ -15,6 +15,10 @@ Install Pagean globally (as shown below), or locally, via
15
15
  npm install -g pagean
16
16
  ```
17
17
 
18
+ If `puppeteer` issues are encountered during installation, see the
19
+ [system requirements](https://github.com/puppeteer/puppeteer/blob/main/docs/guides/system-requirements.md)
20
+ for complete details. These should be standard for most installations.
21
+
18
22
  ## Usage
19
23
 
20
24
  Pagean runs as a command line tool and is executed as follows:
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { Levels, log } from 'ci-logger';
4
- import kleur from 'kleur';
5
4
  import { program } from 'commander';
5
+ import { styleText } from 'node:util';
6
6
 
7
7
  import { formatErrors } from '../lib/schema-errors.js';
8
8
  import { lintConfigFile } from '../lib/config.js';
@@ -35,9 +35,11 @@ const outputJsonResults = (configFileName, lintResults) => {
35
35
 
36
36
  const outputConsoleResults = (configFileName, lintResults) => {
37
37
  if (lintResults.isValid) {
38
- log({ message: `\n${configFileName}: ${kleur.green('valid')}\n` });
38
+ log({
39
+ message: `\n${configFileName}: ${styleText('green', 'valid')}\n`
40
+ });
39
41
  } else {
40
- logError(`\n${kleur.underline(configFileName)}`, false);
42
+ logError(`\n${styleText('underline', configFileName)}`, false);
41
43
  for (const error of formatErrors(lintResults.errors)) {
42
44
  logError(error, false);
43
45
  }
@@ -7,8 +7,6 @@
7
7
  import fs from 'node:fs';
8
8
  import path from 'node:path';
9
9
 
10
- import axios from 'axios';
11
-
12
10
  const externalFilePath = 'pagean-external-scripts';
13
11
 
14
12
  /**
@@ -58,14 +56,17 @@ const saveExternalScript = async (script) => {
58
56
  // Path generated above from URL, not from user input.
59
57
  // nosemgrep: eslint.detect-non-literal-fs-filename
60
58
  if (!fs.existsSync(pathName)) {
61
- // Axios will throw for any error response
62
- const response = await axios.get(script);
59
+ const response = await fetch(script);
60
+ if (!response.ok) {
61
+ throw new Error(`HTTP ${response.status}`);
62
+ }
63
+ const data = await response.text();
63
64
  // Path generated above from URL, not from user input.
64
65
  // nosemgrep: eslint.detect-non-literal-fs-filename
65
66
  fs.mkdirSync(path.dirname(pathName), { recursive: true });
66
67
  // Path generated above from URL, not from user input.
67
68
  // nosemgrep: eslint.detect-non-literal-fs-filename
68
- fs.writeFileSync(pathName, response.data);
69
+ fs.writeFileSync(pathName, data);
69
70
  }
70
71
  result.localFile = pathName;
71
72
  } catch (error) {
@@ -4,9 +4,7 @@
4
4
  * @module link-utilities
5
5
  */
6
6
 
7
- import https from 'node:https';
8
-
9
- import axios from 'axios';
7
+ import { Agent } from 'undici';
10
8
  import cssesc from 'cssesc';
11
9
  import normalizeUrl from 'normalize-url';
12
10
 
@@ -128,7 +126,7 @@ const checkExternalPageLinkBrowser = async (page, link) => {
128
126
  };
129
127
 
130
128
  /**
131
- * Checks the provided link for validity by requesting with axios. If useGet if false,
129
+ * Checks the provided link for validity by requesting with fetch. If useGet is false,
132
130
  * a HEAD request is made for efficiency. If useGet is true, a full GET request is made.
133
131
  *
134
132
  * @param {Page} page A Puppeteer page object.
@@ -144,43 +142,38 @@ const checkExternalPageLink = async (page, link, useGet = false) => {
144
142
  return 'Cannot check "file:" URLs';
145
143
  }
146
144
 
147
- // Get user-agent from page so axios uses the same value for requesting links
145
+ // Get user-agent from page so fetch uses the same value for requesting links
148
146
  const userAgent = await page.evaluate('navigator.userAgent');
149
147
 
150
148
  try {
151
- const options = {
152
- decompress: false,
149
+ const fetchOptions = {
153
150
  headers: { 'User-Agent': userAgent },
154
- timeout: timeoutSeconds * msPerSec
155
- // Axios can generate an error trying to decompress an empty compressed
156
- // HEAD response, see https://github.com/axios/axios/issues/5102.
157
- // The response body is also not used, so more efficient to skip.
151
+ method: useGet ? 'GET' : 'HEAD',
152
+ signal: AbortSignal.timeout(timeoutSeconds * msPerSec)
158
153
  };
159
154
  // Using internal browser property since not exposed
160
155
  /* eslint-disable-next-line no-underscore-dangle -- require to match
161
156
  Puppeteer API */
162
157
  if (page.browser()._ignoreHTTPSErrors) {
163
- const agent = new https.Agent({ rejectUnauthorized: false });
164
- options.httpsAgent = agent;
158
+ fetchOptions.dispatcher = new Agent({
159
+ connect: { rejectUnauthorized: false }
160
+ });
165
161
  }
166
- const httpMethod = useGet ? axios.get : axios.head;
167
- const response = await httpMethod(link, options);
168
- return response.status;
169
- } catch (error) {
162
+ const response = await fetch(link, fetchOptions);
170
163
  // Some servers respond invalid for head request (e.g. a lot of 405 Method
171
- // Not Allowed), so if a response was returned, is not a response that should
172
- // skip a retry (e.g. 429), and the request was head then retry with get.
173
- if (
174
- error.response &&
175
- !noRetryResponses.has(error.response.status) &&
176
- !useGet
177
- ) {
178
- return checkExternalPageLink(page, link, true);
164
+ // Not Allowed), so if a non-2xx response was returned, is not a response
165
+ // that should skip a retry (e.g. 429), and the request was head then retry
166
+ // with get.
167
+ if (!response.ok) {
168
+ if (!noRetryResponses.has(response.status) && !useGet) {
169
+ return checkExternalPageLink(page, link, true);
170
+ }
171
+ return response.status;
179
172
  }
180
-
181
- // Axios will throw for failed response (code >= 400), so return
182
- // that response code or the error code if execution error
183
- return error.response ? error.response.status : error.code;
173
+ return response.status;
174
+ } catch (error) {
175
+ // Fetch throws for network/execution errors; return the error code or name
176
+ return error.code ?? error.name;
184
177
  }
185
178
  };
186
179
 
@@ -4,7 +4,7 @@
4
4
  * @module schema-errors
5
5
  */
6
6
 
7
- import kleur from 'kleur';
7
+ import { styleText } from 'node:util';
8
8
 
9
9
  const getDataKey = (instancePath) => {
10
10
  const baseKey = '<pageanrc>';
@@ -64,7 +64,8 @@ const formatErrors = (errors) => {
64
64
  }
65
65
  return errors.map(
66
66
  (error) =>
67
- ` ${error.dataKey.padEnd(maxLength + margin)}${kleur.red(
67
+ ` ${error.dataKey.padEnd(maxLength + margin)}${styleText(
68
+ 'red',
68
69
  error.formattedMessage
69
70
  )}`
70
71
  );
package/lib/sitemap.js CHANGED
@@ -5,8 +5,6 @@
5
5
  */
6
6
 
7
7
  import fs from 'node:fs';
8
-
9
- import axios from 'axios';
10
8
  import { parseStringPromise } from 'xml2js';
11
9
 
12
10
  /**
@@ -21,8 +19,11 @@ import { parseStringPromise } from 'xml2js';
21
19
  const getSitemap = async (url) => {
22
20
  try {
23
21
  if (url.startsWith('http')) {
24
- const response = await axios.get(url);
25
- return response.data;
22
+ const response = await fetch(url);
23
+ if (!response.ok) {
24
+ throw new Error(`HTTP ${response.status}`);
25
+ }
26
+ return await response.text();
26
27
  }
27
28
  // Allow users to specify a local sitemap filename.
28
29
  // nosemgrep: eslint.detect-non-literal-fs-filename
package/lib/utilities.js CHANGED
@@ -12,9 +12,7 @@ import { readFile } from 'node:fs/promises';
12
12
  *
13
13
  * @type {string}
14
14
  */
15
- /* eslint-disable-next-line no-underscore-dangle, node/no-unsupported-features/node-builtins --
16
- match CJS name; per https://github.com/nodejs/node/commit/e21b37d9df there were no code changes,
17
- just documenting the promotion in Node 22.16.0. */
15
+ // eslint-disable-next-line no-underscore-dangle -- match CJS name
18
16
  const __dirname = import.meta.dirname;
19
17
 
20
18
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pagean",
3
- "version": "15.6.6",
3
+ "version": "16.0.0",
4
4
  "description": "Pagean is a web page analysis tool designed to automate tests requiring web pages to be loaded in a browser window (e.g. horizontal scrollbar, console errors)",
5
5
  "bin": {
6
6
  "pagean": "bin/pagean.js",
@@ -42,7 +42,7 @@
42
42
  "author": "Aaron Goldenthal <npm@aarongoldenthal.com>",
43
43
  "license": "MIT",
44
44
  "engines": {
45
- "node": "^20.11.0 || ^22.11.0 || >=24.0.0"
45
+ "node": "^22.19.0 || ^24.11.0 || >=26"
46
46
  },
47
47
  "files": [
48
48
  "index.js",
@@ -56,32 +56,31 @@
56
56
  },
57
57
  "homepage": "https://gitlab.com/gitlab-ci-utils/pagean",
58
58
  "devDependencies": {
59
- "@aarongoldenthal/eslint-config-standard": "45.0.1",
60
- "@aarongoldenthal/stylelint-config-standard": "23.0.0",
61
- "@vitest/coverage-v8": "4.1.5",
62
- "bin-tester": "7.0.1",
59
+ "@aarongoldenthal/eslint-config-standard": "46.0.1",
60
+ "@aarongoldenthal/stylelint-config-standard": "24.0.0",
61
+ "@vitest/coverage-v8": "4.1.7",
62
+ "bin-tester": "8.0.0",
63
63
  "c8": "11.0.0",
64
- "eslint": "10.2.1",
65
- "globals": "17.5.0",
66
- "markdownlint-cli2": "0.22.0",
64
+ "eslint": "10.4.0",
65
+ "globals": "17.6.0",
66
+ "markdownlint-cli2": "0.22.1",
67
67
  "nyc": "18.0.0",
68
68
  "prettier": "3.8.3",
69
- "stylelint": "17.8.0",
70
- "vitest": "4.1.5"
69
+ "stylelint": "17.12.0",
70
+ "vitest": "4.1.7"
71
71
  },
72
72
  "dependencies": {
73
- "ajv": "8.18.0",
73
+ "ajv": "8.20.0",
74
74
  "ajv-errors": "3.0.0",
75
- "axios": "1.15.2",
76
- "ci-logger": "8.0.1",
75
+ "ci-logger": "9.0.0",
77
76
  "commander": "14.0.3",
78
77
  "cssesc": "3.0.0",
79
78
  "handlebars": "4.7.9",
80
79
  "htmlhint": "1.9.2",
81
- "kleur": "4.1.5",
82
- "normalize-url": "9.0.0",
80
+ "normalize-url": "9.0.1",
83
81
  "protocolify": "4.0.0",
84
- "puppeteer": "24.42.0",
82
+ "puppeteer": "25.0.4",
83
+ "undici": "8.3.0",
85
84
  "xml2js": "0.6.2"
86
85
  }
87
86
  }