Skip to content

Commit

Permalink
Option to skip validation while building CI
Browse files Browse the repository at this point in the history
  • Loading branch information
dpilafian committed Apr 27, 2024
1 parent 716d268 commit 66e9684
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 10 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ _Check the markup validity of HTML files using the W3C validator_

[![License:MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/center-key/w3c-html-validator/blob/main/LICENSE.txt)
[![npm](https://img.shields.io/npm/v/w3c-html-validator.svg)](https://www.npmjs.com/package/w3c-html-validator)
[![Build](https://github.com/center-key/w3c-html-validator/workflows/build/badge.svg)](https://github.com/center-key/w3c-html-validator/actions/workflows/run-spec-on-push.yaml)
[![Build](https://github.com/center-key/w3c-html-validator/actions/workflows/run-spec-on-push.yaml/badge.svg)](https://github.com/center-key/w3c-html-validator/actions/workflows/run-spec-on-push.yaml)

**w3c-html-validator** takes HTML files and returns detailed validation results. 
The reporter produces formatted output indented for use in build scripts and test suites.
Expand Down Expand Up @@ -141,6 +141,7 @@ $ node examples.js
| `ignoreLevel` | `'info'` or `'warning'` | `null` | Skip unwanted messages.* |
| `ignoreMessages` | **array** | `[]` | Skip messages containing a string or matching a regex.* |
| `output` | `'json'` or `'html'` | `'json'` | Get results as an array or as a web page. |
| `skip` | **boolean** | `false` | bypass validation (for usage while building your CI). |
| `website` | **string** | `null` | URL of website to validate. |

*The `ignoreMessages` and `ignoreLevel` options only work for `'json'` output. 
Expand Down Expand Up @@ -171,6 +172,7 @@ type ValidatorResults = {
status: number,
messages: ValidatorResultsMessage[] | null, //for 'json' output
display: string | null, //for 'html' output
skip: boolean,
};
```

Expand Down
6 changes: 5 additions & 1 deletion bin/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ const ignore = cli.flagMap.ignore ?? null;
const ignoreConfig = cli.flagMap.ignoreConfig ?? null;
const delay = Number(cli.flagMap.delay) || 500; //default half second debounce pause
const trim = Number(cli.flagMap.trim) || null;
const skip = process.env.w3cHtmlValidator === 'skip'; //bash: export w3cHtmlValidator=skip

// Validator
const globOptions = { ignore: '**/node_modules/**/*' };
Expand All @@ -54,6 +55,8 @@ const error =
null;
if (error)
throw Error('[w3c-html-validator] ' + error);
if (skip)
w3cHtmlValidator.skipNotice();
if (filenames.length > 1 && !cli.flagOn.quiet)
w3cHtmlValidator.summary(filenames.length);
const reporterOptions = {
Expand All @@ -71,8 +74,9 @@ const getIgnoreMessages = () => {
const isRegex = /^\/.*\/$/; //starts and ends with a slash indicating it's a regex
return rawLines.map(line => isRegex.test(line) ? new RegExp(line.slice(1, -1)) : line);
};
const baseOptions = { ignoreMessages: getIgnoreMessages(), skip: skip };
const options = (filename) => ({ filename: filename, ...baseOptions });
const handleResults = (results) => w3cHtmlValidator.reporter(results, reporterOptions);
const options = (filename) => ({ filename: filename, ignoreMessages: getIgnoreMessages() });
const getReport = (filename) => w3cHtmlValidator.validate(options(filename)).then(handleResults);
const processFile = (filename, i) => globalThis.setTimeout(() => getReport(filename), i * delay);
filenames.forEach(processFile);
21 changes: 15 additions & 6 deletions spec/mocha.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,15 @@ describe('Library module', () => {
assertDeepStrictEqual(actual, expected);
});

it('has functions named validate(), summary(), and reporter()', () => {
it('has functions named validate(), skipNotice() summary(), and reporter()', () => {
const module = w3cHtmlValidator;
const actual = Object.keys(module).sort().map(key => [key, typeof module[key]]);
const expected = [
['reporter', 'function'],
['summary', 'function'],
['validate', 'function'],
['version', 'string'],
['reporter', 'function'],
['skipNotice', 'function'],
['summary', 'function'],
['validate', 'function'],
['version', 'string'],
];
assertDeepStrictEqual(actual, expected);
});
Expand All @@ -80,6 +81,7 @@ describe('Pretty-Print JSON website', () => {
status: 200,
messages: [],
display: null,
skip: false,
};
assertDeepStrictEqual(actual, expected, done);
};
Expand All @@ -105,6 +107,7 @@ describe('Valid HTML string', () => {
status: 200,
messages: [],
display: null,
skip: false,
};
assertDeepStrictEqual(actual, expected, done);
};
Expand All @@ -125,6 +128,7 @@ describe('Valid HTML string', () => {
output: 'html',
status: 200,
messages: null,
skip: false,
};
assertDeepStrictEqual(actual, expected, done);
};
Expand Down Expand Up @@ -176,6 +180,7 @@ describe('Invalid HTML string', () => {
},
],
display: null,
skip: false,
};
assertDeepStrictEqual(actual, expected, done);
};
Expand All @@ -196,6 +201,7 @@ describe('Invalid HTML string', () => {
output: 'html',
status: 200,
messages: null,
skip: false,
};
assertDeepStrictEqual(actual, expected, done);
};
Expand All @@ -221,6 +227,7 @@ describe('HTML file', () => {
status: 200,
messages: [],
display: null,
skip: false,
};
assertDeepStrictEqual(actual, expected, done);
};
Expand Down Expand Up @@ -346,11 +353,12 @@ describe('Network request failure', () => {
website: null,
output: 'json',
status: 503,
display: null,
messages: [{
type: 'network-error',
message: '503 Service Unavailable https://centerkey.com/rest/status/503/?out=json',
}],
display: null,
skip: false,
};
assertDeepStrictEqual(actual, expected, done);
};
Expand Down Expand Up @@ -381,6 +389,7 @@ describe('The reporter() function', () => {
status: 200,
messages: [],
display: null,
skip: false,
};
assertDeepStrictEqual(actual, expected, done);
};
Expand Down
21 changes: 19 additions & 2 deletions w3c-html-validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export type ValidatorSettings = {
ignoreLevel: 'info' | 'warning', //skip unwanted validation messages ('warning' also skips 'info')
ignoreMessages: (string | RegExp)[], //patterns to skip unwanted validation messages
output: ValidatorResultsOutput, //'json' or 'html'
skip: boolean, //bypass validation (for usage while building your CI)
};
export type ValidatorResultsMessage = {
// type subType
Expand Down Expand Up @@ -47,6 +48,7 @@ export type ValidatorResults = {
status: number,
messages: ValidatorResultsMessage[] | null,
display: string | null,
skip: boolean,
};
export type ValidatorResultsOutput = ValidatorResults['output'];
export type ReporterSettings = {
Expand All @@ -59,14 +61,15 @@ export type ReporterSettings = {
// W3C HTML Validator
const w3cHtmlValidator = {

version: '{{pkg.version}}',
version: '{{package.version}}',

validate(options: Partial<ValidatorSettings>): Promise<ValidatorResults> {
const defaults = {
checkUrl: 'https://validator.w3.org/nu/',
ignoreLevel: null,
ignoreMessages: [],
output: 'json',
skip: false,
};
const settings = { ...defaults, ...options };
if (!settings.html && !settings.filename && !settings.website)
Expand Down Expand Up @@ -119,6 +122,7 @@ const w3cHtmlValidator = {
status: response.statusCode || -1,
messages: json ? response.body.messages : null,
display: json ? null : response.text,
skip: settings.skip,
});
type ReasonResponse = { request: { url: string }, res: { statusMessage: string }};
type ReasonError = Error & { errno: number, response: request.Response & ReasonResponse };
Expand All @@ -129,7 +133,20 @@ const w3cHtmlValidator = {
errRes.body = { messages: [{ type: 'network-error', message: message.join(' ') }] };
return toValidatorResults(errRes);
};
return w3cRequest.then(filterMessages).then(toValidatorResults).catch(handleError);
const pseudoResponse = <request.Response>{
statusCode: 200,
body: { messages: [] },
text: 'Validation skipped.',
};
const pseudoRequest = (): Promise<request.Response> =>
new Promise(resolve => resolve(pseudoResponse));
const validation = settings.skip ? pseudoRequest() : w3cRequest;
return validation.then(filterMessages).then(toValidatorResults).catch(handleError);
},

skipNotice() {
log(chalk.gray('w3c-html-validator'),
chalk.yellowBright('skip mode:'), chalk.whiteBright('validation being bypassed'));
},

summary(numFiles: number) {
Expand Down

0 comments on commit 66e9684

Please sign in to comment.