Skip to content

Commit

Permalink
Merge e01e235 into 52f96ee
Browse files Browse the repository at this point in the history
  • Loading branch information
KamiKillertO committed Jul 30, 2020
2 parents 52f96ee + e01e235 commit 4e9d71f
Show file tree
Hide file tree
Showing 10 changed files with 197 additions and 152 deletions.
123 changes: 26 additions & 97 deletions lib/cli/index.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
/* eslint-disable no-console */
const fs = require("fs");
const path = require("path");
const globby = require("globby");
const chalk = require("chalk");
const ora = require("ora");
const meow = require("meow");
const ignore = require("ignore");

const linthtml = require("../index");
const { config_from_path, find_local_config } = require("./read-config");
const printErrors = require("./print-errors");
const presets = require("../presets").presets;
const checkInvalidCLIOptions = require("../utils/checkInvalidCliOptions");
const print_file_report = require("../print_file_report");
const init_command = require("./commands/init");
Expand All @@ -20,10 +14,7 @@ const EXIT_CODE_ERROR = 1;
const EXIT_CODE_NORMAL = 0;

const pkg = require("../../package.json");

const excludedFolders = [
"!node_modules/"
];
const printErrors = require("./print-errors");

const cliOptions = {
help: chalk`
Expand Down Expand Up @@ -74,7 +65,7 @@ module.exports = (argv) => {
cliOptions.argv = argv;
const cli = meow(cliOptions);
const invalidOptionsMessage = checkInvalidCLIOptions(cliOptions.flags, cli.flags);
let config = null;
const config = null;
if (invalidOptionsMessage) {
process.stderr.write(invalidOptionsMessage);
return exitProcess();
Expand All @@ -89,33 +80,18 @@ module.exports = (argv) => {
if (cli.flags.config === "") {
console.log(chalk`A file path must be provided when using the {blue.bold config} option.`);
process.exit(EXIT_CODE_ERROR); // eslint-disable-line no-process-exit
} else {
try {
config = config_from_path(cli.flags.config);
} catch (error) {
printErrors(error);
return exitProcess(true);
}
}
}

if (config === null) {
config = find_local_config();
}
if (config === null) {
config = presets.default;
}

config = config.config ? config.config : config;

// use config_path if provided or search local config file
if (cli.flags.printConfig) {
process.stdout.write(JSON.stringify(config, null, " "));
}

if (cli.flags.help || cli.flags.h || argv.length === 0) {
cli.showHelp();
}
return lint(cli.input, config);
return lint(cli.input, cli.flags.config);
};

function exitProcess(is_errored = false) {
Expand All @@ -124,29 +100,22 @@ function exitProcess(is_errored = false) {
return process.exit(exit_code);
}

async function checkLinterConfig(config) {
const configSpinner = ora("Checking rules config").start();
async function lint(input, config_path) {
let files_linters = [];
const searchSpinner = ora("Searching for files").start();
try {
await linthtml.fromConfig(config);
configSpinner.succeed();
files_linters = linthtml.create_linters_for_files(input, config_path);
searchSpinner.succeed(`Found ${files_linters.length} files`); // deal with 0
} catch (error) {
configSpinner.fail();
console.log();
console.error(chalk`{red ${error.message}}`);
return exitProcess(true);
searchSpinner.fail();
printErrors(error);
exitProcess(true);
}
}

async function lint(input, config) {
await checkLinterConfig(config);

const searchSpinner = ora("Searching for files").start();
const lintSpinner = ora("Analysing files").start();
let files = await getFilesToLint(input, config);
searchSpinner.succeed(`Found ${files.length} files`);
files = files.map(getFileContent);
const lintSpinner = ora("Analysing files");
try {
let reports = await Promise.all(files.map(file => lintFile(file, config)));
lintSpinner.start();
let reports = await Promise.all(files_linters.map(lintFile));
reports = reports.filter(report => report.issues.length > 0);
lintSpinner.succeed();
printReports(reports);
Expand All @@ -155,6 +124,7 @@ async function lint(input, config) {
console.log();
console.log(chalk`An error occured while analysing {underline ${error.fileName}}`);
console.log();
printErrors(error);
console.log(chalk`{red ${error.message}}`);
return exitProcess(true);
}
Expand Down Expand Up @@ -182,59 +152,18 @@ function printReports(reports) {
return exitProcess();
}

function getFilesFromGlob(globPattern, ignorePaths) {
const customIgnore = ignorePaths === undefined;
return globby(globPattern, {
gitignore: customIgnore,
ignore: customIgnore ? excludedFolders : [],
expandDirectories: {
files: ["**/*.html"],
extensions: ["html"]
}
});
}

function getFilesToLint(input, config) {
const ignoreConfig = readLintIgnoreFile();
let { ignoreFiles } = config;
if (ignoreConfig) {
ignoreFiles = ignoreConfig;
}
return Promise.all(input.map(pattern => getFilesFromGlob(pattern, ignoreFiles)))
.then(flatten)
.then(filesPath => filterIgnoredFiles(filesPath, ignoreFiles));
}

function readLintIgnoreFile() {
const ignore_file_path = path.join(process.cwd(), ".linthtmlignore");
if (fs.existsSync(ignore_file_path)) {
return fs.readFileSync(ignore_file_path).toString();
}
}

function filterIgnoredFiles(filesPath, customIgnore) {
if (customIgnore === undefined) {
return filesPath;
}
const ignorer = ignore().add(customIgnore);
return ignorer.filter(filesPath);
}

function getFileContent(name) {
return {
name,
content: fs.readFileSync(name, "utf8")
};
}

async function lintFile(file, config) {
async function lintFile({ file_path, linter, config_path, preset }) {
try {
const linter = await linthtml.fromConfig(config); // await needed by legacy linter

const issues = await linter.lint(file.content, config); // config needed by legacy linter
return { fileName: file.name, issues };
const file_content = fs.readFileSync(file_path, "utf8");
const issues = await linter.lint(file_content);
return {
fileName: file_path,
issues,
config_path,
preset
};
} catch (error) {
error.fileName = file.name;
error.fileName = file_path;
throw error;
}
}
Expand Down
10 changes: 6 additions & 4 deletions lib/cli/print-errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ const chalk = require("chalk");
const errors = require("../messages");

module.exports = function(error) {
const [type, code] = error.code.split("-");

const error_message = errors[`${type}_ERRORS`][code];
console.log(error_message(chalk, error.meta));
if (error.code) {
const [type, code] = error.code.split("-");
const error_message = errors[`${type}_ERRORS`][code];
return console.log(error_message(chalk, error.meta));
}
return console.log(chalk`{red ${error.message}}`);
};
100 changes: 92 additions & 8 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
const { config_from_path, find_local_config } = require("./read-config");
const Linter = require("./linter");
const LegacyLinter = require("./legacy/linter");
const presets = require("./presets").presets;

const path = require("path");
const fs = require("fs");
const globby = require("globby");
const ignore = require("ignore");
const { flatten } = require("./utils/arrays");

const DEFAULT_EXCLUDED_FOLDERS = [
"!node_modules/"
];

/**
* The linthtml namespace.
Expand All @@ -10,20 +22,15 @@ const linthtml = function(html, config) {
const linter = new Linter(config);
return linter.lint(html);
}
const linter = new LegacyLinter(...arguments);
return linter.lint.apply(linter, arguments);
const linter = new LegacyLinter(null, config);
return linter.lint(html);
};

module.exports = linthtml;

linthtml.fromConfig = function(config) {
if (config && config.rules !== undefined) {
return new Linter(config);
}
const linter = new LegacyLinter();
/* eslint-disable-next-line */
linter.lint.call(linter, "", config);
return linter;
return new LegacyLinter(null, config);
};

linthtml.Linter = Linter;
Expand All @@ -40,3 +47,80 @@ linthtml.messages = require("./messages");
// linthtml.use(plugin);
// });
// };

function get_files_to_lint(input, config = {}) {
const ignoreConfig = read_dot_ignore_file();
let { ignoreFiles } = config;
if (ignoreConfig) {
ignoreFiles = ignoreConfig;
}
const file_paths = input.map(pattern => get_files_from_glob(pattern, ignoreFiles));
return filter_ignored_files(flatten(file_paths), ignoreFiles);
}

function get_files_from_glob(glob_pattern, ignore_config) {
const use_default_ignore = ignore_config === undefined;
return globby.sync(glob_pattern, {
gitignore: use_default_ignore,
ignore: use_default_ignore ? DEFAULT_EXCLUDED_FOLDERS : [],
expandDirectories: {
files: ["**/*.html"],
extensions: ["html"]
}
});
}

function filter_ignored_files(file_paths, ignore_pattern) {
if (ignore_pattern === undefined) {
return file_paths;
}

const ignorer = ignore().add(ignore_pattern);
return ignorer.filter(file_paths);
}

function read_dot_ignore_file() {
const ignore_file_path = path.join(process.cwd(), ".linthtmlignore");
if (fs.existsSync(ignore_file_path)) {
return fs.readFileSync(ignore_file_path).toString();
}
}

function should_ignore_file(file_path, ignore_pattern) {
const ignorer = ignore().add(ignore_pattern);
return ignorer.ignores(file_path);
}

function create_file_linter(file_path, config) {
return {
file_path,
preset: config.preset,
config_path: config.filepath,
linter: linthtml.fromConfig(config.config)
};
}

linthtml.create_linters_for_files = function(globs, config_path) {
if (config_path) {
const config = config_from_path(config_path);
const files = get_files_to_lint(globs, config.config);
return files.map(file_path => create_file_linter(file_path, config));
}
const files = get_files_to_lint(globs);
return files.reduce((files_to_lint, file_path) => {
let config = find_local_config(file_path);
if (!config) {
config = {
config: presets.default,
preset: "default"
};
}
// if no config fallback to presets as before
if (!should_ignore_file(file_path, config.ignoreFiles)) {
return files_to_lint.concat(create_file_linter(file_path, config));
}
return files_to_lint;
}, []);
};

module.exports = linthtml;
24 changes: 9 additions & 15 deletions lib/legacy/linter.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
const parse = require("../parser");
const presets = require("../presets");
const Config = require("./config");
const InlineConfig = require("./inline_config");
const { flatten } = require("../utils/arrays");
Expand All @@ -19,21 +18,16 @@ function rawIgnoreRegex(html, opts) {
});
}

function getOptions(args) {
let optList = Array.prototype.slice.call(args, 1);
optList = flatten(optList);

if (optList[optList.length - 1] !== "nodefault") {
optList.unshift("default");
}

return presets.flattenOpts(optList);
}

class Linter {
constructor() {
this.config = getOptions(arguments);
this.rules = new Config(rules);
constructor(_rules) {
// this.config = config;
this.config = Array.prototype.slice.call(arguments, 1)
.reduce((obj, cell) => ({
...obj,
...cell
}), {});
_rules = _rules || rules;
this.rules = new Config(_rules);
this.inlineConfig = null;
}

Expand Down
16 changes: 0 additions & 16 deletions lib/presets/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ const presetsValidate = require("./validate");
const presets = {};

const none = (() => {
// let keys = Object.keys(presets.default);
const keys = Object.keys(presetsDefault);
const obj = {};
keys.forEach(key => {
Expand All @@ -18,18 +17,3 @@ presets.accessibility = presetsA11y;
presets.validate = presetsValidate;
presets.default = presetsDefault;
module.exports.presets = presets;

module.exports.flattenOpts = function(optList) {
let options = {};
optList.forEach(function(opt) {
if (typeof opt === "string") {
opt = presets[opt];
}
options = {
...options,
...opt
};
});

return options;
};
Loading

0 comments on commit 4e9d71f

Please sign in to comment.