Repository: release-drafter/release-drafter
Pull request #767 (2021-01-27 12:45:04)

Category templating
I wanted to avoid the hard-coded category title markdown, i.e. change it from `## Features` to `### Features` to be a bit more subtle.

jetersen: Please rebase and run `yarn install` to get the latest `@vercel/ncc` than rerun `yarn build` to avoid the many thousand of changes inside `dist/index.js`
rofafor: Thanks. I had some odd issues for generating the file on my MAC: all kind of CRLF issues no matter which `core.autocrlf`setting I was using. Looks better now.

Patch:
diff --git a/.prettierrc b/.prettierrc
index 0beac85..c345cc8 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -1,4 +1,6 @@
 {
+  "trailingComma": "es5",
+  "arrowParens": "always",
   "semi": false,
   "singleQuote": true,
   "bracketSpacing": true
diff --git a/README.md b/README.md
index 07d9015..4e785ab 100644
--- a/README.md
+++ b/README.md
@@ -96,6 +96,7 @@ You can configure Release Drafter using the following key in your `.github/relea
 | Key                    | Required | Description                                                                                                                                                                |
 | ---------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
 | `template`             | Required | The template for the body of the draft release. Use [template variables](#template-variables) to insert values.                                                            |
+| `category-template`    | Optional | The template to use for each category. Use [category template variables](#category-template-variables) to insert values. Default: `"## $TITLE"`.                           |
 | `name-template`        | Optional | The template for the name of the draft release. For example: `"v$NEXT_PATCH_VERSION"`.                                                                                     |
 | `tag-template`         | Optional | The template for the tag of the draft release. For example: `"v$NEXT_PATCH_VERSION"`.                                                                                      |
 | `version-template`     | Optional | The template to use when calculating the next version number for the release. Useful for projects that don't use semantic versioning. Default: `"$MAJOR.$MINOR.$PATCH"`    |
@@ -125,6 +126,14 @@ You can use any of the following variables in your `template`:
 | `$CONTRIBUTORS` | A comma separated list of contributors to this release (pull request authors, commit authors, and commit committers). |
 | `$PREVIOUS_TAG` | The previous releases’s tag.                                                                                          |
 
+## Category Template Variables
+
+You can use any of the following variables in `category-template`:
+
+| Variable | Description                          |
+| -------- | ------------------------------------ |
+| `$TITLE` | The category title, e.g. `Features`. |
+
 ## Next Version Variables
 
 You can use any of the following variables in your `template`, `name-template` and `tag-template`:
diff --git a/dist/index.js b/dist/index.js
index 39d22c9..979b743 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -402,6 +402,7 @@ const DEFAULT_CONFIG = Object.freeze({
   'sort-direction': SORT_DIRECTIONS.descending,
   prerelease: false,
   'filter-by-commitish': false,
+  'category-template': `## $TITLE`,
 })
 
 module.exports.DEFAULT_CONFIG = DEFAULT_CONFIG
@@ -699,7 +700,10 @@ const generateChangeLog = (mergedPullRequests, config) => {
 
   categorizedPullRequests.map((category, index) => {
     if (category.pullRequests.length) {
-      changeLog.push(`## ${category.title}\n\n`)
+      changeLog.push(
+        template(config['category-template'], { $TITLE: category.title })
+      )
+      changeLog.push('\n\n')
 
       changeLog.push(pullRequestToString(category.pullRequests))
 
@@ -952,6 +956,10 @@ const schema = (context) => {
         })
         .default(DEFAULT_CONFIG['version-resolver']),
 
+      'category-template': Joi.string()
+        .allow('')
+        .default(DEFAULT_CONFIG['category-template']),
+
       template: Joi.string().required(),
 
       _extends: Joi.string(),
diff --git a/lib/default-config.js b/lib/default-config.js
index 8fd6c9a..ce925ae 100644
--- a/lib/default-config.js
+++ b/lib/default-config.js
@@ -21,6 +21,7 @@ const DEFAULT_CONFIG = Object.freeze({
   'sort-direction': SORT_DIRECTIONS.descending,
   prerelease: false,
   'filter-by-commitish': false,
+  'category-template': `## $TITLE`,
 })
 
 module.exports.DEFAULT_CONFIG = DEFAULT_CONFIG
diff --git a/lib/releases.js b/lib/releases.js
index b868bcb..7bb83a4 100644
--- a/lib/releases.js
+++ b/lib/releases.js
@@ -199,7 +199,10 @@ const generateChangeLog = (mergedPullRequests, config) => {
 
   categorizedPullRequests.map((category, index) => {
     if (category.pullRequests.length) {
-      changeLog.push(`## ${category.title}\n\n`)
+      changeLog.push(
+        template(config['category-template'], { $TITLE: category.title })
+      )
+      changeLog.push('\n\n')
 
       changeLog.push(pullRequestToString(category.pullRequests))
 
diff --git a/lib/schema.js b/lib/schema.js
index d9c55e7..25475bf 100644
--- a/lib/schema.js
+++ b/lib/schema.js
@@ -105,6 +105,10 @@ const schema = (context) => {
         })
         .default(DEFAULT_CONFIG['version-resolver']),
 
+      'category-template': Joi.string()
+        .allow('')
+        .default(DEFAULT_CONFIG['category-template']),
+
       template: Joi.string().required(),
 
       _extends: Joi.string(),
diff --git a/schema.json b/schema.json
index 77ccd4c..b4ef89f 100644
--- a/schema.json
+++ b/schema.json
@@ -205,6 +205,18 @@
       "additionalProperties": false,
       "patterns": []
     },
+    "category-template": {
+      "anyOf": [
+        {
+          "type": "string",
+          "enum": [""]
+        },
+        {
+          "default": "## $TITLE",
+          "type": "string"
+        }
+      ]
+    },
     "template": {
       "type": "string"
     },


Test patch:
diff --git a/test/schema.test.js b/test/schema.test.js
index 64cc347..f308d89 100644
--- a/test/schema.test.js
+++ b/test/schema.test.js
@@ -26,6 +26,8 @@ const invalidConfigs = [
   [{ template: { '👶': 'a' } }, 'must be a string'],
   [{ template: null }, 'must be a string'],
   [{ template: '' }, 'is not allowed to be empty'],
+  [{ 'category-template': ['## $TITLE'] }, 'must be a string'],
+  [{ 'category-template': null }, 'must be a string'],
   [{ 'change-template': ['* $TITLE (#$NUMBER) @$AUTHOR'] }, 'must be a string'],
   [{ 'change-template': null }, 'must be a string'],
   [{ 'change-title-escapes': ['<_*'] }, 'must be a string'],