Skip to content

Commit

Permalink
feat: 🔥 support bodyFormat
Browse files Browse the repository at this point in the history
added new "bodyFormat" configuration option that accepts string or
function, and added function option to "headerFormat"
  • Loading branch information
tal-rofe committed Apr 19, 2023
1 parent 9a94b4f commit 5a134a0
Show file tree
Hide file tree
Showing 26 changed files with 359 additions and 584 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ module.exports = {
},
},
{
files: ['./scripts/onboarding.js'],
files: ['./scripts/onboarding.js', './src/services/logger.service.ts'],
rules: {
'no-console': 'off',
},
Expand Down
43 changes: 22 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,27 +143,28 @@ The default commit types, descriptions and emoji that are used are:
]
```
| Environment variable | Key | Type | default | Description |
| :------------------------- | :-------------------- | :--------- | :------------------------------------------------------------ | :------------------------------------------------------------------------- |
| `CZ_HEADER_FORMAT` | `headerFormat` | `string` | `{type}: {emoji} [{ticket_id}] {subject}` | How the commit header will be formatted. Support: `type`, `scope`, `emoji`, `ticket_id`, `subject`
| `CZ_COMMIT_TYPES` | `commitTypes` | `{ value: string; description: string; emoji?: string }[]` | Above | The commit types to work with. Only `value` and `description` are required |
| `CZ_MAX_COMMIT_LINE_WIDTH` | `maxCommitLineWidth` | `number` | `72` | Wraps the commit body message with max line width |
| `CZ_TYPE_QUESTION` | `typeQuestion` | `string` | `Select the type of changes you're commiting:\n` | The CLI question for type |
| `CZ_SCOPE_QUESTION` | `scopeQuestion` | `string` | `Specify a scope:` | The CLI question for scope |
| `CZ_SKIP_SCOPE` | `skipScope` | `boolean` | `true` | Whether to prompt the user to a scope question |
| `CZ_SCOPES` | `scopes` | `string[]` | `[]` | Available scopes (empty array allows free text) |
| `CZ_TICKET_ID_QUESTION` | `ticketIdQuestion` | `string` | `Type the JIRA Id (ex. V-12345):` | The CLI question for ticket ID |
| `CZ_SKIP_TICKET_ID` | `skipTicketId` | `boolean` | `false` | Whether to prompt the user to a ticket ID question |
| `CZ_TICKET_ID_REGEX` | `ticketIdRegex` | `string` | `((?<!([A-Z]{1,10})-?)[A-Z]+-\d+)` | A string represents a valid RegEx to extract ticket ID from the branch |
| `CZ_ALLOW_EMPTY_TICKET_ID_FOR_BRANCHES` | `allowEmptyTicketIdForBranches` | `string[]` | `[]` | List of branches to exclude validation for ticket ID |
| `CZ_SUBJECT_QUESTION` | `subjectQuestion` | `string` | `Write a short, imperative mood description of the change:\n` | The CLI question for subject |
| `CZ_SUBJECT_MAX_LENGTH` | `subjectMaxLength` | `number` | `70` | Max length of the subject text |
| `CZ_SUBJECT_MIN_LENGTH` | `subjectMinLength` | `number` | `3` | Min length of the subject text |
| `CZ_BODY_QUESTION` | `bodyQuestion` | `string` | `Provide a longer description of the change:\n` | The CLI question for body |
| `CZ_SKIP_BODY` | `skipBody` | `boolean` | `false` | Whether to prompt the user to a body question |
| `SKIP_BREAKING_CHANGES` | `skipBreakingChanges` | `boolean` | `true` | Whether to prompt the user to a breaking change question |
| `CZ_ISSUES_QUESTION` | `issuesQuestion` | `string` | `List any issue closed (#1, #2, ...):` | The CLI question for issues |
| `CZ_SKIP_ISSUES` | `skipIssues` | `boolean` | `true` | Whether to prompt the user to a issues question |
| **Environment variable** | **Key** | **Type** | **Default** | **Description** |
|---------------------------------------|---------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------|---------------------------------------------------------------------------------------------------------|
| CZ_HEADER_FORMAT | `headerFormat` | `string` \| `(commitType: string, scope: string \| undefined, emoji: string \| undefined, ticketId: string \| undefined, subject: string) => string` | `{type}: {emoji} [{ticket_id}] {subject}` | How the commit header will be formatted. Supported placeholders: type, scope, emoji, ticket_id, subject |
| CZ_BODY_FORMAT | `bodyFormat` | `string` \| `(commitType: string, scope: string \| undefined, ticketId: string \| undefined, body: string \| undefined) => string` | `{body}` | How the commit body will be formatted. Supported placeholders: type, scope, ticket_id, body |
| | `commitTypes` | `{ value: string; description: string, emoji?: string }[]` | See above | The commit types to work with. |
| CZ_MAX_COMMIT_LINE_WIDTH | `maxCommitLineWidth` | `number` | `72` | Wraps the commit body message with max line width |
| CZ_TYPE_QUESTION | `typeQuestion` | `string` | `Select the type of changes you're committing:\n` | The CLI question for type |
| CZ_SCOPE_QUESTION | `scopeQuestion` | `string` | `Specify a scope:` | The CLI question for scope |
| CZ_SKIP_SCOPE | `skipScope` | `boolean` | `true` | Whether to prompt the user to a scope question |
| | `scopes` | `string[]` | `[]` | Available scopes (empty array allows free text) |
| CZ_TICKET_ID_QUESTION | `ticketIdQuestion` | `string` | `Type the JIRA Id (ex. V-12345):` | The CLI question for ticket ID |
| CZ_SKIP_TICKET_ID | `skipTicketId` | `boolean` | `false` | Whether to prompt the user to a ticket ID question |
| CZ_TICKET_ID_REGEX | `ticketIdRegex` | `string` | `((?<!([A-Z]{1,10})-?)[A-Z]+-\d+)` | A string represents a valid RegEx to extract ticket ID from the branch |
| CZ_ALLOW_EMPTY_TICKET_ID_FOR_BRANCHES | `allowEmptyTicketIdForBranches` | `string[]` | `[]` | List of branches to exclude validation for ticket ID |
| CZ_SUBJECT_QUESTION | `subjectQuestion` | `string` | `Write a short, imperative mood description of the change:\n` | The CLI question for subject |
| CZ_SUBJECT_MAX_LENGTH | `subjectMaxLength` | `number` | `70` | Max length of the subject text |
| CZ_SUBJECT_MIN_LENGTH | `subjectMinLength` | `number` | `3` | Min length of the subject text |
| CZ_BODY_QUESTION | `bodyQuestion` | `string` | `Provide a longer description of the change:\n` | The CLI question for body |
| CZ_SKIP_BODY | `skipBody` | `boolean` | `false` | Whether to prompt the user to a body question |
| CZ_SKIP_BREAKING_CHANGES | `skipBreakingChanges` | `boolean` | `true` | Whether to prompt the user to a breaking change question |
| CZ_ISSUES_QUESTION | `issuesQuestion` | `string` | `List any issue closed (#1, #2, ...):` | The CLI question for issues |
| CZ_SKIP_ISSUES | `skipIssues` | `boolean` | `true` | Whether to prompt the user to a issues question |
## Examples
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@
"inquirer-autocomplete-prompt": "2.0.0",
"inquirer-maxlength-input-prompt": "1.0.2",
"string-template": "1.0.0",
"word-wrap": "1.2.3"
"word-wrap": "1.2.3",
"zod": "3.21.4"
},
"devDependencies": {
"@commitlint/cli": "17.6.1",
Expand Down
4 changes: 3 additions & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/constants/commit-type.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { ICommitType } from '../interfaces/configuration';
import type { FinalConfiguration } from '../types/final-configuration';

export const DEFAULT_COMMIT_TYPES: ICommitType[] = [
export const DEFAULT_COMMIT_TYPES: FinalConfiguration['commitTypes'] = [
{
description: 'Build process or auxiliary tool changes',
emoji: '🤖',
Expand Down
7 changes: 4 additions & 3 deletions src/constants/configuration.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import type { IConfiguration } from '../interfaces/configuration';
import type { FinalConfiguration } from '../types/final-configuration';
import { DEFAULT_COMMIT_TYPES } from './commit-type';
import { TICKET_ID_REGEX } from './ticket-id';

export const DEFAULT_CONFIGURATION: IConfiguration = {
export const DEFAULT_CONFIGURATION: FinalConfiguration = {
headerFormat: '{type}: {emoji} [{ticket_id}] {subject}',
bodyFormat: '{body}',
commitTypes: DEFAULT_COMMIT_TYPES,
maxCommitLineWidth: 72,
typeQuestion: "Select the type of changes you're commiting:\n",
typeQuestion: "Select the type of changes you're committing:\n",
scopeQuestion: 'Specify a scope:',
skipScope: true,
scopes: [],
Expand Down
40 changes: 27 additions & 13 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import InquirerMaxLength from 'inquirer-maxlength-input-prompt';
import wrap from 'word-wrap';

import { getConfiguration } from './utils/configuration';
import { formatHeader, formatIssues, formatBreakingChange } from './pipes/commit-format';
import { formatHeader, formatIssues, formatBreakingChange, formatBody } from './pipes/commit-format';
import { getQuestions } from './utils/questions';
import type { ICommitFunc } from './interfaces/commit';
import type { PromptAnswers } from './interfaces/prompt-answers';

const prompter = async (cz: Inquirer, commit: ICommitFunc) => {
cz.prompt.registerPrompt('autocomplete', InquirerAutoComplete);
Expand All @@ -21,21 +22,34 @@ const prompter = async (cz: Inquirer, commit: ICommitFunc) => {
};

const questions = await getQuestions(configuration);
const answers = await cz.prompt(questions);
const answers = await cz.prompt<PromptAnswers>(questions);

const answersForHeader = [
answers.type.type,
answers.scope,
answers.type.emoji,
answers.ticket_id,
answers.subject,
] as const;

const header =
typeof configuration.headerFormat === 'function'
? configuration.headerFormat.call(null, ...answersForHeader)
: formatHeader(configuration.headerFormat, ...answersForHeader);

const answersForBody = [answers.type.type, answers.scope, answers.ticket_id, answers.body] as const;

const body =
typeof configuration.bodyFormat === 'function'
? configuration.bodyFormat.call(null, ...answersForBody)
: formatBody(configuration.bodyFormat, ...answersForBody);

commit(
[
formatHeader(
configuration.headerFormat,
answers.type.type,
answers.scope,
answers.type.emoji,
answers.ticket_id,
answers.subject,
),
wrap(answers.body || '', wrapOptions),
wrap(formatBreakingChange(answers.breakingBody) || '', wrapOptions),
formatIssues(answers.issues),
header,
body.length > 0 ? wrap(body, wrapOptions) : false,
answers.breakingBody ? wrap(formatBreakingChange(answers.breakingBody), wrapOptions) : false,
answers.issues ? formatIssues(answers.issues) : false,
]
.filter(Boolean)
.join('\n\n')
Expand Down
27 changes: 0 additions & 27 deletions src/interfaces/configuration.ts

This file was deleted.

12 changes: 12 additions & 0 deletions src/interfaces/prompt-answers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export interface PromptAnswers {
readonly type: Readonly<{
type: string;
emoji?: string;
}>;
readonly scope?: string;
readonly ticket_id?: string;
readonly subject: string;
readonly body?: string;
readonly breakingBody?: string;
readonly issues?: string;
}
1 change: 0 additions & 1 deletion src/interfaces/unknown-record.ts

This file was deleted.

Loading

0 comments on commit 5a134a0

Please sign in to comment.