html-validate
Version:
Offline HTML5 validator and linter
272 lines (261 loc) • 7.62 kB
JavaScript
;
var fs = require('fs');
var path = require('node:path');
var kleur = require('kleur');
var minimist = require('minimist');
var core = require('./core.js');
var cli = require('./cli.js');
require('ajv');
require('./elements.js');
require('./meta-helper.js');
require('./utils/natural-join.js');
require('@sidvind/better-ajv-errors');
require('@html-validate/stylish');
require('semver');
require('./core-nodejs.js');
require('node:fs');
require('node:fs/promises');
require('node:url');
require('node:path/posix');
require('glob');
require('prompts');
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
var fs__default = /*#__PURE__*/_interopDefault(fs);
var path__default = /*#__PURE__*/_interopDefault(path);
var kleur__default = /*#__PURE__*/_interopDefault(kleur);
var minimist__default = /*#__PURE__*/_interopDefault(minimist);
function getMode(argv2) {
if (argv2.init) {
return cli.Mode.INIT;
}
if (argv2["dump-events"]) {
return cli.Mode.DUMP_EVENTS;
}
if (argv2["dump-source"]) {
return cli.Mode.DUMP_SOURCE;
}
if (argv2["dump-tokens"]) {
return cli.Mode.DUMP_TOKENS;
}
if (argv2["dump-tree"]) {
return cli.Mode.DUMP_TREE;
}
if (argv2["print-config"]) {
return cli.Mode.PRINT_CONFIG;
}
return cli.Mode.LINT;
}
function requiresFilename(mode) {
switch (mode) {
case cli.Mode.LINT:
return true;
case cli.Mode.INIT:
return false;
case cli.Mode.DUMP_EVENTS:
case cli.Mode.DUMP_TOKENS:
case cli.Mode.DUMP_TREE:
case cli.Mode.DUMP_SOURCE:
case cli.Mode.PRINT_CONFIG:
return true;
}
}
function handleUserError(err) {
const formatted = err.prettyFormat();
if (formatted) {
console.error();
console.error(formatted);
return;
}
console.error(kleur__default.default.red("Caught exception:"));
console.group();
{
console.error(err.prettyFormat() ?? err);
}
console.groupEnd();
}
function handleUnknownError(err) {
console.error(kleur__default.default.red("Caught exception:"));
console.group();
{
console.error(err);
}
console.groupEnd();
const bugUrl = `${core.bugs}?issuable_template=Bug`;
console.error(kleur__default.default.red(`This is a bug in ${core.name}-${core.version}.`));
console.error(
kleur__default.default.red(
[
`Please file a bug at ${bugUrl}`,
`and include this message in full and if possible the content of the`,
`file being parsed (or a reduced testcase).`
].join("\n")
)
);
}
const argv = minimist__default.default(process.argv.slice(2), {
string: [
"c",
"config",
"ext",
"f",
"formatter",
"max-warnings",
"p",
"preset",
"rule",
"stdin-filename"
],
boolean: [
"init",
"dump-events",
"dump-source",
"dump-tokens",
"dump-tree",
"h",
"help",
"print-config",
"stdin",
"version"
],
alias: {
c: "config",
f: "formatter",
p: "preset",
h: "help"
},
default: {
ext: "html",
formatter: "stylish"
},
unknown: (opt) => {
if (opt.startsWith("-")) {
process.stderr.write(`unknown option ${opt}
`);
process.exit(1);
}
return true;
}
});
function showUsage() {
process.stdout.write(`${core.name}-${core.version}
Usage: html-validate [OPTIONS] [FILENAME..] [DIR..]
Common options:
--ext=STRING specify file extensions (commaseparated).
-f, --formatter=FORMATTER specify the formatter to use.
--max-warnings=INT number of warnings to trigger nonzero exit code
-p, --preset=STRING configuration preset to use, use
comma-separator for multiple presets. (default:
"recommended")
--rule=RULE:SEVERITY set additional rule, use comma separator for
multiple.
--stdin process markup from stdin.
--stdin-filename=STRING specify filename to report when using stdin
Miscellaneous:
-c, --config=STRING use custom configuration file.
--init initialize project with a new configuration
--print-config output configuration for given file.
-h, --help show help.
--version show version.
Debugging options:
--dump-events output events during parsing.
--dump-source output post-transformed source data.
--dump-tokens output tokens from lexing stage.
--dump-tree output nodes from the dom tree.
Formatters:
Multiple formatters can be specified with a comma-separated list,
e.g. "json,checkstyle" to enable both.
To capture output to a file use "formatter=/path/to/file",
e.g. "checkstyle=dist/html-validate.xml"
`);
}
function showVersion() {
process.stdout.write(`${core.name}-${core.version}
`);
}
if (argv.stdin) {
argv._.push("-");
}
if (argv.version) {
showVersion();
process.exit();
}
if (argv.help) {
showUsage();
process.exit();
}
if (argv._.length === 0) {
const mode = getMode(argv);
if (mode === cli.Mode.LINT) {
showUsage();
process.exit(0);
} else if (requiresFilename(mode)) {
const flag = cli.modeToFlag(mode);
console.error(`\`${flag}\` requires a filename.`);
process.exit(1);
}
}
if (typeof argv.config !== "undefined") {
const checkPath = path__default.default.resolve(argv.config);
if (!fs__default.default.existsSync(checkPath)) {
console.error(`The file "${argv.config}" was not found.`);
console.error(`The location this file was checked for at was: "${checkPath}"`);
process.exit(1);
}
}
async function run() {
const cli$1 = new cli.CLI({
configFile: argv.config,
preset: argv.preset,
rules: argv.rule
});
const mode = getMode(argv);
const formatter = await cli$1.getFormatter(argv.formatter);
const maxWarnings = parseInt(argv["max-warnings"] ?? "-1", 10);
const htmlvalidate = await cli$1.getValidator();
if (isNaN(maxWarnings)) {
console.error(`Invalid value "${String(argv["max-warnings"])}" given to --max-warnings`);
process.exit(1);
}
const extensions = argv.ext.split(",").map((cur) => {
return cur.startsWith(".") ? cur.slice(1) : cur;
});
const files = await cli$1.expandFiles(argv._, { extensions });
if (files.length === 0 && mode !== cli.Mode.INIT) {
console.error("No files matching patterns", argv._);
process.exit(1);
}
try {
if (!cli.haveImportMetaResolve()) {
throw new cli.ImportResolveMissingError();
}
let success;
if (mode === cli.Mode.LINT) {
success = await cli.lint(htmlvalidate, process.stdout, files, {
formatter,
maxWarnings,
stdinFilename: argv["stdin-filename"] ?? false
});
} else if (mode === cli.Mode.INIT) {
success = await cli.init(cli$1, process.stdout, { cwd: process.cwd() });
} else if (mode === cli.Mode.PRINT_CONFIG) {
success = await cli.printConfig(htmlvalidate, process.stdout, files);
} else {
success = await cli.dump(htmlvalidate, process.stdout, files, mode);
}
process.exit(success ? 0 : 1);
} catch (err) {
if (err instanceof core.SchemaValidationError) {
cli.handleSchemaValidationError(console, err);
} else if (core.isUserError(err)) {
handleUserError(err);
} else {
handleUnknownError(err);
}
process.exit(1);
}
}
run().catch((err) => {
console.error(err);
process.exit(1);
});
//# sourceMappingURL=html-validate.js.map