UNPKG

4.56 kBJavaScriptView Raw
1import util from 'util';
2import isIgnored from '@commitlint/is-ignored';
3import parse from '@commitlint/parse';
4import defaultRules from '@commitlint/rules';
5import { RuleConfigSeverity } from '@commitlint/types';
6import { buildCommitMessage } from './commit-message.js';
7export default async function lint(message, rawRulesConfig, rawOpts) {
8 const opts = rawOpts
9 ? rawOpts
10 : { defaultIgnores: undefined, ignores: undefined };
11 const rulesConfig = rawRulesConfig || {};
12 // Found a wildcard match, skip
13 if (isIgnored(message, { defaults: opts.defaultIgnores, ignores: opts.ignores })) {
14 return {
15 valid: true,
16 errors: [],
17 warnings: [],
18 input: message,
19 };
20 }
21 // Parse the commit message
22 const parsed = message === ''
23 ? { header: null, body: null, footer: null }
24 : await parse(message, undefined, opts.parserOpts);
25 if (parsed.header === null &&
26 parsed.body === null &&
27 parsed.footer === null) {
28 // Commit is empty, skip
29 return {
30 valid: true,
31 errors: [],
32 warnings: [],
33 input: message,
34 };
35 }
36 const allRules = new Map(Object.entries(defaultRules));
37 if (opts.plugins) {
38 Object.values(opts.plugins).forEach((plugin) => {
39 if (plugin.rules) {
40 Object.keys(plugin.rules).forEach((ruleKey) => allRules.set(ruleKey, plugin.rules[ruleKey]));
41 }
42 });
43 }
44 // Find invalid rules configs
45 const missing = Object.keys(rulesConfig).filter((name) => typeof allRules.get(name) !== 'function');
46 if (missing.length > 0) {
47 const names = [...allRules.keys()];
48 throw new RangeError(`Found invalid rule names: ${missing.join(', ')}. Supported rule names are: ${names.join(', ')}`);
49 }
50 const invalid = Object.entries(rulesConfig)
51 .map(([name, config]) => {
52 if (!Array.isArray(config)) {
53 return new Error(`config for rule ${name} must be array, received ${util.inspect(config)} of type ${typeof config}`);
54 }
55 const [level] = config;
56 if (level === RuleConfigSeverity.Disabled && config.length === 1) {
57 return null;
58 }
59 const [, when] = config;
60 if (typeof level !== 'number' || isNaN(level)) {
61 return new Error(`level for rule ${name} must be number, received ${util.inspect(level)} of type ${typeof level}`);
62 }
63 if (config.length < 2 || config.length > 3) {
64 return new Error(`config for rule ${name} must be 2 or 3 items long, received ${util.inspect(config)} of length ${config.length}`);
65 }
66 if (level < 0 || level > 2) {
67 return new RangeError(`level for rule ${name} must be between 0 and 2, received ${util.inspect(level)}`);
68 }
69 if (typeof when !== 'string') {
70 return new Error(`condition for rule ${name} must be string, received ${util.inspect(when)} of type ${typeof when}`);
71 }
72 if (when !== 'never' && when !== 'always') {
73 return new Error(`condition for rule ${name} must be "always" or "never", received ${util.inspect(when)}`);
74 }
75 return null;
76 })
77 .filter((item) => item instanceof Error);
78 if (invalid.length > 0) {
79 throw new Error(invalid.map((i) => i.message).join('\n'));
80 }
81 // Validate against all rules
82 const pendingResults = Object.entries(rulesConfig)
83 // Level 0 rules are ignored
84 .filter(([, config]) => !!config && config.length && config[0] > 0)
85 .map(async (entry) => {
86 const [name, config] = entry;
87 const [level, when, value] = config; //
88 const rule = allRules.get(name);
89 if (!rule) {
90 throw new Error(`Could not find rule implementation for ${name}`);
91 }
92 const executableRule = rule;
93 const [valid, message] = await executableRule(parsed, when, value);
94 return {
95 level,
96 valid,
97 name,
98 message,
99 };
100 });
101 const results = (await Promise.all(pendingResults)).filter((result) => result !== null);
102 const errors = results.filter((result) => result.level === 2 && !result.valid);
103 const warnings = results.filter((result) => result.level === 1 && !result.valid);
104 const valid = errors.length === 0;
105 return {
106 valid,
107 errors,
108 warnings,
109 input: buildCommitMessage(parsed),
110 };
111}
112//# sourceMappingURL=lint.js.map
\No newline at end of file