Commit aa544d68 authored by David Sveningsson's avatar David Sveningsson

feat(cli): support passing options to CLI class

parent 6f4be7d4
......@@ -21,4 +21,7 @@ function statSync(dir: string): any {
module.exports = {
setMockDirectories,
statSync,
readFileSync: () => {
throw new Error("ENOENT");
},
};
import fs from "fs";
import HtmlValidate from "../htmlvalidate";
import { CLI } from "./cli";
jest.disableAutomock();
jest.mock("fs");
jest.mock("../htmlvalidate");
describe("CLI", () => {
beforeEach(() => {
(HtmlValidate as any).mockClear();
});
describe("getValidator()", () => {
it("should create new HtmlValidate instance", () => {
const cli = new CLI();
const htmlvalidate = cli.getValidator();
expect(HtmlValidate).toHaveBeenCalledWith({
extends: ["htmlvalidate:recommended"],
});
expect(htmlvalidate).toBeDefined();
});
it("should use configuration file", () => {
const readFileSync = jest
.spyOn(fs, "readFileSync")
.mockImplementation(() => '{"rules": {"foo": "error"}}');
const cli = new CLI({
configFile: "config.json",
});
const htmlvalidate = cli.getValidator();
expect(HtmlValidate).toHaveBeenCalledWith({
rules: {
foo: "error",
},
});
expect(htmlvalidate).toBeDefined();
expect(readFileSync).toHaveBeenCalledWith("config.json", "utf-8");
});
it("should configure single rule", () => {
const cli = new CLI({
rules: "foo:1",
});
const htmlvalidate = cli.getValidator();
expect(HtmlValidate).toHaveBeenCalledWith({
extends: [],
rules: {
foo: 1,
},
});
expect(htmlvalidate).toBeDefined();
});
it("should configure multiple rule", () => {
const cli = new CLI({
rules: ["foo:1", "bar:0"],
});
const htmlvalidate = cli.getValidator();
expect(HtmlValidate).toHaveBeenCalledWith({
extends: [],
rules: {
foo: 1,
bar: 0,
},
});
expect(htmlvalidate).toBeDefined();
});
});
});
import HtmlValidate from "htmlvalidate";
import { readFileSync } from "fs";
import { ConfigData } from "../config";
import defaultConfig from "../config/default";
import { UserError } from "../error";
import HtmlValidate from "../htmlvalidate";
import { Report } from "../reporter";
import { expandFiles, ExpandOptions } from "./expand-files";
import { getFormatter } from "./formatter";
export interface CLIOptions {
configFile?: string;
rules?: string | string[];
}
export class CLI {
private options: CLIOptions;
private config: ConfigData;
public constructor(options?: CLIOptions) {
this.options = options || {};
this.config = this.getConfig();
}
public expandFiles(
patterns: string[],
options: ExpandOptions = {}
......@@ -16,6 +33,34 @@ export class CLI {
}
public getValidator(): HtmlValidate {
return new HtmlValidate();
return new HtmlValidate(this.config);
}
private getConfig(): ConfigData {
const { options } = this;
const config: ConfigData = options.configFile
? JSON.parse(readFileSync(options.configFile, "utf-8"))
: defaultConfig;
let rules = options.rules;
if (rules) {
if (Array.isArray(rules)) {
rules = rules.join(",");
}
const raw = rules
.split(",")
.map((x: string) => x.replace(/ *(.*):/, '"$1":'))
.join(",");
try {
const rules = JSON.parse(`{${raw}}`);
config.extends = [];
config.rules = rules;
} catch (e) {
// istanbul ignore next
throw new UserError(
`Error while parsing --rule option "{${raw}}": ${e.message}.\n`
);
}
}
return config;
}
}
/* eslint-disable no-console, no-process-exit, sonarjs/no-duplicate-string */
import { ConfigData } from "../config";
import defaultConfig from "../config/default";
import { TokenDump } from "../engine";
import { UserError } from "../error/user-error";
import HtmlValidate from "../htmlvalidate";
import { Report, Reporter, Result } from "../reporter";
import { expandFiles } from "./expand-files";
import { getFormatter } from "./formatter";
import { eventFormatter } from "./json";
const pkg = require("../../package.json");
import chalk from "chalk";
import minimist from "minimist";
import { CLI } from "./cli";
enum Mode {
LINT,
......@@ -42,35 +38,6 @@ function getMode(argv: { [key: string]: any }): Mode {
return Mode.LINT;
}
function getGlobalConfig(
configFile: string,
rules?: string | string[]
): ConfigData {
const baseConfig: ConfigData = configFile
? require(`${process.cwd()}/${configFile}`)
: defaultConfig;
const config: any = Object.assign({}, baseConfig);
if (rules) {
if (Array.isArray(rules)) {
rules = rules.join(",");
}
const raw = rules
.split(",")
.map((x: string) => x.replace(/ *(.*):/, '"$1":'))
.join(",");
try {
const rules = JSON.parse(`{${raw}}`);
config.extends = [];
config.rules = rules;
} catch (e) {
process.stderr.write(
`Error while parsing "${rules}": ${e.message}, rules ignored.\n`
);
}
}
return config;
}
function lint(files: string[]): Report {
const reports = files.map((filename: string) => {
try {
......@@ -208,11 +175,14 @@ if (argv.help || argv._.length === 0) {
process.exit();
}
const cli = new CLI({
configFile: argv.config,
rules: argv.rule,
});
const mode = getMode(argv);
const config = getGlobalConfig(argv.config, argv.rule);
const formatter = getFormatter(argv.formatter);
const formatter = cli.getFormatter(argv.formatter);
const maxWarnings = parseInt(argv["max-warnings"] || "-1", 10);
const htmlvalidate = new HtmlValidate(config);
const htmlvalidate = cli.getValidator();
/* sanity check: ensure maxWarnings has a valid value */
if (isNaN(maxWarnings)) {
......@@ -227,7 +197,7 @@ const extensions = (argv.ext || "html").split(",").map((cur: string) => {
return cur[0] === "." ? cur.slice(1) : cur;
});
const files = expandFiles(argv._, { extensions });
const files = cli.expandFiles(argv._, { extensions });
if (files.length === 0) {
console.error("No files matching patterns", argv._);
process.exit(1);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment