relion 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/cli.js +64 -0
  2. package/dist/index.d.ts +231 -0
  3. package/dist/index.js +652 -0
  4. package/package.json +31 -50
  5. package/src/cli.js +0 -6
  6. package/src/commands.js +0 -176
  7. package/src/defaults.js +0 -60
  8. package/src/index.js +0 -75
  9. package/src/lib/checkpoint.js +0 -23
  10. package/src/lib/configuration.js +0 -35
  11. package/src/lib/detect-package-manager.js +0 -52
  12. package/src/lib/format-commit-message.js +0 -4
  13. package/src/lib/latest-semver-tag.js +0 -34
  14. package/src/lib/lifecycles/bump.js +0 -242
  15. package/src/lib/lifecycles/changelog.js +0 -106
  16. package/src/lib/lifecycles/commit.js +0 -67
  17. package/src/lib/lifecycles/tag.js +0 -61
  18. package/src/lib/print-error.js +0 -15
  19. package/src/lib/run-exec.js +0 -20
  20. package/src/lib/run-execFile.js +0 -20
  21. package/src/lib/run-lifecycle-script.js +0 -18
  22. package/src/lib/stringify-package.js +0 -34
  23. package/src/lib/updaters/index.js +0 -130
  24. package/src/lib/updaters/types/csproj.js +0 -13
  25. package/src/lib/updaters/types/gradle.js +0 -16
  26. package/src/lib/updaters/types/json.js +0 -25
  27. package/src/lib/updaters/types/maven.js +0 -43
  28. package/src/lib/updaters/types/openapi.js +0 -15
  29. package/src/lib/updaters/types/plain-text.js +0 -7
  30. package/src/lib/updaters/types/python.js +0 -30
  31. package/src/lib/updaters/types/yaml.js +0 -15
  32. package/src/lib/write-file.js +0 -6
  33. package/src/preset/constants.js +0 -16
  34. package/src/preset/index.js +0 -19
  35. package/src/preset/parser.js +0 -11
  36. package/src/preset/templates/commit.hbs +0 -19
  37. package/src/preset/templates/footer.hbs +0 -10
  38. package/src/preset/templates/header.hbs +0 -10
  39. package/src/preset/templates/index.js +0 -13
  40. package/src/preset/templates/main.hbs +0 -21
  41. package/src/preset/whatBump.js +0 -33
  42. package/src/preset/writer.js +0 -201
@@ -1,130 +0,0 @@
1
- import path from 'path'
2
- import defaults from '../../defaults.js'
3
- import * as jsonUpdater from './types/json.js'
4
- import * as plainTextUpdater from './types/plain-text.js'
5
- import * as mavenUpdater from './types/maven.js'
6
- import * as gradleUpdater from './types/gradle.js'
7
- import * as csprojUpdater from './types/csproj.js'
8
- import * as yamlUpdater from './types/yaml.js'
9
- import * as openapiUpdater from './types/openapi.js'
10
- import * as pythonUpdater from './types/python.js'
11
-
12
- const JSON_BUMP_FILES = defaults.bumpFiles
13
- const updatersByType = {
14
- 'json': jsonUpdater,
15
- 'plain-text': plainTextUpdater,
16
- 'maven': mavenUpdater,
17
- 'gradle': gradleUpdater,
18
- 'csproj': csprojUpdater,
19
- 'yaml': yamlUpdater,
20
- 'openapi': openapiUpdater,
21
- 'python': pythonUpdater,
22
- }
23
- const PLAIN_TEXT_BUMP_FILES = ['VERSION.txt', 'version.txt']
24
-
25
- function getUpdaterByType(type) {
26
- const updater = updatersByType[type]
27
- if (!updater) {
28
- throw Error(`Unable to locate updater for provided type (${type}).`)
29
- }
30
- return updater
31
- }
32
-
33
- function getUpdaterByFilename(filename) {
34
- if (JSON_BUMP_FILES.includes(path.basename(filename))) {
35
- return getUpdaterByType('json')
36
- }
37
- if (PLAIN_TEXT_BUMP_FILES.includes(filename)) {
38
- return getUpdaterByType('plain-text')
39
- }
40
- if (/pom.xml/.test(filename)) {
41
- return getUpdaterByType('maven')
42
- }
43
- if (/build.gradle/.test(filename)) {
44
- return getUpdaterByType('gradle')
45
- }
46
- if (filename.endsWith('.csproj')) {
47
- return getUpdaterByType('csproj')
48
- }
49
- if (/openapi.yaml/.test(filename)) {
50
- return getUpdaterByType('openapi')
51
- }
52
- if (/\.ya?ml$/.test(filename)) {
53
- return getUpdaterByType('yaml')
54
- }
55
- if (/pyproject.toml/.test(filename)) {
56
- return getUpdaterByType('python')
57
- }
58
- throw Error(
59
- `Unsupported file (${filename}) provided for bumping.\n Please specify the updater \`type\` or use a custom \`updater\`.`,
60
- )
61
- }
62
-
63
- async function getCustomUpdaterFromPath(updater) {
64
- if (typeof updater === 'string') {
65
- return (await import(path.resolve(process.cwd(), updater))).default
66
- }
67
- if (
68
- typeof updater.readVersion === 'function'
69
- && typeof updater.writeVersion === 'function'
70
- ) {
71
- return updater
72
- }
73
- throw new Error('Updater must be a string path or an object with readVersion and writeVersion methods')
74
- }
75
-
76
- /**
77
- * Simple check to determine if the object provided is a compatible updater.
78
- */
79
- function isValidUpdater(obj) {
80
- return (
81
- obj
82
- && typeof obj.readVersion === 'function'
83
- && typeof obj.writeVersion === 'function'
84
- )
85
- }
86
-
87
- export async function resolveUpdaterObjectFromArgument(arg) {
88
- /**
89
- * If an Object was not provided, we assume it's the path/filename
90
- * of the updater.
91
- */
92
- let updater = arg
93
- if (isValidUpdater(updater)) {
94
- return updater
95
- }
96
- if (typeof updater !== 'object') {
97
- updater = {
98
- filename: arg,
99
- }
100
- }
101
-
102
- if (!isValidUpdater(updater.updater)) {
103
- try {
104
- if (typeof updater.updater === 'string') {
105
- updater.updater = await getCustomUpdaterFromPath(updater.updater)
106
- }
107
- else if (updater.type) {
108
- updater.updater = getUpdaterByType(updater.type)
109
- }
110
- else {
111
- updater.updater = getUpdaterByFilename(updater.filename)
112
- }
113
- }
114
- catch (err) {
115
- if (err.code !== 'ENOENT')
116
- console.warn(
117
- `Unable to obtain updater for: ${JSON.stringify(arg)}\n - Error: ${err.message
118
- }\n - Skipping...`,
119
- )
120
- }
121
- }
122
- /**
123
- * We weren't able to resolve an updater for the argument.
124
- */
125
- if (!isValidUpdater(updater.updater)) {
126
- return false
127
- }
128
-
129
- return updater
130
- }
@@ -1,13 +0,0 @@
1
- const versionRegex = /<Version>(.*)<\/Version>/
2
-
3
- export function readVersion(contents) {
4
- const matches = versionRegex.exec(contents)
5
- if (matches === null || matches.length !== 2) {
6
- throw new Error('Failed to read the Version field in your csproj file - is it present?')
7
- }
8
- return matches[1]
9
- }
10
-
11
- export function writeVersion(contents, version) {
12
- return contents.replace(versionRegex, `<Version>${version}</Version>`)
13
- }
@@ -1,16 +0,0 @@
1
- const versionRegex = /^version\s+=\s+['"]([\d.]+)['"]/m
2
-
3
- export function readVersion(contents) {
4
- const matches = versionRegex.exec(contents)
5
- if (matches === null) {
6
- throw new Error('Failed to read the version field in your gradle file - is it present?')
7
- }
8
-
9
- return matches[1]
10
- }
11
-
12
- export function writeVersion(contents, version) {
13
- return contents.replace(versionRegex, () => {
14
- return `version = "${version}"`
15
- })
16
- }
@@ -1,25 +0,0 @@
1
- import stringifyPackage from '../../stringify-package.js'
2
- import detectIndent from 'detect-indent'
3
- import { detectNewline } from 'detect-newline'
4
-
5
- export function readVersion(contents) {
6
- return JSON.parse(contents).version
7
- }
8
-
9
- export function writeVersion(contents, version) {
10
- const json = JSON.parse(contents)
11
- const indent = detectIndent(contents).indent
12
- const newline = detectNewline(contents)
13
- json.version = version
14
-
15
- if (json.packages && json.packages['']) {
16
- // package-lock v2 stores version there too
17
- json.packages[''].version = version
18
- }
19
-
20
- return stringifyPackage(json, indent, newline)
21
- }
22
-
23
- export function isPrivate(contents) {
24
- return JSON.parse(contents).private
25
- }
@@ -1,43 +0,0 @@
1
- import jsdomPkg from 'jsdom'
2
- import serialize from 'w3c-xmlserializer'
3
- import { detectNewline } from 'detect-newline'
4
- const { JSDOM } = jsdomPkg
5
- const CRLF = '\r\n'
6
- const LF = '\n'
7
-
8
- function pomDocument(contents) {
9
- const dom = new JSDOM('')
10
- const parser = new dom.window.DOMParser()
11
- return parser.parseFromString(contents, 'application/xml')
12
- }
13
-
14
- function pomVersionElement(document) {
15
- const versionElement = document.querySelector('project > version')
16
-
17
- if (!versionElement) {
18
- throw new Error('Failed to read the version field in your pom file - is it present?')
19
- }
20
-
21
- return versionElement
22
- }
23
-
24
- export function readVersion(contents) {
25
- const document = pomDocument(contents)
26
- return pomVersionElement(document).textContent
27
- }
28
-
29
- export function writeVersion(contents, version) {
30
- const newline = detectNewline(contents)
31
- const document = pomDocument(contents)
32
- const versionElement = pomVersionElement(document)
33
-
34
- versionElement.textContent = version
35
-
36
- const xml = serialize(document)
37
-
38
- if (newline === CRLF) {
39
- return xml.replace(/\n/g, CRLF) + CRLF
40
- }
41
-
42
- return xml + LF
43
- }
@@ -1,15 +0,0 @@
1
- import yaml from 'yaml'
2
- import { detectNewline } from 'detect-newline'
3
-
4
- export function readVersion(contents) {
5
- return yaml.parse(contents).info.version
6
- }
7
-
8
- export function writeVersion(contents, version) {
9
- const newline = detectNewline(contents)
10
- const document = yaml.parseDocument(contents)
11
-
12
- document.get('info').set('version', version)
13
-
14
- return document.toString().replace(/\r?\n/g, newline)
15
- }
@@ -1,7 +0,0 @@
1
- export function readVersion(contents) {
2
- return contents
3
- }
4
-
5
- export function writeVersion(_contents, version) {
6
- return version
7
- }
@@ -1,30 +0,0 @@
1
- const versionExtractRegex = /version[" ]*=[ ]*["'](.*)["']/i
2
-
3
- const getVersionIndex = function (lines) {
4
- let version
5
- const lineNumber = lines.findIndex((line) => {
6
- const versionMatcher = line.match(versionExtractRegex)
7
- // if version not found in lines provided, return false
8
- if (versionMatcher == null) {
9
- return false
10
- }
11
- version = versionMatcher[1]
12
- return true
13
- })
14
- return { version, lineNumber }
15
- }
16
-
17
- export function readVersion(contents) {
18
- const lines = contents.split('\n')
19
- const versionIndex = getVersionIndex(lines)
20
- return versionIndex.version
21
- }
22
-
23
- export function writeVersion(contents, version) {
24
- const lines = contents.split('\n')
25
- const versionIndex = getVersionIndex(lines)
26
- const versionLine = lines[versionIndex.lineNumber]
27
- const newVersionLine = versionLine.replace(versionIndex.version, version)
28
- lines[versionIndex.lineNumber] = newVersionLine
29
- return lines.join('\n')
30
- }
@@ -1,15 +0,0 @@
1
- import yaml from 'yaml'
2
- import { detectNewline } from 'detect-newline'
3
-
4
- export function readVersion(contents) {
5
- return yaml.parse(contents).version
6
- }
7
-
8
- export function writeVersion(contents, version) {
9
- const newline = detectNewline(contents)
10
- const document = yaml.parseDocument(contents)
11
-
12
- document.set('version', version)
13
-
14
- return document.toString().replace(/\r?\n/g, newline)
15
- }
@@ -1,6 +0,0 @@
1
- import fs from 'fs'
2
-
3
- export default function (args, filePath, content) {
4
- if (args.dryRun) return
5
- fs.writeFileSync(filePath, content, 'utf8')
6
- }
@@ -1,16 +0,0 @@
1
- export const DEFAULT_COMMIT_TYPES = Object.freeze(
2
- [
3
- { type: 'feat', section: 'Features' },
4
- { type: 'feature', section: 'Features' },
5
- { type: 'fix', section: 'Bug Fixes' },
6
- { type: 'perf', section: 'Performance Improvements' },
7
- { type: 'revert', section: 'Reverts' },
8
- { type: 'docs', section: 'Documentation', hidden: true },
9
- { type: 'style', section: 'Styles', hidden: true },
10
- { type: 'chore', section: 'Miscellaneous Chores', hidden: true },
11
- { type: 'refactor', section: 'Code Refactoring', hidden: true },
12
- { type: 'test', section: 'Tests', hidden: true },
13
- { type: 'build', section: 'Build System', hidden: true },
14
- { type: 'ci', section: 'Continuous Integration', hidden: true },
15
- ].map(Object.freeze),
16
- )
@@ -1,19 +0,0 @@
1
- import { DEFAULT_COMMIT_TYPES } from './constants.js'
2
- import { createParserOpts } from './parser.js'
3
- import { createWriterOpts } from './writer.js'
4
- import { createWhatBump } from './whatBump.js'
5
-
6
- export { DEFAULT_COMMIT_TYPES }
7
- export * from './templates/index.js'
8
-
9
- export default async function createPreset(config) {
10
- return {
11
- commits: {
12
- ignore: config?.ignoreCommits,
13
- merges: false,
14
- },
15
- parser: createParserOpts(config),
16
- writer: await createWriterOpts(config),
17
- whatBump: createWhatBump(config),
18
- }
19
- }
@@ -1,11 +0,0 @@
1
- export function createParserOpts(config) {
2
- return {
3
- headerPattern: /^(\w*)(?:\((.*)\))?!?: (.*)$/,
4
- breakingHeaderPattern: /^(\w*)(?:\((.*)\))?!: (.*)$/,
5
- headerCorrespondence: ['type', 'scope', 'subject'],
6
- noteKeywords: ['BREAKING CHANGE', 'BREAKING-CHANGE'],
7
- revertPattern: /^(?:Revert|revert:)\s"?([\s\S]+?)"?\s*This reverts commit (\w*)\./i,
8
- revertCorrespondence: ['header', 'hash'],
9
- issuePrefixes: config?.issuePrefixes || ['#'],
10
- }
11
- }
@@ -1,19 +0,0 @@
1
- * {{#if scope}}`{{scope}}` {{/if~}}
2
- {{#if subject}}{{subject}}{{else}}{{header}}{{/if}}
3
-
4
- {{~! commit link}}
5
- {{~#if hash}}
6
- {{~#if @root.linkReferences}} ([{{shortHash}}]({{commitUrlFormat}}))
7
- {{~else}} {{shortHash}}{{~/if}}
8
- {{~/if}}
9
-
10
- {{~! commit references}}
11
- {{~#if references}} (
12
- {{~#each references}}
13
- {{#if @root.linkReferences~}}
14
- [{{~#if owner}}{{owner}}/{{/if}}{{repository}}{{prefix}}{{issue}}]({{issueUrlFormat}})
15
- {{~else}}
16
- {{~#if owner}}{{owner}}/{{/if}}{{repository}}{{prefix}}{{issue}}
17
- {{~/if}}{{~#unless @last}}, {{/unless}}{{~#if @last}}){{~/if}}
18
- {{~/each}}
19
- {{~/if}}
@@ -1,10 +0,0 @@
1
- {{#if fullChangelogLink~}}
2
- **Full Changelog:** {{#if previousTag~}}
3
- [`{{previousTag}}...{{currentTag}}`]({{compareUrlFormat}})
4
- {{~else~}}
5
- [`{{currentTag}}`]({{host}}/{{owner}}/{{repository}}/commits/{{currentTag}})
6
- {{~/if}}
7
-
8
-
9
- {{/if}}
10
-
@@ -1,10 +0,0 @@
1
- ## {{#if previousTag~}}
2
- [{{currentTag}}]({{compareUrlFormat}})
3
- {{~else~}}
4
- [{{currentTag}}]({{host}}/{{owner}}/{{repository}}/commits/{{currentTag}})
5
- {{~/if}}
6
- {{~#if title}} "{{title}}"
7
- {{~/if}}
8
- {{~#if date}} ({{date}})
9
- {{/if}}
10
-
@@ -1,13 +0,0 @@
1
- import fs from 'fs'
2
- import path from 'path'
3
-
4
- const dirpath = import.meta.dirname
5
-
6
- function read(name) {
7
- return fs.readFileSync(path.join(dirpath, `${name}.hbs`), 'utf-8')
8
- }
9
-
10
- export const main = read('main')
11
- export const header = read('header')
12
- export const commit = read('commit')
13
- export const footer = read('footer')
@@ -1,21 +0,0 @@
1
- {{> header}}
2
- {{#if noteGroups}}
3
- {{#each noteGroups}}
4
- ### ⚠ {{title}}
5
- {{#each notes}}
6
- * {{#if commit.scope}}`{{commit.scope}}` {{/if}}{{text}}
7
- {{/each}}
8
-
9
- {{/each}}
10
- {{/if}}
11
- {{#each commitGroups}}
12
- {{#if title}}
13
- ### {{title}}
14
- {{/if}}
15
- {{#each commits}}
16
- {{> commit}}
17
-
18
- {{/each}}
19
-
20
- {{/each}}
21
- {{> footer}}
@@ -1,33 +0,0 @@
1
- export function createWhatBump(config) {
2
- return function whatBump(commits) {
3
- let level = 2
4
- let breakings = 0
5
- let features = 0
6
-
7
- commits.forEach((commit) => {
8
- if (commit.notes.length > 0) {
9
- breakings += commit.notes.length
10
- level = 0
11
- }
12
- else if (commit.type === 'feat' || commit.type === 'feature') {
13
- features += 1
14
-
15
- if (level === 2) {
16
- level = 1
17
- }
18
- }
19
- })
20
-
21
- if (config?.preMajor && level < 2) {
22
- level++
23
- }
24
-
25
- return {
26
- level,
27
- reason:
28
- breakings === 1
29
- ? `There is ${breakings} BREAKING CHANGE and ${features} features`
30
- : `There are ${breakings} BREAKING CHANGES and ${features} features`,
31
- }
32
- }
33
- }
@@ -1,201 +0,0 @@
1
- import compareFunc from 'compare-func'
2
- import { DEFAULT_COMMIT_TYPES } from './constants.js'
3
- import { main, commit, header, footer } from './templates/index.js'
4
-
5
- const COMMIT_HASH_LENGTH = 7
6
- const releaseAsRegex = /release-as:\s*\w*@?([0-9]+\.[0-9]+\.[0-9a-z]+(-[0-9a-z.]+)?)\s*/i
7
- /**
8
- * Handlebar partials for various property substitutions based on commit context.
9
- */
10
- const owner = '{{#if this.owner}}{{~this.owner}}{{else}}{{~@root.owner}}{{/if}}'
11
- const host = '{{~@root.host}}'
12
- const repository = '{{#if this.repository}}{{~this.repository}}{{else}}{{~@root.repository}}{{/if}}'
13
-
14
- export async function createWriterOpts(config) {
15
- const finalConfig = {
16
- types: DEFAULT_COMMIT_TYPES,
17
- issueUrlFormat: '{{host}}/{{owner}}/{{repository}}/issues/{{id}}',
18
- commitUrlFormat: '{{host}}/{{owner}}/{{repository}}/commit/{{hash}}',
19
- compareUrlFormat: '{{host}}/{{owner}}/{{repository}}/compare/{{previousTag}}...{{currentTag}}',
20
- userUrlFormat: '{{host}}/{{user}}',
21
- issuePrefixes: ['#'],
22
- ...config,
23
- }
24
- const commitUrlFormat = expandTemplate(finalConfig.commitUrlFormat, {
25
- host,
26
- owner,
27
- repository,
28
- })
29
- const compareUrlFormat = expandTemplate(finalConfig.compareUrlFormat, {
30
- host,
31
- owner,
32
- repository,
33
- })
34
- const issueUrlFormat = expandTemplate(finalConfig.issueUrlFormat, {
35
- host,
36
- owner,
37
- repository,
38
- id: '{{this.issue}}',
39
- prefix: '{{this.prefix}}',
40
- })
41
- const writerOpts = getWriterOpts(finalConfig)
42
-
43
- writerOpts.mainTemplate = main
44
- writerOpts.headerPartial = header
45
- .replace(/{{compareUrlFormat}}/g, compareUrlFormat)
46
- writerOpts.commitPartial = commit
47
- .replace(/{{commitUrlFormat}}/g, commitUrlFormat)
48
- .replace(/{{issueUrlFormat}}/g, issueUrlFormat)
49
- writerOpts.footerPartial = footer
50
- .replace(/{{compareUrlFormat}}/g, compareUrlFormat)
51
-
52
- return writerOpts
53
- }
54
-
55
- function getWriterOpts(config) {
56
- const commitGroupOrder = config.types.flatMap(t => t.section).filter(t => t)
57
-
58
- return {
59
- finalizeContext: (context, _writerOpts, _filteredCommits, keyCommit) => {
60
- if (keyCommit) {
61
- const versionTagRegex = /tag:\s*([^,\s)]+)/i
62
- const keyCommitTag = keyCommit.gitTags?.match(versionTagRegex)
63
- if (keyCommitTag) {
64
- context.currentTag = keyCommitTag[1]
65
- const currentTagIndex = context.gitSemverTags.indexOf(context.currentTag)
66
- context.previousTag = (currentTagIndex === -1) ? null : context.gitSemverTags[currentTagIndex + 1]
67
- }
68
- }
69
- else {
70
- context.currentTag = context.newTag || null
71
- context.previousTag = context.gitSemverTags[0] || null
72
- }
73
- return context
74
- },
75
- transform: (commit, context) => {
76
- let discard = true
77
- const issues = []
78
- const entry = findTypeEntry(config.types, commit)
79
-
80
- // Add an entry in the CHANGELOG if special Release-As footer
81
- // is used:
82
- if ((commit.footer && releaseAsRegex.test(commit.footer))
83
- || (commit.body && releaseAsRegex.test(commit.body))) {
84
- discard = false
85
- }
86
-
87
- const notes = commit.notes.map((note) => {
88
- discard = false
89
-
90
- return {
91
- ...note,
92
- title: 'BREAKING CHANGES',
93
- }
94
- })
95
-
96
- // breaking changes attached to any type are still displayed.
97
- if (discard && (entry === undefined
98
- || entry.hidden)) {
99
- return undefined
100
- }
101
-
102
- const type = entry
103
- ? entry.section
104
- : commit.type
105
- const scope = commit.scope === '*'
106
- ? ''
107
- : commit.scope
108
- const shortHash = typeof commit.hash === 'string'
109
- ? commit.hash.substring(0, COMMIT_HASH_LENGTH)
110
- : commit.shortHash
111
- let { subject } = commit
112
-
113
- if (typeof subject === 'string') {
114
- // Issue URLs.
115
- const issueRegEx = `(${config.issuePrefixes.join('|')})([a-z0-9]+)`
116
- const re = new RegExp(issueRegEx, 'g')
117
-
118
- subject = subject.replace(re, (_, prefix, issue) => {
119
- issues.push(prefix + issue)
120
-
121
- const url = expandTemplate(config.issueUrlFormat, {
122
- host: context.host,
123
- owner: context.owner,
124
- repository: context.repository,
125
- id: issue,
126
- prefix,
127
- })
128
-
129
- return `[${prefix}${issue}](${url})`
130
- })
131
- // User URLs.
132
- subject = subject.replace(/\B@([a-z0-9](?:-?[a-z0-9/]){0,38})/g, (_, user) => {
133
- // TODO: investigate why this code exists.
134
- if (user.includes('/')) {
135
- return `@${user}`
136
- }
137
-
138
- const usernameUrl = expandTemplate(config.userUrlFormat, {
139
- host: context.host,
140
- owner: context.owner,
141
- repository: context.repository,
142
- user,
143
- })
144
-
145
- return `[@${user}](${usernameUrl})`
146
- })
147
- }
148
-
149
- // remove references that already appear in the subject
150
- const references = commit.references.filter(reference => !issues.includes(reference.prefix + reference.issue))
151
-
152
- return {
153
- notes,
154
- type,
155
- scope,
156
- shortHash,
157
- subject,
158
- references,
159
- }
160
- },
161
- groupBy: 'type',
162
- // the groupings of commit messages, e.g., Features vs., Bug Fixes, are
163
- // sorted based on their probable importance:
164
- commitGroupsSort: (a, b) => {
165
- const gRankA = commitGroupOrder.indexOf(a.title)
166
- const gRankB = commitGroupOrder.indexOf(b.title)
167
-
168
- return gRankA - gRankB
169
- },
170
- commitsSort: ['scope', 'subject'],
171
- noteGroupsSort: 'title',
172
- notesSort: compareFunc,
173
- }
174
- }
175
-
176
- function findTypeEntry(types, commit) {
177
- const typeKey = (commit.revert ? 'revert' : commit.type || '').toLowerCase()
178
-
179
- return types.find((entry) => {
180
- if (entry.type !== typeKey) {
181
- return false
182
- }
183
-
184
- if (entry.scope && entry.scope !== commit.scope) {
185
- return false
186
- }
187
-
188
- return true
189
- })
190
- }
191
-
192
- // expand on the simple mustache-style templates supported in
193
- // configuration (we may eventually want to use handlebars for this).
194
- function expandTemplate(template, context) {
195
- let expanded = template
196
-
197
- Object.keys(context).forEach((key) => {
198
- expanded = expanded.replace(new RegExp(`{{${key}}}`, 'g'), context[key])
199
- })
200
- return expanded
201
- }