remark-common-changelog
v2.3.1
Published
Lint or fix a changelog written in markdown, following Common Changelog.
Downloads
1,053
Maintainers
Readme
remark-common-changelog
Lint or fix a changelog written in markdown, following Common Changelog
. Changelogs should be written by humans, for humans. This tool focuses on helping you do that.
Usage
This package is ESM-only.
import changelog from 'remark-common-changelog'
import vfile from 'to-vfile'
import { remark } from 'remark'
remark()
.use(changelog)
.process(vfile.readSync('CHANGELOG.md'), function (err, file) {
if (err) throw err
console.log(String(file))
})
Pair with remark-github
for ultimate pleasure. If you're looking for a CLI that includes both, checkout hallmark
, a markdown style guide with linter and automatic fixer.
Rules
title
Changelog must start with a top-level "Changelog" heading. In fix
mode, it is either added or updated.
release-heading-depth
Release must start with second-level heading.
release-heading
Release heading must have the format <version> - <date>
.
release-version
Release must have a semver-valid version, without v
prefix. Releases that have no matching git tag are not rejected, to support adding a git tag after updating the changelog.
release-version-link
Release version must have a link. The destination URL is not linted. In fix
mode links are automatically inserted (to https://github.com/OWNER/REPO/releases/tag/$tag
) requiring a nearby package.json
with a repository
field. The link is optional for the oldest (last listed) release.
release-version-link-reference
Use a link reference for version link.
Valid:
## [1.0.0] - 2019-08-23
[1.0.0]: https://github.com/vweevers/remark-common-changelog/releases/tag/v1.0.0
Invalid:
## [1.0.0](https://github.com/vweevers/remark-common-changelog/releases/tag/v1.0.0) - 2019-08-23
release-date
Release must have a date with format YYYY-MM-DD
.
latest-release-first
Releases must be sorted latest-first according to semver rules. In fix
mode, releases are reordered.
latest-definition-first
Definitions must be sorted latest-first, same as releases. Any additional definitions (that don't describe a release) must be last. In fix
mode, definitions are reordered.
Valid:
[2.0.0]: https://github.com/vweevers/remark-common-changelog/releases/tag/v2.0.0
[1.0.0]: https://github.com/vweevers/remark-common-changelog/releases/tag/v1.0.0
Invalid:
[1.0.0]: https://github.com/vweevers/remark-common-changelog/releases/tag/v1.0.0
[2.0.0]: https://github.com/vweevers/remark-common-changelog/releases/tag/v2.0.0
unique-release
Each release must have a unique version.
no-empty-release
A release must have content.
In fix mode, an empty release is filled with a commit log as a leg up. Merge commits are skipped. GitHub merge commits ("Merge pull request #n") are used to annotate commits with a PR number (best effort). Squashed GitHub commits that have a default commit description (a list of squashed commits) are converted to sublists.
Valid:
## [2.0.0] - 2019-09-02
foo
## [1.0.0] - 2019-09-01
bar
Invalid:
## [2.0.0] - 2019-09-02
## [1.0.0] - 2019-09-01
group-heading
A "group" (of changes) must start with a third-level, text-only heading.
group-heading-type
A group heading must be one of Changed, Added, Deprecated, Removed, Fixed, Security.
no-empty-group
A group must not be empty. Invalid:
### Added
### Fixed
no-uncategorized-changes
There should not be a group with heading Uncategorized. This group is added by remark-common-changelog
if the fix
option is true and it populates an empty release with commits. This rule then hints that changes should be categorized.
filename
Filename must be CHANGELOG.md
.
To support using remark-common-changelog
in a pipeline that runs on other files too, remark-common-changelog
ignores files other than CHANGELOG.md
but it does reject alternative extensions and the alternative names HISTORY
and RELEASES
.
API
changelog([options])
Options:
fix
(boolean): attempt to fix issuescwd
(string): working directory, defaults tocwd
of file orprocess.cwd()
pkg
(object): a parsedpackage.json
, defaults to reading a nearbypackage.json
(starting incwd
and then its parent directories)repository
(string or object): defaults torepository
field ofpkg
. Used to construct diff URLs.version
(string): defaults toversion
field ofpkg
or the last tag. Used to identify a new release (anything that's greater thanversion
and would normally be rejected in fix mode because it has no git tag yet) to support the workflow of updating a changelog before tagging.add
(string): add a new release (only iffix
is true) and populate it with commits. Value must be one of:- A release type:
major
,minor
,patch
,premajor
,preminor
,prepatch
,prerelease
- These take the current version from the semver-latest tag, release or
package.json
(whichever is greatest if found) and bump it - The
major
type bumps the major version (for example2.4.1 => 3.0.0
);minor
andpatch
work the same way. - The
premajor
type bumps the version up to the next major version and down to a prerelease of that major version;preminor
andprepatch
work the same way. - The
prerelease
type works the same asprepatch
if the current version is a non-prerelease. If the current is already a prerelease then it's simply incremented (for example4.0.0-rc.2
to4.0.0-rc.3
).
- These take the current version from the semver-latest tag, release or
- A semver-valid version like 2.4.0.
- A release type:
commits
(boolean, defaulttrue
, only relevant foradd
): iffalse
, don't populate the release with commits.submodules
(boolean, only relevant foradd
): enable experimental git submodule support. Will collect commits from submodules and list them in the changelog as<name>: <message>
.
Notes on add
If the (resulting) version is greater than the current version then commits will be taken from the semver-latest tag until HEAD. I.e. documenting a new release before it's git-tagged. If the version matches an existing tag then a release will be inserted at the appriopriate place, populated with commits between that version's tag and the one before it. I.e. documenting a past release after it's git-tagged. If the version equals 0.0.1
, 0.1.0
or 1.0.0
and zero versions exist, then a notice will be inserted (rather than commits) containing the text :seedling: Initial release.
.
Works best on a linear git history without merge commits. If remark-common-changelog
encounters other tags in the commit range it will stop there and not include further (older) commits.
Git trailers ("lines that look similar to RFC 822 e-mail headers, at the end of the otherwise free-form part of a commit message") can provide structured information to the generated changelog. The following trailer keys are supported (case-insensitive):
Category
: one ofchange
,addition
,removal
,fix
, ornone
. Ifnone
then the commit will be excluded from the changelog. If not present then the change will be listed under Uncategorized and will require manual categorization.Notice
: a notice for the release. If multiple commits contain a notice, they will be joined as sentences (i.e. ending with a dot) separated by a space.Ref
,Refs
,Fixes
,Closes
orCVE-ID
: a numeric reference in the form of#N
,PREFIX-N
orCVE-N-N
whereN
is a number andPREFIX
is at least 2 letters. For example#123
,GH-123
,JIRA-123
orCVE-2024-123
. Can be repeated, either with multiple trailer lines or by separating references with a comma - e.g.Ref: #1, #2
. Non-numeric references are ignored.Co-Authored-By
: co-author in the form ofname <email>
. Can be repeated.
For example, the following commit (which has Bob as git author, let's say):
Bump math-utils to 4.5.6
Ref: JIRA-123
Category: change
Co-Authored-By: Alice <[email protected]>
Turns into:
## Changed
- Bump math-utils to 4.5.6 (d23ba8f) (JIRA-123) (Bob, Alice)
Install
With npm do:
npm install remark-common-changelog