UNPKG

2.83 kBJavaScriptView Raw
1const _ = require('lodash');
2const wrap = require('word-wrap');
3
4const defaultSubjectSeparator = ': ';
5const defaultMaxLineWidth = 100;
6const defaultBreaklineChar = '|';
7
8const addTicketNumber = (ticketNumber, config) => {
9 if (!ticketNumber) {
10 return '';
11 }
12
13 if (config.ticketNumberPrefix) {
14 return `${config.ticketNumberPrefix + ticketNumber.trim()} `;
15 }
16
17 return `${ticketNumber.trim()} `;
18};
19
20const addScope = (scope, config) => {
21 const separator = _.get(config, 'subjectSeparator', defaultSubjectSeparator);
22
23 if (!scope) return separator; // it could be type === WIP. So there is no scope
24
25 return `(${scope.trim()})${separator}`;
26};
27
28const addSubject = subject => _.trim(subject);
29
30const addType = (type, config) => {
31 const prefix = _.get(config, 'typePrefix', '');
32 const suffix = _.get(config, 'typeSuffix', '');
33
34 return _.trim(`${prefix}${type}${suffix}`);
35};
36
37const addBreaklinesIfNeeded = (value, breaklineChar = defaultBreaklineChar) =>
38 value
39 .split(breaklineChar)
40 .join('\n')
41 .valueOf();
42
43const addFooter = (footer, config) => {
44 if (config && config.footerPrefix === '') return `\n\n${footer}`;
45
46 const footerPrefix = config && config.footerPrefix ? config.footerPrefix : 'ISSUES CLOSED:';
47
48 return `\n\n${footerPrefix} ${addBreaklinesIfNeeded(footer, config.breaklineChar)}`;
49};
50
51const escapeSpecialChars = result => {
52 // eslint-disable-next-line no-useless-escape
53 const specialChars = ['`'];
54
55 let newResult = result;
56 // eslint-disable-next-line array-callback-return
57 specialChars.map(item => {
58 // If user types "feat: `string`", the commit preview should show "feat: `\string\`".
59 // Don't worry. The git log will be "feat: `string`"
60 newResult = result.replace(new RegExp(item, 'g'), '\\`');
61 });
62 return newResult;
63};
64
65module.exports = (answers, config) => {
66 const wrapOptions = {
67 trim: true,
68 newline: '\n',
69 indent: '',
70 width: defaultMaxLineWidth,
71 };
72
73 // Hard limit this line
74 // eslint-disable-next-line max-len
75 const head =
76 addType(answers.type, config) +
77 addScope(answers.scope, config) +
78 addTicketNumber(answers.ticketNumber, config) +
79 addSubject(answers.subject.slice(0, config.subjectLimit));
80
81 // Wrap these lines at 100 characters
82 let body = wrap(answers.body, wrapOptions) || '';
83 body = addBreaklinesIfNeeded(body, config.breaklineChar);
84
85 const breaking = wrap(answers.breaking, wrapOptions);
86 const footer = wrap(answers.footer, wrapOptions);
87
88 let result = head;
89 if (body) {
90 result += `\n\n${body}`;
91 }
92 if (breaking) {
93 const breakingPrefix = config && config.breakingPrefix ? config.breakingPrefix : 'BREAKING CHANGE:';
94 result += `\n\n${breakingPrefix}\n${breaking}`;
95 }
96 if (footer) {
97 result += addFooter(footer, config);
98 }
99
100 return escapeSpecialChars(result);
101};