# Changelog Tools

This package provides changelog-oriented tools for use in CLI, Node and browser scripts.

Features:
- Parse CHANGELOG.md files compatible with https://keepachangelog.com/en/1.1.0/ into JSON structure
- Filter output based on semver range, or custom filter conditions
- Combine multiple versions into a single structure, grouped by type of change (Added, Fixed etc.)
- Compatible with both browser and node environments
- Add new entries into changelog with CLI

The parsing algorithm was initially based on [the changelog-parser package](https://www.npmjs.com/package/changelog-parser), but it was updated to provide a more object-oriented approach.

## CLI API

### `parse`
```
changelog-tools parse path-to-changelog.md
```

Parses the changelog and returns it in JSON format

#### Parameters

| Param                                      | Alias | Default | Description                                                                                                                                                    |
| ------------------------------------------ | ----- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--help`                                   | `-h`  |         |                                                                                                                                                                |
| `--version`                                | `-v`  |         |                                                                                                                                                                |
| `--new-line`                               | `-n`  | `AUTO`  | `AUTO\|LF\|CRLF\|CR` - Define what should be newline character for output data. `AUTO` will try to detect the line endings from the document.                  |
| `--consolidate` / `--no-consolidate`       | `-c`  | `false` | Merge multiple versions into one entry, groupiung the same ypes of changes together                                                                            |
| `--strip-markdown` / `--no-strip-markdown` |       | `true`  | Decide if markdown syntax should be cleaned from the output                                                                                                    |
| `--semver`                                 | `-s`  | `''`    | filter versions by semver range syntax. E.g.  `-s '>=1.0.0'`                                                                                                   |
| `--filter`                                 | `-f`  |         | Filter entries based on provided statement. Use `this` to access version data. Statement needs to return a `boolean`. Example: `-f 'this.version === "1.0.0"'` |
| `--error` / `--no-error`                   | `-e`  | `false` | Exit with non-zero code if filtering or parsing returned no version entries                                                                                    |
| `--format`                                 |       | `json`  | `json\|markdown` - output format for results                                                                                                                   |

#### Examples


##### Parse changelog and output a JSON structure representing the document.

```bash
changelog-tools CHANGELOG.md
```

##### Find all versions in the changelog between `1.0.0` and `1.1.0` and group `Added`, `Fixed` etc entries together.
 
```bash
changelog-tools -cs '~1.0.0' CHANGELOG.md
```


### `add` 

```
changelog-tools add path-to-changelog.md -t 'Title of new version' [-o output file]
```

Adds a new version to the changelog.

#### Parameters

| Param             | Alias | Default | Description                                                                                                                                                                                                                       |
| ----------------- | ----- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--help`          | `-h`  |         |                                                                                                                                                                                                                                   |
| `--version`       | `-v`  |         |                                                                                                                                                                                                                                   |
| `--new-line`      | `-n`  | `AUTO`  | `AUTO\|LF\|CRLF\|CR` - Define what should be newline character for output data. `AUTO` will try to detect the line endings from the document.                                                                                     |
| `--title`         | `-t`  |         | (Required) Title of the version to add (e.g. `-t '1.0.0 (2020-01-01) - My Version Title'`. Title can include semver increase level (e.g. `-t ':patch'` or `-t 'v:patch'`) - in this case last known version will be bumped by 1.) |
| `--added`         | `-a`  |         | `### Added` entries (e.g. `-a 'new feature' -a 'new feature 2'`)                                                                                                                                                                  |
| `--changed`       | `-c`  |         | `### Changed` entries (e.g. `-c 'format 1' -c 'api description'`)                                                                                                                                                                 |
| `--deprecated`    | `-d`  |         | `### Deprecated` entries (e.g. `-d 'old feature' -d 'old feature 2'`).                                                                                                                                                            |
| `--removed`       | `-r`  |         | `### Removed` entries (e.g. `-r 'old feature' -r 'old feature 2'`)                                                                                                                                                                |
| `--fixed`         | `-f`  |         | `### Fixed` entries (e.g. `-f 'bug 1' -f 'bug 2'`)                                                                                                                                                                                |
| `--new-changelog` |       |         | Raw changelog text (including `###` section headers) to be parsed and merged with other sections (e.g. `--new-changelog "### Added\n* Something new"`)                                                                            |
| `--list-bullet`   | `-l`  |         | Character to be used for list items (e.g. `-l '*'`)                                                                                                                                                                               |
| `--output`        | `-o`  | stdout  | Output file                                                                                                                                                                                                                       |

#### Examples


##### Add a new version with a single 'Added' entry

```bash
changelog-tools add CHANGELOG.md -t 'v1.5.0 - 2022-01-01' -a 'New command `add`'
```
output on CLI:
```markdown
# Changelog Tools

## v1.5.0 - 2022-01-01
### Added
- New command `add`

<!-- ... previous versions -->
```

##### Auto bump minor version

```bash
changelog-tools add CHANGELOG.md -t 'v:minor - 2022-01-01' -a 'New command `add`'
```
output on CLI:
```markdown
# Changelog Tools

## v1.6.0 - 2022-01-01
### Added
- New command `add`

<!-- ... previous versions -->
```

##### Add a new version with a single 'Added' entry and save it to the same file as input

```bash
changelog-tools add CHANGELOG.md -t 'v1.5.0 - 2022-01-01' -a 'New command `add`' -o CHANGELOG.md
```

## JavaScript (Node and browser)

### Loading parser class

CommonJS: 
```javascript
const { ChangelogParser } = require("changelog-tools");
```

ES Modules:

```javascript
import { ChangelogParser } from "changelog-tools";
```

### Creating parser

```javascript
// Empty parser:
const changelogParser = new ChangelogParser();

// Parser with preloaded changelog text:
const changelogParser = new ChangelogParser({
  text: changelogContent
});
```

### Parsing

```javascript
// If text was already preloaded
const changelog = changelogParser.parse();

// With new changelog content:
const changelog = changelogParser.parse(changelogContent);
```

`.parse()` method will return an instance of the `Changelog` class.

An example structure of this object can be seen below:

```json
{
  "title": "Changelog title",
  "description": "This is a sample changelog",
  "versions": [
    {
      "version": "1.1.0",
      "line": 4,
      "date": "2022-12-20",
      "title": "v1.1.0 - 2022-12-20",
      "parsed": {
        "_": ["Removed 1", "Changed 2"],
        "Removed": ["Removed 1"],
        "Changed": ["Changed 2"]
      },
      "body": "### Removed \n\n- Removed 1\n\n### Changed\n\n-Changed 2"
    },
    {
      "version": "1.0.0",
      "line": 12,
      "date": "2022-12-12",
      "title": "v1.0.0 - 2022-12-12",
      "parsed": {
        "_": ["Added 1", "Changed 1"],
        "Added": ["Added 1"],
        "Changed": ["Changed 1"]
      },
      "body": "### Added \n\n- Added 1\n\n### Changed\n\n-Changed 1"
    }
  ]
}
```

### Filtering results

```javascript
const filteredChangelog = changelog.filter((v) => v.version === '1.0.0' || v.title.includes('Unversioned'))
```

`.filter()` method will also return an instance of the `Changelog` class.

### Consolidate versions from the changelog

```javascript
const changeSummary = changelog.consolidate();
```

This is best used to summarize all changes from multiple versions. E.g. the script below will gather all changes from versions 1.1.X.

```javascript
const changeSummary = changelog.filter((v) => v.version.startsWith('1.1')).consolidate();
```

The result will be provided as an object like below:

```json
{
  "Added": [
    {
      "text": "Added 2",
      "version": "0.0.3"
    },
    {
      "text": "Added 1",
      "version": "0.0.1"
    }
  ],
  "Removed": [
    {
      "text": "Removed 1",
      "version": "0.0.2"
    }
  ]
}
```

## Examples

See the [`./examples`](./examples/) folder to check for examples of use cases.