w3c-html-validator 2.0.0 → 2.0.1

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
@@ -62,8 +62,7 @@ Command-line flags:
62
62
  | `--quiet` | Suppress messages for successful validations. | N/A |
63
63
  | `--trim` | Truncate validation messages to not exceed a maximum length. | **number** |
64
64
 
65
- ### 4. Example CLI usage
66
- Examples:
65
+ ### 4. Examples
67
66
  - `html-validator`<br>
68
67
  Validates all HTML files in the project.
69
68
 
package/bin/cli.js CHANGED
@@ -21,63 +21,6 @@
21
21
  // $ npm test
22
22
  // $ node bin/cli.js spec --continue
23
23
 
24
- // Imports
25
- import { cliArgvUtil } from 'cli-argv-util';
26
- import { globSync } from 'glob';
27
24
  import { w3cHtmlValidator } from '../dist/w3c-html-validator.js';
28
- import fs from 'fs';
29
- import slash from 'slash';
30
25
 
31
- // Parameters and flags
32
- const validFlags = ['continue', 'default-rules', 'delay', 'dry-run', 'exclude',
33
- 'ignore', 'ignore-config', 'note', 'quiet', 'trim'];
34
- const cli = cliArgvUtil.parse(validFlags);
35
- const files = cli.params.length ? cli.params.map(cliArgvUtil.cleanPath) : ['.'];
36
- const excludeList = cli.flagMap.exclude?.split(',') ?? [];
37
- const ignore = cli.flagMap.ignore ?? null;
38
- const ignoreConfig = cli.flagMap.ignoreConfig ?? null;
39
- const defaultRules = cli.flagOn.defaultRules;
40
- const delay = Number(cli.flagMap.delay) || 500; //default half second debounce pause
41
- const trim = Number(cli.flagMap.trim) || null;
42
- const dryRun = cli.flagOn.dryRun || process.env.w3cHtmlValidator === 'dry-run'; //bash: export w3cHtmlValidator=dry-run
43
-
44
- const getFilenames = () => {
45
- const readFilenames = (file) => globSync(file, { ignore: '**/node_modules/**/*' }).map(slash);
46
- const readHtmlFiles = (folder) => readFilenames(folder + '/**/*.html');
47
- const addHtml = (file) => fs.lstatSync(file).isDirectory() ? readHtmlFiles(file) : file;
48
- const keep = (file) => excludeList.every(exclude => !file.includes(exclude));
49
- return files.map(readFilenames).flat().map(addHtml).flat().filter(keep).sort();
50
- };
51
- const filenames = getFilenames();
52
- const error =
53
- cli.invalidFlag ? cli.invalidFlagMsg :
54
- !filenames.length ? 'No files to validate.' :
55
- cli.flagOn.trim && !trim ? 'Value of "trim" must be a positive whole number.' :
56
- null;
57
- if (error)
58
- throw new Error('[w3c-html-validator] ' + error);
59
- if (dryRun)
60
- w3cHtmlValidator.dryRunNotice();
61
- if (filenames.length > 1 && !cli.flagOn.quiet)
62
- w3cHtmlValidator.summary(filenames.length);
63
- const reporterOptions = {
64
- continueOnFail: cli.flagOn.continue,
65
- quiet: cli.flagOn.quiet,
66
- maxMessageLen: trim,
67
- };
68
- const getIgnoreMessages = () => {
69
- const toArray = (text) => text.replace(/\r/g, '').split('\n').map(line => line.trim());
70
- const notComment = (line) => line.length > 1 && !line.startsWith('#');
71
- const readLines = (file) => toArray(fs.readFileSync(file).toString()).filter(notComment);
72
- const rawLines = ignoreConfig ? readLines(ignoreConfig) : [];
73
- if (ignore)
74
- rawLines.push(ignore);
75
- const isRegex = /^\/.*\/$/; //starts and ends with a slash indicating it's a regex
76
- return rawLines.map(line => isRegex.test(line) ? new RegExp(line.slice(1, -1)) : line);
77
- };
78
- const ignoreMessages = getIgnoreMessages();
79
- const options = (filename) => ({ filename, ignoreMessages, defaultRules, dryRun });
80
- const handleResults = (results) => w3cHtmlValidator.reporter(results, reporterOptions);
81
- const getReport = (filename) => w3cHtmlValidator.validate(options(filename)).then(handleResults);
82
- const processFile = (filename, i) => globalThis.setTimeout(() => getReport(filename), i * delay);
83
- filenames.forEach(processFile);
26
+ w3cHtmlValidator.cli();
@@ -1,14 +1,14 @@
1
- //! w3c-html-validator v2.0.0 ~~ https://github.com/center-key/w3c-html-validator ~~ MIT License
1
+ //! w3c-html-validator v2.0.1 ~~ https://github.com/center-key/w3c-html-validator ~~ MIT License
2
2
 
3
3
  export type ValidatorSettings = {
4
- html: string;
5
- filename: string;
6
- website: string;
7
- checkUrl: string;
8
- ignoreLevel: 'info' | 'warning';
4
+ html: string | null;
5
+ filename: string | null;
6
+ website: string | null;
7
+ checkUrl: string | null;
8
+ ignoreLevel: 'info' | 'warning' | null;
9
9
  ignoreMessages: ValidatorIgnorePattern[];
10
10
  defaultRules: boolean;
11
- output: ValidatorResultsOutput;
11
+ output: 'json' | 'html' | null;
12
12
  dryRun: boolean;
13
13
  };
14
14
  export type ValidatorIgnorePattern = string | RegExp;
@@ -38,7 +38,6 @@ export type ValidatorResults = {
38
38
  display: string | null;
39
39
  dryRun: boolean;
40
40
  };
41
- export type ValidatorResultsOutput = ValidatorResults['output'];
42
41
  export type ReporterSettings = {
43
42
  continueOnFail: boolean;
44
43
  maxMessageLen: number | null;
@@ -48,6 +47,8 @@ export type ReporterSettings = {
48
47
  declare const w3cHtmlValidator: {
49
48
  version: string;
50
49
  defaultIgnoreList: string[];
50
+ assert(ok: unknown, message: string | null): void;
51
+ cli(): void;
51
52
  validate(options: Partial<ValidatorSettings>): Promise<ValidatorResults>;
52
53
  dryRunNotice(): void;
53
54
  summary(numFiles: number): void;
@@ -1,31 +1,94 @@
1
- //! w3c-html-validator v2.0.0 ~~ https://github.com/center-key/w3c-html-validator ~~ MIT License
1
+ //! w3c-html-validator v2.0.1 ~~ https://github.com/center-key/w3c-html-validator ~~ MIT License
2
2
 
3
+ import { cliArgvUtil } from 'cli-argv-util';
4
+ import { globSync } from 'glob';
3
5
  import chalk from 'chalk';
4
6
  import fs from 'fs';
5
7
  import log from 'fancy-log';
6
8
  import request from 'superagent';
7
9
  import slash from 'slash';
8
10
  const w3cHtmlValidator = {
9
- version: '2.0.0',
11
+ version: '2.0.1',
10
12
  defaultIgnoreList: [
11
13
  'Section lacks heading.'
12
14
  ],
15
+ assert(ok, message) {
16
+ if (!ok)
17
+ throw new Error(`[w3c-html-validator] ${message}`);
18
+ },
19
+ cli() {
20
+ const validFlags = ['continue', 'default-rules', 'delay', 'dry-run', 'exclude',
21
+ 'ignore', 'ignore-config', 'note', 'quiet', 'trim'];
22
+ const cli = cliArgvUtil.parse(validFlags);
23
+ const files = cli.params.length ? cli.params.map(cliArgvUtil.cleanPath) : ['.'];
24
+ const excludeList = cli.flagMap.exclude?.split(',') ?? [];
25
+ const ignore = cli.flagMap.ignore ?? null;
26
+ const ignoreConfig = cli.flagMap.ignoreConfig ?? null;
27
+ const defaultRules = cli.flagOn.defaultRules;
28
+ const delay = Number(cli.flagMap.delay) || 500;
29
+ const trim = Number(cli.flagMap.trim) || null;
30
+ const dryRun = cli.flagOn.dryRun || process.env.w3cHtmlValidator === 'dry-run';
31
+ const getFilenames = () => {
32
+ const readFilenames = (file) => globSync(file, { ignore: '**/node_modules/**/*' }).map(slash);
33
+ const readHtmlFiles = (folder) => readFilenames(folder + '/**/*.html');
34
+ const addHtml = (file) => fs.lstatSync(file).isDirectory() ? readHtmlFiles(file) : file;
35
+ const keep = (file) => excludeList.every(exclude => !file.includes(exclude));
36
+ return files.map(readFilenames).flat().map(addHtml).flat().filter(keep).sort();
37
+ };
38
+ const filenames = getFilenames();
39
+ const error = cli.invalidFlag ? cli.invalidFlagMsg :
40
+ !filenames.length ? 'No files to validate.' :
41
+ cli.flagOn.trim && !trim ? 'Value of "trim" must be a positive whole number.' :
42
+ null;
43
+ w3cHtmlValidator.assert(!error, error);
44
+ if (dryRun)
45
+ w3cHtmlValidator.dryRunNotice();
46
+ if (filenames.length > 1 && !cli.flagOn.quiet)
47
+ w3cHtmlValidator.summary(filenames.length);
48
+ const reporterOptions = {
49
+ continueOnFail: cli.flagOn.continue,
50
+ maxMessageLen: trim,
51
+ quiet: cli.flagOn.quiet,
52
+ title: null,
53
+ };
54
+ const getIgnoreMessages = () => {
55
+ const toArray = (text) => text.replace(/\r/g, '').split('\n').map(line => line.trim());
56
+ const notComment = (line) => line.length > 1 && !line.startsWith('#');
57
+ const readLines = (file) => toArray(fs.readFileSync(file).toString()).filter(notComment);
58
+ const rawLines = ignoreConfig ? readLines(ignoreConfig) : [];
59
+ if (ignore)
60
+ rawLines.push(ignore);
61
+ const isRegex = /^\/.*\/$/;
62
+ return rawLines.map(line => isRegex.test(line) ? new RegExp(line.slice(1, -1)) : line);
63
+ };
64
+ const ignoreMessages = getIgnoreMessages();
65
+ const options = (filename) => ({ filename, ignoreMessages, defaultRules, dryRun });
66
+ const handleResults = (results) => w3cHtmlValidator.reporter(results, reporterOptions);
67
+ const getReport = (filename) => w3cHtmlValidator.validate(options(filename)).then(handleResults);
68
+ const processFile = (filename, i) => globalThis.setTimeout(() => getReport(filename), i * delay);
69
+ filenames.forEach(processFile);
70
+ },
13
71
  validate(options) {
14
72
  const defaults = {
15
73
  checkUrl: 'https://validator.w3.org/nu/',
16
74
  defaultRules: false,
17
75
  dryRun: false,
76
+ filename: null,
77
+ html: null,
18
78
  ignoreLevel: null,
19
79
  ignoreMessages: [],
20
80
  output: 'json',
81
+ website: null,
21
82
  };
22
83
  const settings = { ...defaults, ...options };
23
- if (!settings.html && !settings.filename && !settings.website)
24
- throw new Error('[w3c-html-validator] Must specify the "html", "filename", or "website" option.');
25
- if (![null, 'info', 'warning'].includes(settings.ignoreLevel))
26
- throw new Error(`[w3c-html-validator] Invalid ignoreLevel option: ${settings.ignoreLevel}`);
27
- if (settings.output !== 'json' && settings.output !== 'html')
28
- throw new Error('[w3c-html-validator] Option "output" must be "json" or "html".');
84
+ const missingInput = !settings.html && !settings.filename && !settings.website;
85
+ const badLevel = ![null, 'info', 'warning'].includes(settings.ignoreLevel);
86
+ const invalidOutput = settings.output !== 'json' && settings.output !== 'html';
87
+ const error = missingInput ? 'Must specify the "html", "filename", or "website" option.' :
88
+ badLevel ? `Invalid ignoreLevel option: ${settings.ignoreLevel}` :
89
+ invalidOutput ? 'Option "output" must be "json" or "html".' :
90
+ null;
91
+ w3cHtmlValidator.assert(!error, error);
29
92
  const filename = settings.filename ? slash(settings.filename) : null;
30
93
  const mode = settings.html ? 'html' : filename ? 'filename' : 'website';
31
94
  const unixify = (text) => text.replace(/\r/g, '');
@@ -102,8 +165,8 @@ const w3cHtmlValidator = {
102
165
  title: null,
103
166
  };
104
167
  const settings = { ...defaults, ...options };
105
- if (typeof results?.validates !== 'boolean')
106
- throw new Error(`[w3c-html-validator] Invalid results for reporter(): ${results}`);
168
+ const hasResults = 'validates' in results && typeof results.validates === 'boolean';
169
+ w3cHtmlValidator.assert(hasResults, `Invalid results for reporter(): ${results}`);
107
170
  const messages = results.messages ?? [];
108
171
  const title = settings.title ?? results.title;
109
172
  const status = results.validates ? chalk.green.bold('✔ pass') : chalk.red.bold('✘ fail');
@@ -131,8 +194,8 @@ const w3cHtmlValidator = {
131
194
  const fileDetails = () => `${results.filename} -- ${results.messages.map(toString).join(', ')}`;
132
195
  return !results.filename ? results.messages[0].message : fileDetails();
133
196
  };
134
- if (!settings.continueOnFail && !results.validates)
135
- throw new Error(`[w3c-html-validator] Failed: ${failDetails()}`);
197
+ const failed = !settings.continueOnFail && !results.validates;
198
+ w3cHtmlValidator.assert(!failed, `Failed: ${failDetails()}`);
136
199
  return results;
137
200
  },
138
201
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "w3c-html-validator",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "Check the markup validity of HTML files using the W3C validator",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -65,18 +65,18 @@
65
65
  "superagent": "~10.2"
66
66
  },
67
67
  "devDependencies": {
68
- "@eslint/js": "~9.38",
68
+ "@eslint/js": "~9.39",
69
69
  "@types/fancy-log": "~2.0",
70
- "@types/node": "~24.9",
70
+ "@types/node": "~24.10",
71
71
  "@types/superagent": "~8.1",
72
- "add-dist-header": "~1.5",
72
+ "add-dist-header": "~1.6",
73
73
  "assert-deep-strict-equal": "~1.2",
74
74
  "copy-file-util": "~1.3",
75
75
  "copy-folder-util": "~1.1",
76
- "eslint": "~9.38",
76
+ "eslint": "~9.39",
77
77
  "jshint": "~2.13",
78
78
  "mocha": "~11.7",
79
- "rimraf": "~6.0",
79
+ "rimraf": "~6.1",
80
80
  "run-scripts-util": "~1.3",
81
81
  "typescript": "~5.9",
82
82
  "typescript-eslint": "~8.46"