import type { ParserPreset, UserConfig } from '@commitlint/types';
import config from '@commitlint/config-conventional';
import createPreset from 'conventional-changelog-conventionalcommits';
import { merge } from 'lodash-es';
// Build emoji regex dynamically from your type enum
async function createEmojiParser(): Promise<ParserPreset> {
const emojiRegexPart = Object.values(config.prompt.questions.type.enum)
.map((value) => (value as any).emoji.trim())
.join('|');
const parserOpts = {
headerPattern: new RegExp(
`^(?:${emojiRegexPart})\\s+(\\w*)(?:\\((.*)\\))?!?:\\s+(.*)$`
),
breakingHeaderPattern: new RegExp(
`^(?:${emojiRegexPart})\\s+(\\w*)(?:\\((.*)\\))?!:\\s+(.*)$`
),
headerCorrespondence: ['type', 'scope', 'subject'],
};
const emojiParser = merge({}, await createPreset(), {
conventionalChangelog: { parserOpts },
parserOpts,
recommendedBumpOpts: { parserOpts },
});
return emojiParser;
}
const emojiParser = await createEmojiParser();
const config: UserConfig = {
extends: ['@commitlint/config-conventional'],
parserPreset: emojiParser,
rules: {
'type-enum': [
2,
'always',
['feat', 'fix', 'refactor', 'build', 'perf', 'test', 'docs', 'chore', 'revert'],
],
},
prompt: {
questions: {
type: {
enum: {
feat: { emoji: '✨', description: 'User-facing new feature' },
fix: { emoji: '🩹', description: 'Bug fix' },
refactor: { emoji: '♻️', description: 'Internal improvement, no behavior change' },
build: { emoji: '👷', description: 'Build system & pipelines' },
perf: { emoji: '⚡️', description: 'Performance optimization' },
test: { emoji: '✅', description: 'Add or fix test cases' },
docs: { emoji: '📝', description: 'Documentation update' },
chore: { emoji: '🔨', description: 'Maintenance, deps, config, formatting' },
revert: { emoji: '⏪', description: 'Revert a previous commit' },
},
headerWithEmoji: true, // includes emoji in the final commit header
},
},
},
};
export default config;