Lint or fix a changelog written in markdown, following Keep A Changelog
. Changelogs should be written by humans, for humans. This tool focuses on helping you do that.
const changelog = require('remark-changelog')
const vfile = require('to-vfile')
const remark = require('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.
Changelog must start with a top-level "Changelog" heading. In fix
mode, it is either added or updated.
Release must start with second-level heading.
Release heading must be Unreleased
or have the format <version> - <date>
.
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 must have a link. The destination URL is not linted. In fix
mode links are automatically inserted (to https://github.com/OWNER/REPO/compare/A...B
or https://github.com/OWNER/REPO/releases/tag/$tag
for the oldest release) requiring a nearby package.json
with a repository
field. The link is optional for the oldest (last listed) release.
Use a link reference for version link.
Valid:
## [1.0.0] - 2019-08-23
[1.0.0]: https://github.com/vweevers/remark-changelog/compare/v0.0.1...v1.0.0
Invalid:
## [1.0.0](https://github.com/vweevers/remark-changelog/compare/v0.0.1...v1.0.0) - 2019-08-23
Release must have a date with format YYYY-MM-DD
.
Releases must be sorted latest-first according to semver rules. If there is an Unreleased section, it must be the very first. In fix
mode, releases are reordered.
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-changelog/compare/v1.0.0...v2.0.0
[1.0.0]: https://github.com/vweevers/remark-changelog/compare/v0.0.1...v1.0.0
Invalid:
[1.0.0]: https://github.com/vweevers/remark-changelog/compare/v0.0.1...v1.0.0
[2.0.0]: https://github.com/vweevers/remark-changelog/compare/v1.0.0...v2.0.0
Each release must have a unique version.
A release section must have content. This also goes for the Unreleased section.
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
A "group" (of changes) must start with a third-level, text-only heading.
A group heading must be one of Changed, Added, Deprecated, Removed, Fixed, Security.
A group must not be empty. Invalid:
### Added
### Fixed
There should not be a group with heading Uncategorized. This group is added by remark-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 must be CHANGELOG.md
.
To support using remark-changelog
in a pipeline that runs on other files too, remark-changelog
ignores files other than CHANGELOG.md
but it does reject alternative extensions and the alternative names HISTORY
and RELEASES
.
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.submodules
(boolean): enable experimental git submodule support. Will collect commits from submodules and list them in the changelog as<name>: <message>
.add
(string): add a new changelog entry (only iffix
is true). Value must be one of:- A release type:
major
,minor
,patch
,premajor
,preminor
,prepatch
,prerelease
(relative to last entry in changelog)- 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 previous version is a non-prerelease. If the previous is already a prerelease then it's simply incremented (for example4.0.0-rc.2 => 4.0.0-rc.3
).
- The
- A specific version like 2.4.0 (must be semver). This can also be used to insert a missing version (that is not necessarily the latest).
- A release type:
Because we might deviate from Keep A Changelog
, which is too loose to lint and has a broad target audience and thus technical scope. Conversely, remark-changelog
only works on npm packages with a GitHub repository, to start.
With npm do:
npm install remark-changelog
MIT © 2019-present Vincent Weevers