changelog-tool 0.2.0 → 0.4.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.
- package/changelog.md +12 -0
- package/changelog.mjs +51 -7
- package/cli.mjs +213 -0
- package/index.mjs +2 -131
- package/package.json +4 -1
- package/parse.mjs +45 -4
- package/readme.md +48 -0
- package/test/parse.mjs +62 -1
- package/util.mjs +1 -1
package/changelog.md
CHANGED
@@ -1,6 +1,18 @@
|
|
1
1
|
Changelog
|
2
2
|
=========
|
3
3
|
|
4
|
+
0.4.0 (2023-02-12)
|
5
|
+
------------------
|
6
|
+
|
7
|
+
* Implemented the "format", "parse" and "release" commands.
|
8
|
+
|
9
|
+
|
10
|
+
0.3.0 (2023-02-12)
|
11
|
+
------------------
|
12
|
+
|
13
|
+
* Implemented the 'show' command.
|
14
|
+
|
15
|
+
|
4
16
|
0.2.0 (2023-02-12)
|
5
17
|
------------------
|
6
18
|
|
package/changelog.mjs
CHANGED
@@ -16,8 +16,7 @@ export class Changelog {
|
|
16
16
|
this.title + '\n' +
|
17
17
|
('='.repeat(this.title.length)) + '\n' +
|
18
18
|
'\n' +
|
19
|
-
this.versions.map(version => version.toString()).join('\n\n')
|
20
|
-
'\n'
|
19
|
+
this.versions.map(version => version.toString()).join('\n\n')
|
21
20
|
);
|
22
21
|
|
23
22
|
}
|
@@ -26,17 +25,59 @@ export class Changelog {
|
|
26
25
|
* Adds a new Version log
|
27
26
|
*
|
28
27
|
* @param version {VersionLog}
|
28
|
+
* @returns {VersionLog}
|
29
29
|
*/
|
30
30
|
add(version) {
|
31
31
|
|
32
|
-
this.versions.
|
32
|
+
this.versions = [version, ...this.versions];
|
33
|
+
return version;
|
34
|
+
|
35
|
+
}
|
36
|
+
|
37
|
+
/**
|
38
|
+
* Adds a new version to the log. Version string is automatically increased
|
39
|
+
* from the previous one
|
40
|
+
*
|
41
|
+
* @returns {VersionLog}
|
42
|
+
*/
|
43
|
+
newVersion() {
|
44
|
+
|
45
|
+
const lastVersionStr = this.versions[0].version;
|
46
|
+
const lastVersionParts = lastVersionStr.split('.');
|
47
|
+
if (!lastVersionParts.at(-1)?.match(/^[0-9]+$/)) {
|
48
|
+
throw new Error(`Could not automatically determine the next version string after "${lastVersionStr}"`);
|
49
|
+
}
|
50
|
+
const newVersionStr = [
|
51
|
+
...lastVersionParts.slice(0, -1),
|
52
|
+
// @ts-ignore-error 'Possibly udefined', but we know it isnt
|
53
|
+
parseInt(lastVersionParts.at(-1)) + 1
|
54
|
+
].join('.');
|
55
|
+
const versionLog = new VersionLog(newVersionStr);
|
56
|
+
|
57
|
+
return this.add(versionLog);
|
58
|
+
|
59
|
+
}
|
60
|
+
|
61
|
+
/**
|
62
|
+
* Finds a VersionLog by its version string
|
63
|
+
*
|
64
|
+
* @param {string} version
|
65
|
+
* @returns {VersionLog}
|
66
|
+
*/
|
67
|
+
get(version) {
|
68
|
+
|
69
|
+
const log = this.versions.find( myLog => myLog.version === version);
|
70
|
+
if (!log) {
|
71
|
+
throw new Error(`Couldn't find version ${version} in the changelog`);
|
72
|
+
}
|
73
|
+
return log;
|
33
74
|
|
34
75
|
}
|
35
76
|
|
36
77
|
}
|
37
78
|
|
38
79
|
export class VersionLog {
|
39
|
-
|
80
|
+
|
40
81
|
/**
|
41
82
|
* @type {string}
|
42
83
|
*/
|
@@ -72,9 +113,12 @@ export class VersionLog {
|
|
72
113
|
|
73
114
|
/**
|
74
115
|
* @param {string} message
|
116
|
+
* @returns {LogItem}
|
75
117
|
*/
|
76
118
|
add(message) {
|
77
|
-
|
119
|
+
const item = new LogItem(message);
|
120
|
+
this.items.push(item);
|
121
|
+
return item;
|
78
122
|
}
|
79
123
|
|
80
124
|
toString() {
|
@@ -83,11 +127,11 @@ export class VersionLog {
|
|
83
127
|
return (
|
84
128
|
title + '\n' +
|
85
129
|
('-'.repeat(title.length)) + '\n' +
|
86
|
-
(this.preface ? wrap(this.preface)
|
130
|
+
(this.preface ? '\n' + wrap(this.preface) : '') +
|
87
131
|
'\n' +
|
88
132
|
this.items.map(version => version.toString()).join('\n') +
|
89
133
|
'\n' +
|
90
|
-
(this.postface ? wrap(this.postface) + '\n' : '')
|
134
|
+
(this.postface ? '\n' + wrap(this.postface) + '\n' : '')
|
91
135
|
);
|
92
136
|
|
93
137
|
}
|
package/cli.mjs
ADDED
@@ -0,0 +1,213 @@
|
|
1
|
+
// @ts-check
|
2
|
+
import { parseArgs } from 'node:util';
|
3
|
+
import * as fs from 'node:fs/promises';
|
4
|
+
import * as url from 'node:url';
|
5
|
+
import { readPackageVersion, exists } from './util.mjs';
|
6
|
+
import { Changelog, VersionLog, LogItem } from './changelog.mjs';
|
7
|
+
import { parseFile } from './parse.mjs';
|
8
|
+
|
9
|
+
const filename = 'changelog.md';
|
10
|
+
|
11
|
+
const pkg = JSON.parse(
|
12
|
+
await fs.readFile(
|
13
|
+
url.fileURLToPath(url.resolve(import.meta.url, './package.json')),
|
14
|
+
'utf-8',
|
15
|
+
)
|
16
|
+
);
|
17
|
+
|
18
|
+
async function main() {
|
19
|
+
|
20
|
+
const { positionals, values } = parseArgs({
|
21
|
+
options: {
|
22
|
+
help: {
|
23
|
+
type: 'boolean',
|
24
|
+
short: 'h',
|
25
|
+
default: false,
|
26
|
+
description: 'This help screen',
|
27
|
+
},
|
28
|
+
all: {
|
29
|
+
type: 'boolean',
|
30
|
+
default: false,
|
31
|
+
description: 'Show all versions',
|
32
|
+
},
|
33
|
+
},
|
34
|
+
allowPositionals: true,
|
35
|
+
});
|
36
|
+
|
37
|
+
|
38
|
+
|
39
|
+
if (positionals.length < 1 || values.help) {
|
40
|
+
help();
|
41
|
+
process.exit(1);
|
42
|
+
}
|
43
|
+
|
44
|
+
const command = positionals[0];
|
45
|
+
|
46
|
+
switch(command) {
|
47
|
+
case 'help' :
|
48
|
+
await help();
|
49
|
+
break;
|
50
|
+
case 'init' :
|
51
|
+
await init();
|
52
|
+
break;
|
53
|
+
case 'add' :
|
54
|
+
if (positionals.length < 2) {
|
55
|
+
throw new Error('The "message" argument must be specified with the "add" command');
|
56
|
+
}
|
57
|
+
await add(positionals.slice(1).join(' '));
|
58
|
+
break;
|
59
|
+
case 'release' :
|
60
|
+
await release();
|
61
|
+
break;
|
62
|
+
case 'format' :
|
63
|
+
await format();
|
64
|
+
break;
|
65
|
+
case 'show' :
|
66
|
+
await show({ all: !!values.all, version: positionals[1]});
|
67
|
+
break;
|
68
|
+
case 'list' :
|
69
|
+
await list();
|
70
|
+
break;
|
71
|
+
default:
|
72
|
+
process.stderr.write(`Unknown command ${command}\n`);
|
73
|
+
process.exit(1);
|
74
|
+
break;
|
75
|
+
}
|
76
|
+
|
77
|
+
}
|
78
|
+
|
79
|
+
try {
|
80
|
+
await main();
|
81
|
+
} catch (err) {
|
82
|
+
process.stderr.write('Error: ' + err.message + '\n');
|
83
|
+
process.exit(1);
|
84
|
+
}
|
85
|
+
|
86
|
+
function help() {
|
87
|
+
console.log(
|
88
|
+
`Changelog Tool v${pkg.version}
|
89
|
+
|
90
|
+
Manipulate your changelog file
|
91
|
+
|
92
|
+
Usage:
|
93
|
+
|
94
|
+
changelog init - Create a new, empty changelog.
|
95
|
+
changelog add [message] - Adds a new line to the changelog.
|
96
|
+
changelog release - Marks the current changelog as released.
|
97
|
+
changelog show - Show the last changelog.
|
98
|
+
changelog show [version] - Show the changelog of a specific version.
|
99
|
+
changelog list - List all versions in the changelog.
|
100
|
+
changelog format - Reformats the changelog in the standard format.
|
101
|
+
|
102
|
+
The logs this tool uses follows a specific markdown format. Currently it will
|
103
|
+
only look for a file named 'changelog.md' in the current directory.
|
104
|
+
|
105
|
+
To see an example of this format, you can either run 'changelog init' or
|
106
|
+
check out the changelog shipped with this project:
|
107
|
+
|
108
|
+
https://github.com/evert/changelog-tool
|
109
|
+
`);
|
110
|
+
|
111
|
+
}
|
112
|
+
|
113
|
+
async function init() {
|
114
|
+
|
115
|
+
if (await exists(filename)) {
|
116
|
+
throw new Error(`A file named ${filename} already exists`);
|
117
|
+
}
|
118
|
+
|
119
|
+
const changelog = new Changelog();
|
120
|
+
const version = new VersionLog(await readPackageVersion());
|
121
|
+
version.add('New project!');
|
122
|
+
changelog.versions.push(version);
|
123
|
+
|
124
|
+
await fs.writeFile(filename, changelog.toString());
|
125
|
+
console.log(`${filename} created`);
|
126
|
+
|
127
|
+
}
|
128
|
+
|
129
|
+
async function list() {
|
130
|
+
|
131
|
+
const changelog = await parseChangelog();
|
132
|
+
|
133
|
+
for(const version of changelog.versions) {
|
134
|
+
console.log(version.version);
|
135
|
+
}
|
136
|
+
|
137
|
+
}
|
138
|
+
|
139
|
+
/**
|
140
|
+
* @param {Object} showOptions
|
141
|
+
* @param {boolean} showOptions.all Show all versions
|
142
|
+
* @param {string?} showOptions.version show a specific version
|
143
|
+
*/
|
144
|
+
async function show({all, version}) {
|
145
|
+
|
146
|
+
const changelog = await parseChangelog();
|
147
|
+
|
148
|
+
let toRender;
|
149
|
+
if (all) {
|
150
|
+
toRender = changelog.versions;
|
151
|
+
} else if (version) {
|
152
|
+
toRender = [changelog.get(version)];
|
153
|
+
} else {
|
154
|
+
toRender = [changelog.versions[0]];
|
155
|
+
}
|
156
|
+
|
157
|
+
console.log(
|
158
|
+
toRender
|
159
|
+
.map( log => log.toString())
|
160
|
+
.join('\n\n')
|
161
|
+
);
|
162
|
+
|
163
|
+
}
|
164
|
+
|
165
|
+
async function format() {
|
166
|
+
const changelog = await parseChangelog();
|
167
|
+
await fs.writeFile(filename, changelog.toString());
|
168
|
+
console.log(`${changelog.versions.length} changelogs saved to ${filename}`);
|
169
|
+
}
|
170
|
+
|
171
|
+
/**
|
172
|
+
* @param {string} message
|
173
|
+
*/
|
174
|
+
async function add(message) {
|
175
|
+
const changelog = await parseChangelog();
|
176
|
+
|
177
|
+
let lastVersion = changelog.versions[0];
|
178
|
+
if (lastVersion.date) {
|
179
|
+
lastVersion = changelog.newVersion();
|
180
|
+
console.log('Creating new version: %s', lastVersion.version);
|
181
|
+
}
|
182
|
+
lastVersion.add(message);
|
183
|
+
|
184
|
+
await fs.writeFile(filename, changelog.toString());
|
185
|
+
console.log(`${changelog.versions.length} changelogs saved to ${filename}`);
|
186
|
+
}
|
187
|
+
|
188
|
+
async function release() {
|
189
|
+
const changelog = await parseChangelog();
|
190
|
+
|
191
|
+
let lastVersion = changelog.versions[0];
|
192
|
+
if (lastVersion.date) {
|
193
|
+
throw new Error(`Previous version "${lastVersion.version}" already had a release date`);
|
194
|
+
}
|
195
|
+
lastVersion.date = new Date().toISOString().substr(0,10);
|
196
|
+
console.log(`Releasing ${lastVersion.version}`);
|
197
|
+
await fs.writeFile(filename, changelog.toString());
|
198
|
+
console.log(`${changelog.versions.length} changelogs saved to ${filename}`);
|
199
|
+
|
200
|
+
}
|
201
|
+
|
202
|
+
/**
|
203
|
+
* @returns {Promise<Changelog>}
|
204
|
+
*/
|
205
|
+
async function parseChangelog() {
|
206
|
+
|
207
|
+
if (!await exists(filename)) {
|
208
|
+
throw new Error(`${filename} not found in current directory`);
|
209
|
+
}
|
210
|
+
|
211
|
+
return await parseFile(filename);
|
212
|
+
|
213
|
+
}
|
package/index.mjs
CHANGED
@@ -1,131 +1,2 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
import * as fs from 'node:fs/promises';
|
4
|
-
import * as url from 'node:url';
|
5
|
-
import { readPackageVersion, exists } from './util.mjs';
|
6
|
-
import { Changelog, VersionLog, LogItem } from './changelog.mjs';
|
7
|
-
import { parseFile } from './parse.mjs';
|
8
|
-
|
9
|
-
const filename = 'changelog.md';
|
10
|
-
|
11
|
-
const pkg = JSON.parse(
|
12
|
-
await fs.readFile(
|
13
|
-
url.fileURLToPath(url.resolve(import.meta.url, './package.json')),
|
14
|
-
'utf-8',
|
15
|
-
)
|
16
|
-
);
|
17
|
-
|
18
|
-
async function main() {
|
19
|
-
|
20
|
-
const { positionals, values } = parseArgs({
|
21
|
-
options: {
|
22
|
-
help: {
|
23
|
-
type: 'boolean',
|
24
|
-
short: 'h',
|
25
|
-
default: false,
|
26
|
-
description: 'This help screen',
|
27
|
-
},
|
28
|
-
},
|
29
|
-
allowPositionals: true,
|
30
|
-
});
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
if (positionals.length < 1 || values.help) {
|
35
|
-
help();
|
36
|
-
process.exit(1);
|
37
|
-
}
|
38
|
-
|
39
|
-
const command = positionals[0];
|
40
|
-
|
41
|
-
switch(command) {
|
42
|
-
case 'help' :
|
43
|
-
await help();
|
44
|
-
break;
|
45
|
-
case 'init' :
|
46
|
-
await init();
|
47
|
-
break;
|
48
|
-
/*
|
49
|
-
case 'add' :
|
50
|
-
await add();
|
51
|
-
break;
|
52
|
-
case 'release' :
|
53
|
-
await release();
|
54
|
-
break;
|
55
|
-
case 'show' :
|
56
|
-
await show();
|
57
|
-
break;
|
58
|
-
*/
|
59
|
-
case 'list' :
|
60
|
-
await list();
|
61
|
-
break;
|
62
|
-
default:
|
63
|
-
process.stderr.write(`Unknown command ${command}\n`);
|
64
|
-
process.exit(1);
|
65
|
-
break;
|
66
|
-
}
|
67
|
-
|
68
|
-
}
|
69
|
-
|
70
|
-
try {
|
71
|
-
await main();
|
72
|
-
} catch (err) {
|
73
|
-
process.stderr.write('Error: ' + err.message + '\n');
|
74
|
-
process.exit(1);
|
75
|
-
}
|
76
|
-
|
77
|
-
function help() {
|
78
|
-
console.log(
|
79
|
-
`Changelog Tool v${pkg.version}
|
80
|
-
|
81
|
-
Manipulate your changelog file
|
82
|
-
|
83
|
-
Usage:
|
84
|
-
|
85
|
-
changelog init - Create a new, empty changelog.
|
86
|
-
changelog add [message] - Adds a new line to the changelog.
|
87
|
-
changelog release - Marks the current changelog as released.
|
88
|
-
changelog show - Show the last changelog.
|
89
|
-
changelog show [version] - Show the changelog of a specific version.
|
90
|
-
changelog list - List all versions in the changelog.
|
91
|
-
|
92
|
-
The logs this tool uses follows a specific markdown format. Currently it will
|
93
|
-
only look for a file named 'changelog.md' in the current directory.
|
94
|
-
|
95
|
-
To see an example of this format, you can either run 'changelog init' or
|
96
|
-
check out the changelog shipped with this project:
|
97
|
-
|
98
|
-
https://github.com/evert/changelog-tool
|
99
|
-
`);
|
100
|
-
|
101
|
-
}
|
102
|
-
|
103
|
-
async function init() {
|
104
|
-
|
105
|
-
if (await exists(filename)) {
|
106
|
-
throw new Error(`A file named ${filename} already exists`);
|
107
|
-
}
|
108
|
-
|
109
|
-
const changelog = new Changelog();
|
110
|
-
const version = new VersionLog(await readPackageVersion());
|
111
|
-
version.add('New project!');
|
112
|
-
changelog.versions.push(version);
|
113
|
-
|
114
|
-
await fs.writeFile(filename, changelog.toString());
|
115
|
-
console.log(`${filename} created`);
|
116
|
-
|
117
|
-
}
|
118
|
-
|
119
|
-
async function list() {
|
120
|
-
|
121
|
-
if (!await exists(filename)) {
|
122
|
-
throw new Error(`${filename} not found in current directory`);
|
123
|
-
}
|
124
|
-
|
125
|
-
const changelog = await parseFile(filename);
|
126
|
-
|
127
|
-
for(const version of changelog.versions) {
|
128
|
-
console.log(version.version);
|
129
|
-
}
|
130
|
-
|
131
|
-
}
|
1
|
+
export { parse, parseFile } from './parse.mjs';
|
2
|
+
export { Changelog, VersionLog, LogItem } from './changelog.mjs';
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "changelog-tool",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.4.0",
|
4
4
|
"description": "A CLI tool for manipulating changelogs",
|
5
5
|
"main": "index.mjs",
|
6
6
|
"scripts": {
|
@@ -15,6 +15,9 @@
|
|
15
15
|
"engine": {
|
16
16
|
"node": ">16"
|
17
17
|
},
|
18
|
+
"bin": {
|
19
|
+
"changelog": "./cli.mjs"
|
20
|
+
},
|
18
21
|
"devDependencies": {
|
19
22
|
"@types/node": "^18.11.19",
|
20
23
|
"typescript": "^4.9.5"
|
package/parse.mjs
CHANGED
@@ -27,15 +27,37 @@ export function parse(changelogInput) {
|
|
27
27
|
const changelog = new Changelog();
|
28
28
|
changelog.title = lines[0];
|
29
29
|
|
30
|
+
let lastVersionLog = null;
|
31
|
+
let lastBullet = null;
|
32
|
+
|
30
33
|
for(let idx=2; idx<lines.length; idx++) {
|
31
34
|
|
35
|
+
const line = lines[idx];
|
36
|
+
|
37
|
+
if (line.startsWith('* ')) {
|
38
|
+
// Found a bullet point
|
39
|
+
if (!lastVersionLog) {
|
40
|
+
throw new Error(`Parse error: found a bullet point * outside of a level 2 heading on line ${idx+1}`);
|
41
|
+
}
|
42
|
+
lastBullet = lastVersionLog.add(line.substr(1).trim());
|
43
|
+
continue;
|
44
|
+
}
|
45
|
+
if (line.startsWith(' ')) {
|
46
|
+
// Continuation of last line.
|
47
|
+
if (!lastBullet) {
|
48
|
+
throw new Error(`Parse error: unexpected indented string on line ${line+1}`);
|
49
|
+
}
|
50
|
+
lastBullet.message += ' ' + line.trim();
|
51
|
+
continue;
|
52
|
+
}
|
53
|
+
|
54
|
+
// Look to the next line for ----
|
32
55
|
if (lines[idx+1]?.match(/^-{1,}$/)) {
|
33
56
|
// Found a new Version
|
34
|
-
const
|
35
|
-
const matches = versionTitle.match(/^([0-9\.]{3,}(?:-(?:alpha|beta)\.[0-9])?) \(([0-9]{4}-[0-9]{2}-[0-9]{2}|\?\?\?\?-\?\?-\?\?)\)$/);
|
57
|
+
const matches = line.match(/^([0-9\.]{3,}(?:-(?:alpha|beta)\.[0-9])?) \(([0-9]{4}-[0-9]{2}-[0-9]{2}|\?\?\?\?-\?\?-\?\?)\)$/);
|
36
58
|
|
37
59
|
if (!matches) {
|
38
|
-
throw new Error(`A version title must have the format "1.0.0 (YYYY-MM-DD)" or "1.0.0 (????-??-??)" for unreleased versions. We found: "${
|
60
|
+
throw new Error(`A version title must have the format "1.0.0 (YYYY-MM-DD)" or "1.0.0 (????-??-??)" for unreleased versions. We found: "${line}"`);
|
39
61
|
}
|
40
62
|
|
41
63
|
const versionLog = new VersionLog(matches[1]);
|
@@ -44,10 +66,29 @@ export function parse(changelogInput) {
|
|
44
66
|
} else {
|
45
67
|
versionLog.date = matches[2];
|
46
68
|
}
|
47
|
-
changelog.
|
69
|
+
changelog.versions.push(versionLog);
|
70
|
+
lastVersionLog = versionLog;
|
71
|
+
lastBullet = null;
|
72
|
+
idx++;
|
73
|
+
continue;
|
48
74
|
|
49
75
|
}
|
50
76
|
|
77
|
+
if (line.trim()==='') {
|
78
|
+
continue;
|
79
|
+
}
|
80
|
+
|
81
|
+
if (!lastVersionLog) {
|
82
|
+
throw new Error(`Parse error: unexpected string on line ${line+1}`);
|
83
|
+
}
|
84
|
+
// If we got here, this is either a loose preface or postface line.
|
85
|
+
if (lastBullet) {
|
86
|
+
lastVersionLog.postface = lastVersionLog.postface ? lastVersionLog.postface + ' ' + line : line;
|
87
|
+
} else {
|
88
|
+
lastVersionLog.preface = lastVersionLog.preface ? lastVersionLog.preface + ' ' + line : line;
|
89
|
+
}
|
90
|
+
|
91
|
+
|
51
92
|
}
|
52
93
|
|
53
94
|
return changelog;
|
package/readme.md
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
Changelog tool
|
2
|
+
==============
|
3
|
+
|
4
|
+
This repository contains a simple tool for reading and manipulating changelog
|
5
|
+
files.
|
6
|
+
|
7
|
+
This tool currently expects to work with a file named 'changelog.md' in the
|
8
|
+
current working directory. This is a markdown file that looks like this:
|
9
|
+
|
10
|
+
```
|
11
|
+
0.4.0 (????-??-??)
|
12
|
+
------------------
|
13
|
+
|
14
|
+
* Feature A
|
15
|
+
* Bugfix 3
|
16
|
+
|
17
|
+
0.3.0 (2023-02-08)
|
18
|
+
------------------
|
19
|
+
|
20
|
+
* First public release!
|
21
|
+
```
|
22
|
+
|
23
|
+
Questionmarks for the date indicate an unreleased version.
|
24
|
+
|
25
|
+
Installation
|
26
|
+
------------
|
27
|
+
|
28
|
+
```sh
|
29
|
+
npm install changelog-tool --save-dev
|
30
|
+
```
|
31
|
+
|
32
|
+
CLI
|
33
|
+
---
|
34
|
+
|
35
|
+
To tool can be used programmatically and with the CLI. The CLI has the
|
36
|
+
following commands:
|
37
|
+
|
38
|
+
```
|
39
|
+
npx changelog init - Create a new, empty npx changelog.
|
40
|
+
npx changelog add [message] - Adds a new line to the npx changelog.
|
41
|
+
npx changelog release - Marks the current npx changelog as released.
|
42
|
+
npx changelog show - Show the last npx changelog.
|
43
|
+
npx changelog show [version] - Show the npx changelog of a specific version.
|
44
|
+
npx changelog list - List all versions in the npx changelog.
|
45
|
+
npx changelog format - Reformats the npx changelog in the standard format.
|
46
|
+
```
|
47
|
+
|
48
|
+
Feature requests and bug reports are welcome.
|
package/test/parse.mjs
CHANGED
@@ -2,7 +2,7 @@ import { test } from 'node:test';
|
|
2
2
|
import { parse } from '../parse.mjs';
|
3
3
|
import * as assert from 'node:assert';
|
4
4
|
|
5
|
-
test('Parsing
|
5
|
+
test('Parsing changelog metadata', async () => {
|
6
6
|
|
7
7
|
const input = `Time for a change
|
8
8
|
=========
|
@@ -31,3 +31,64 @@ test('Parsing a basic changelog', async () => {
|
|
31
31
|
assert.equal('0.1.0', result.versions[1].version);
|
32
32
|
|
33
33
|
});
|
34
|
+
|
35
|
+
test('Parsing changelog entries', async () => {
|
36
|
+
|
37
|
+
const input = `Time for a change
|
38
|
+
=========
|
39
|
+
|
40
|
+
0.2.0 (????-??-??)
|
41
|
+
------------------
|
42
|
+
|
43
|
+
* Implemented the 'list' command.
|
44
|
+
* Added testing framework.
|
45
|
+
|
46
|
+
0.1.0 (2023-02-08)
|
47
|
+
------------------
|
48
|
+
|
49
|
+
* Implemented the 'help' and 'init' commands.
|
50
|
+
*
|
51
|
+
`;
|
52
|
+
|
53
|
+
const result = await parse(input);
|
54
|
+
|
55
|
+
const latest = result.get('0.2.0');
|
56
|
+
assert.equal(2, latest.items.length);
|
57
|
+
assert.equal('Implemented the \'list\' command.', latest.items[0].message);
|
58
|
+
|
59
|
+
|
60
|
+
});
|
61
|
+
|
62
|
+
test('Preface and postface', async () => {
|
63
|
+
|
64
|
+
const input = `Time for a change
|
65
|
+
=========
|
66
|
+
|
67
|
+
0.2.0 (????-??-??)
|
68
|
+
------------------
|
69
|
+
|
70
|
+
WOW another release. How good is that?
|
71
|
+
Here's another line.
|
72
|
+
|
73
|
+
* Implemented the 'list' command.
|
74
|
+
* Added testing framework.
|
75
|
+
|
76
|
+
Well, that's all folks.
|
77
|
+
|
78
|
+
0.1.0 (2023-02-08)
|
79
|
+
------------------
|
80
|
+
|
81
|
+
* Implemented the 'help' and 'init' commands.
|
82
|
+
*
|
83
|
+
`;
|
84
|
+
|
85
|
+
debugger;
|
86
|
+
const result = await parse(input);
|
87
|
+
|
88
|
+
const latest = result.get('0.2.0');
|
89
|
+
|
90
|
+
assert.equal('WOW another release. How good is that? Here\'s another line.', latest.preface);
|
91
|
+
assert.equal('Well, that\'s all folks.', latest.postface);
|
92
|
+
|
93
|
+
|
94
|
+
});
|
package/util.mjs
CHANGED
@@ -49,7 +49,7 @@ export async function readPackageVersion() {
|
|
49
49
|
* @param {number} secondLineOffset
|
50
50
|
* @param {number} lineLength
|
51
51
|
*/
|
52
|
-
export function wrap(input, secondLineOffset = 0, lineLength =
|
52
|
+
export function wrap(input, secondLineOffset = 0, lineLength = 79) {
|
53
53
|
|
54
54
|
const words = input.split(' ');
|
55
55
|
const lines = [];
|