news-fragments 4.3.0 → 4.4.3

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.
package/CHANGELOG.md CHANGED
@@ -1,4 +1,45 @@
1
1
 
2
+ [//]: # (s-4.4.3)
3
+
4
+ # [4.4.3] - (2026-06-24)
5
+
6
+ ## Misc
7
+ * Update dependencies.
8
+
9
+ [//]: # (e-4.4.3)
10
+
11
+
12
+ [//]: # (s-4.4.2)
13
+
14
+ # [4.4.2] - (2026-06-24)
15
+
16
+ [//]: # (e-4.4.2)
17
+
18
+
19
+ [//]: # (s-4.4.1)
20
+
21
+ # [4.4.1] - (2026-06-24)
22
+
23
+ ## Misc
24
+ * Fix node package.
25
+
26
+ [//]: # (e-4.4.1)
27
+
28
+
29
+ [//]: # (s-4.4.0)
30
+
31
+ # [4.4.0] - (2026-06-24)
32
+
33
+ ## Features
34
+ * Replace dependency marked with markdown-it.
35
+
36
+ ## Documentation
37
+ * Updates documentation.
38
+
39
+
40
+ [//]: # (e-4.4.0)
41
+
42
+
2
43
  [//]: # (s-4.3.0)
3
44
 
4
45
  # [4.3.0] - (2026-04-27)
package/README.md CHANGED
@@ -2,24 +2,111 @@
2
2
  <img src="./changelog.png" alt="Logo" title="Logo" />
3
3
  </p>
4
4
 
5
- News fragments is a plugin for [release-it](https://github.com/release-it/release-it) that helps you to generate a changelog file.
5
+ <p align="center">
6
+ <a href="https://www.npmjs.com/package/news-fragments?activeTab=versions"><img src="https://img.shields.io/npm/v/news-fragments?label=version&color=blue" alt="npm version" /></a>
7
+ <a href="https://www.npmjs.com/package/news-fragments?activeTab=versions"><img src="https://img.shields.io/npm/dw/news-fragments?color=green" alt="weekly downloads" /></a>
8
+ <a href="https://www.npmjs.com/package/news-fragments?activeTab=versions"><img src="https://img.shields.io/npm/l/news-fragments" alt="license" /></a>
9
+ </p>
6
10
 
7
- Basically, you need to specify a folder to be your center of fragments that will generate a custom changelog when released. After that, you'll create files with the desired extension with quick messages inside that folder to better understand what will come up on the new version of your software.
11
+ News Fragments is a plugin for [release-it](https://github.com/release-it/release-it) that generates a changelog from small "fragment" files. During development, contributors add one fragment file per change; at release time the fragments are compiled into a versioned changelog entry and then deleted automatically.
8
12
 
9
13
  ## Requirements
10
14
 
11
- - Use Node v22+
15
+ - Node v22+
16
+ - npm v10+
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install news-fragments
22
+ ```
12
23
 
13
24
  ## Setup
14
25
 
15
- In [release-it](https://github.com/release-it/release-it) config at `package.json`, create a `news-fragments` key-pair to override the default config - e.g.
26
+ Add `news-fragments` as a plugin inside your [release-it](https://github.com/release-it/release-it) configuration in `package.json`:
16
27
 
17
28
  ```json
18
- "plugins": {
19
- "news-fragments": {}
29
+ {
30
+ "release-it": {
31
+ "plugins": {
32
+ "news-fragments": {}
33
+ }
34
+ }
20
35
  }
21
36
  ```
22
37
 
38
+ Pass any [config options](#config-params) directly in this object to override the defaults.
39
+
40
+ ---
41
+
42
+ ## Release Workflow
43
+
44
+ Follow these steps every time you need to publish a new version.
45
+
46
+ ### 1. Create fragment files during development
47
+
48
+ For each change you want to appear in the changelog, run:
49
+
50
+ ```bash
51
+ news-fragments create <fragment-type> "<description>"
52
+ ```
53
+
54
+ **Available fragment types** (default): `feature`, `bugfix`, `doc`, `removal`, `misc`.
55
+
56
+ Examples:
57
+
58
+ ```bash
59
+ news-fragments create feature "Add dark mode support"
60
+ news-fragments create bugfix "Fix race condition on login"
61
+ news-fragments create misc "Update dependencies"
62
+ ```
63
+
64
+ Each command creates a timestamped file inside the `fragments/` folder (e.g., `fragments/1714220400000.feature`). Commit these files together with the code changes they describe.
65
+
66
+ ### 2. Preview the next changelog entry
67
+
68
+ Before releasing, verify what the generated changelog will look like:
69
+
70
+ ```bash
71
+ news-fragments preview
72
+ ```
73
+
74
+ To preview an already-released version stored in `CHANGELOG.md`:
75
+
76
+ ```bash
77
+ news-fragments preview -p <version>
78
+ # e.g. news-fragments preview -p 1.2.3
79
+ ```
80
+
81
+ ### 3. Run the release
82
+
83
+ ```bash
84
+ npm run release
85
+ ```
86
+
87
+ This command triggers `release-it`, which will:
88
+
89
+ 1. Run the test suite (`npm test`) as a pre-release check.
90
+ 2. Prompt you to select the next version (patch / minor / major).
91
+ 3. Burn the pending fragments into `CHANGELOG.md` under the new version header and delete the fragment files.
92
+ 4. Bump the version in `package.json`.
93
+ 5. Commit, tag, and push the release.
94
+
95
+ > The burn step runs automatically via the `news-fragments` plugin — you do **not** need to run `news-fragments burn` manually when using `release-it`.
96
+
97
+ ### Manual burn (without release-it)
98
+
99
+ If you need to compile fragments into the changelog outside of `release-it`, use:
100
+
101
+ ```bash
102
+ news-fragments burn <version>
103
+ # e.g. news-fragments burn 2.0.0
104
+ ```
105
+
106
+ This writes the changelog entry for `<version>` and removes all consumed fragment files.
107
+
108
+ ---
109
+
23
110
  ## Config
24
111
 
25
112
  ### Default config
@@ -28,21 +115,21 @@ In [release-it](https://github.com/release-it/release-it) config at `package.jso
28
115
  {
29
116
  "changelogFile": "CHANGELOG.md",
30
117
  "changelogDateFormat": "YYYY-MM-DD",
31
- "changelogTemplate": changelogTemplate,
118
+ "changelogTemplate": "<built-in handlebars template>",
32
119
  "fragmentsFolder": "fragments",
33
120
  "fragmentsTypes": [
34
- { "title": "Features", "extension": "feature" },
35
- { "title": "Bugfixes", "extension": "bugfix" },
36
- { "title": "Documentation", "extension": "doc" },
121
+ { "title": "Features", "extension": "feature" },
122
+ { "title": "Bugfixes", "extension": "bugfix" },
123
+ { "title": "Documentation", "extension": "doc" },
37
124
  { "title": "Deprecations and Removals", "extension": "removal" },
38
- { "title": "Misc", "extension": "misc" }
125
+ { "title": "Misc", "extension": "misc" }
39
126
  ]
40
127
  }
41
128
  ```
42
129
 
43
130
  ### Default changelog template
44
131
 
45
- ```
132
+ ```handlebars
46
133
  # [{{newVersion}}] - ({{bumpDate}})
47
134
  {{#fragments}}
48
135
  ## {{title}}
@@ -54,16 +141,39 @@ In [release-it](https://github.com/release-it/release-it) config at `package.jso
54
141
 
55
142
  ### Config params
56
143
 
57
- - **changelogFile**: A path to the file that will center your changelog.
58
- - **changelogDateFormat**: The date format that will be send to changelog template.
59
- - **changelogTemplate**: A [handlebars](https://www.npmjs.com/package/handlebars) template that will be used to render your changelog file content.
60
- - **fragmentsFolder**: A path to the folder that the fragments should be stored.
61
- - **fragmentsTypes**: An array containing a collection of objects with the title of changelog section and the extension of fragment types.
144
+ | Key | Description |
145
+ |-----|-------------|
146
+ | `changelogFile` | Path to the changelog file. |
147
+ | `changelogDateFormat` | [Moment.js](https://momentjs.com/docs/#/displaying/format/) date format used in the changelog header. |
148
+ | `changelogTemplate` | A [Handlebars](https://handlebarsjs.com/) template string for each version block. |
149
+ | `fragmentsFolder` | Path to the folder where fragment files are stored. |
150
+ | `fragmentsTypes` | Array of `{ title, extension }` objects that define the supported fragment types and their changelog section headings. |
62
151
 
63
152
  > See this plugin in action by checking our [CHANGELOG.md](./CHANGELOG.md)
64
153
 
65
- ## CLI
154
+ ---
155
+
156
+ ## CLI Reference
66
157
 
67
158
  ```bash
68
159
  news-fragments --help
69
160
  ```
161
+
162
+ | Command | Description |
163
+ |---------|-------------|
164
+ | `news-fragments create <type> "<text>"` | Create a new fragment file of the given type. |
165
+ | `news-fragments preview` | Print the next changelog entry to the terminal. |
166
+ | `news-fragments preview -p <version>` | Print a previously released changelog entry. |
167
+ | `news-fragments burn <version>` | Compile fragments into the changelog and delete them. |
168
+
169
+ ---
170
+
171
+ ## Contributing
172
+
173
+ ```bash
174
+ # Install dependencies
175
+ npm install
176
+
177
+ # Run tests (includes lint)
178
+ npm test
179
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "news-fragments",
3
- "version": "4.3.0",
3
+ "version": "4.4.3",
4
4
  "description": "A release-it plugin to manipulate changelogs",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -14,7 +14,7 @@
14
14
  },
15
15
  "repository": {
16
16
  "type": "git",
17
- "url": "https://github.com/grupoboticario/news-fragments.git"
17
+ "url": "git+https://github.com/grupoboticario/news-fragments.git"
18
18
  },
19
19
  "keywords": [
20
20
  "release",
@@ -32,32 +32,34 @@
32
32
  "devDependencies": {
33
33
  "@eslint/eslintrc": "^3.3.5",
34
34
  "@eslint/js": "^10.0.1",
35
- "@release-it/bumper": "^7.0.5",
36
- "@vitest/coverage-v8": "^4.1.5",
37
- "@vitest/ui": "^4.1.5",
38
- "eslint": "^10.2.1",
35
+ "@release-it/bumper": "^7.0.6",
36
+ "@vitest/coverage-v8": "^4.1.9",
37
+ "@vitest/ui": "^4.1.9",
38
+ "eslint": "^10.5.0",
39
39
  "eslint-config-prettier": "^10.1.8",
40
- "eslint-plugin-prettier": "^5.5.5",
40
+ "eslint-plugin-prettier": "^5.5.6",
41
41
  "eslint-plugin-simple-import-sort": "^13.0.0",
42
42
  "fs-monkey": "^1.1.0",
43
- "globals": "^17.5.0",
44
- "memfs": "^4.57.2",
43
+ "globals": "^17.7.0",
44
+ "memfs": "^4.57.8",
45
45
  "mockdate": "^3.0.5",
46
- "prettier": "^3.8.3",
46
+ "prettier": "^3.8.4",
47
47
  "pretty-quick": "^4.2.2",
48
- "semver": "^7.7.4",
49
- "vitest": "^4.1.5"
48
+ "semver": "^7.8.5",
49
+ "vitest": "^4.1.9"
50
50
  },
51
51
  "dependencies": {
52
52
  "chalk": "^5.6.2",
53
53
  "chalk-template": "^1.1.2",
54
54
  "handlebars": "^4.7.9",
55
- "joi": "^18.1.2",
56
- "marked": "^15.0.12",
57
- "marked-terminal": "^7.3.0",
55
+ "joi": "^18.2.3",
56
+ "markdown-it": "^14.2.0",
58
57
  "meow": "^14.1.0",
59
58
  "moment": "^2.30.1",
60
- "release-it": "^20.0.1"
59
+ "release-it": "^20.2.0"
60
+ },
61
+ "overrides": {
62
+ "undici": "^8.5.0"
61
63
  },
62
64
  "engines": {
63
65
  "npm": ">=10",
@@ -13,7 +13,7 @@ ${compiledTemplate}
13
13
  }
14
14
 
15
15
  export const renderTemplate = function (changelogTemplate, data, version) {
16
- const compiledTemplate = Handlebars.compile(changelogTemplate);
16
+ const compiledTemplate = Handlebars.compile(changelogTemplate, { noEscape: true });
17
17
  return injectMetadata(compiledTemplate(data), version);
18
18
  };
19
19
 
@@ -0,0 +1,70 @@
1
+ import chalk from "chalk";
2
+ import MarkdownIt from "markdown-it";
3
+
4
+ const styles = {
5
+ firstHeading: chalk.magenta.underline.bold,
6
+ heading: chalk.green.bold,
7
+ };
8
+
9
+ const md = new MarkdownIt();
10
+
11
+ const renderInlineToken = (token, env) => {
12
+ let content = token.content;
13
+
14
+ if (env.headingLevel) {
15
+ const prefix = `${"#".repeat(env.headingLevel)} `;
16
+ content = prefix + content;
17
+ const style =
18
+ env.headingLevel === 1 ? styles.firstHeading : styles.heading;
19
+
20
+ return style(content);
21
+ }
22
+
23
+ return content;
24
+ };
25
+
26
+ const renderTokens = (tokens, env) => {
27
+ let result = "";
28
+
29
+ for (const token of tokens) {
30
+ switch (token.type) {
31
+ case "heading_open":
32
+ env.headingLevel = Number(token.tag.slice(1));
33
+ break;
34
+ case "heading_close":
35
+ env.headingLevel = 0;
36
+ result += "\n";
37
+ break;
38
+ case "inline":
39
+ result += renderInlineToken(token, env);
40
+ break;
41
+ case "list_item_open":
42
+ result += "- ";
43
+ break;
44
+ case "list_item_close":
45
+ result += "\n";
46
+ break;
47
+ case "bullet_list_close":
48
+ result += "\n";
49
+ break;
50
+ case "paragraph_open":
51
+ case "paragraph_close":
52
+ case "bullet_list_open":
53
+ case "ordered_list_open":
54
+ case "ordered_list_close":
55
+ break;
56
+ default:
57
+ break;
58
+ }
59
+ }
60
+
61
+ return result;
62
+ };
63
+
64
+ export const renderMarkdownForTerminal = (source) => {
65
+ if (!source) {
66
+ return "";
67
+ }
68
+
69
+ return renderTokens(md.parse(source, {}), { headingLevel: 0 });
70
+ };
@@ -1,15 +1,7 @@
1
- import { marked } from "marked";
2
- import TerminalRenderer from "marked-terminal";
3
-
4
1
  import { generateTemplateData, renderTemplate } from "../build-template.js";
5
2
  import { newsFragmentsUserConfig } from "../config.js";
6
3
  import { getChangelogContent, getFragments } from "../file.js";
7
-
8
- marked.setOptions({
9
- renderer: new TerminalRenderer({ tab: 0 }),
10
- mangle: false,
11
- headerIds: false,
12
- });
4
+ import { renderMarkdownForTerminal } from "./markdown-terminal.js";
13
5
 
14
6
  export const preview = function (inputs, flags) {
15
7
  if (!!flags && flags.previousVersion) {
@@ -18,7 +10,7 @@ export const preview = function (inputs, flags) {
18
10
  );
19
11
 
20
12
  const changelogContent = getChangelogContent(newsFragmentsUserConfig);
21
- const previousOutput = marked(
13
+ const previousOutput = renderMarkdownForTerminal(
22
14
  (changelogContent.match(previousVersionRegex) || [""])[0],
23
15
  );
24
16
 
@@ -42,7 +34,7 @@ export const preview = function (inputs, flags) {
42
34
  version,
43
35
  );
44
36
 
45
- const output = marked(renderedTemplate);
37
+ const output = renderMarkdownForTerminal(renderedTemplate);
46
38
  process.stdout.write(output);
47
39
 
48
40
  return output;