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