UNPKG

gplint

Version:

A Gherkin linter/validator written in Javascript.

106 lines 4 kB
import fs from 'node:fs'; import path from 'node:path'; import { pathToFileURL, fileURLToPath } from 'node:url'; import * as glob from 'glob'; import _ from 'lodash'; import { RuleErrors } from './errors.js'; import { readAndParseFile } from './linter.js'; const LEVELS = [ 'off', 'warn', 'error', ]; export async function getAllRules(additionalRulesDirs) { if ((additionalRulesDirs?.length ?? 0) > 0) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore if (process[Symbol.for('ts-node.register.instance')] == null) { // Check if ts-node was registered previously await loadRegister(); } } const rules = {}; const cwd = path.dirname(fileURLToPath(import.meta.url)); const rulesDirs = [ path.join(cwd, 'rules') ].concat(additionalRulesDirs ?? []); for (let rulesDir of rulesDirs) { rulesDir = path.resolve(rulesDir); const rulesWildcard = path.join(rulesDir, '*.?(c|m)@(j|t)s'); // .js, .cjs, .mjs (and TS equivalents) for (const file of glob.sync(rulesWildcard, { windowsPathsNoEscape: true, ignore: '**/*.d.?(c|m)ts' })) { const rule = await import(pathToFileURL(file).toString()); rules[rule.name] = rule; } } return rules; } export async function getRule(rule, additionalRulesDirs) { return (await getAllRules(additionalRulesDirs))[rule]; } export async function doesRuleExist(rule, additionalRulesDirs) { return (await getRule(rule, additionalRulesDirs)) !== undefined; } export function getRuleLevel(ruleConfig, rule) { const level = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig; if (level == null) { return 0; } let levelNum = _.isNumber(level) ? level : _.toNumber(level); if (isNaN(levelNum)) { levelNum = LEVELS.indexOf(level); } if (levelNum < 0 || levelNum > 2) { throw new Error(`Unknown level ${level} for ${rule}.`); } return levelNum; } export async function runAllEnabledRules(gherkinData, configuration = {}, additionalRulesDirs, autoFix = false) { let errors = []; const rules = await getAllRules(additionalRulesDirs); for (const ruleName of Object.keys(rules)) { const rule = rules[ruleName]; const ruleLevel = getRuleLevel(configuration[rule.name], rule.name); if (ruleLevel > 0) { const ruleConfig = (Array.isArray(configuration[rule.name]) ? configuration[rule.name][1] : {}); const error = rule.run(gherkinData, ruleConfig); if (error.length > 0) { if (autoFix && rule.fix) { error.forEach(e => { rule.fix(e, gherkinData.file, ruleConfig); }); fs.writeFileSync(gherkinData.file.relativePath, gherkinData.file.lines.join(gherkinData.file.EOL)); const regeneratedGherkinData = await readAndParseFile(gherkinData.file.relativePath); gherkinData.feature = regeneratedGherkinData.feature; gherkinData.pickles = regeneratedGherkinData.pickles; gherkinData.file = regeneratedGherkinData.file; } else { errors = errors.concat(error.map(e => ({ level: ruleLevel, ...(rule.buildRuleErrors ? rule.buildRuleErrors(e) : e) }))); } } } } return new RuleErrors(errors); } async function loadRegister() { try { const { register } = await import('ts-node'); register({ compilerOptions: { allowJs: true } }); /* c8 ignore next 3 */ } catch (err) { // eslint-disable-line @typescript-eslint/no-unused-vars /* empty */ } } //# sourceMappingURL=rules.js.map