changelog-machine 1.0.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/LICENSE.md ADDED
@@ -0,0 +1,8 @@
1
+ The MIT License (MIT)
2
+ Copyright (c) 2022 Philipp Kief
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5
+
6
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7
+
8
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,108 @@
1
+ <h1 align="center">
2
+ <br>
3
+ <img src="./logo.png" alt="logo" width="200">
4
+ <br><br>
5
+ Changelog Machine
6
+ <br>
7
+ <br>
8
+ </h1>
9
+
10
+ <h4 align="center">Generate a changelog based on Git commit messages and tags.</h4>
11
+
12
+ ## Getting started
13
+
14
+ The tool can be executed with this command:
15
+
16
+ ```
17
+ npx changelog-machine
18
+ ```
19
+
20
+ It will generate a file called CHANGELOG.md in the root directory of the project.
21
+
22
+ ## Configuration
23
+
24
+ The generation of the changelog can be configured via a config file.
25
+
26
+ ```
27
+ npx changelog-machine --config changelog.config.json
28
+ ```
29
+
30
+ ### Command overview
31
+
32
+ | COMMAND | ALIAS | DESCRIPTION |
33
+ | ----------- | ----- | ------------------------------ |
34
+ | `--config` | `-c` | Path to the configuration file |
35
+ | `--version` | `-v` | Print version |
36
+ | `--help` | `-h` | Print command instructions |
37
+
38
+ ### Configuration file
39
+
40
+ The configuration file can be configured like this:
41
+
42
+ ```json
43
+ {
44
+ "title": "Changelog",
45
+ "description": "Some description text",
46
+ "repositoryUrl": "https://github.com/PKief/vscode-material-icon-theme",
47
+ "blacklistPattern": "Release|^\\d+\\.\\d+\\.\\d+$",
48
+ "filePath": "CHANGELOG.md"
49
+ }
50
+ ```
51
+
52
+ More detailed description of the config:
53
+
54
+ | CONFIG | DESCRIPTION | DEFAULT |
55
+ | ------------------ | ----------------------------------------------- | -------------------------------------------------------------------------------------------------- |
56
+ | `title` | Title of the changelog | "Changelog" |
57
+ | `description` | Description under the title | "All notable changes to this project will be documented in this file. Dates are displayed in UTC." |
58
+ | `filePath` | Path of the output file | "CHANGELOG.md" |
59
+ | `repositoryUrl` | Links to the repository for further information | |
60
+ | `blacklistPattern` | Regex to remove commit messages | |
61
+
62
+ ## Example output
63
+
64
+ The following commit summary is printed into the CHANGELOG.md file and can look like this:
65
+
66
+ #### [v4.12.1](https://github.com/PKief/vscode-material-icon-theme/compare/v4.12.1...HEAD)
67
+
68
+ > February 5, 2022
69
+
70
+ - Update release commit message [`3167316`](https://github.com/PKief/vscode-material-icon-theme/commit/3167316)
71
+ - Update release workflow [`7f2520d`](https://github.com/PKief/vscode-material-icon-theme/commit/7f2520d)
72
+ - Adjust preview script for folder icons [`6a00111`](https://github.com/PKief/vscode-material-icon-theme/commit/6a00111)
73
+ - Fix compare link [`fa45abf`](https://github.com/PKief/vscode-material-icon-theme/commit/fa45abf)
74
+ - Filter out release commits [`e3468ca`](https://github.com/PKief/vscode-material-icon-theme/commit/e3468ca)
75
+
76
+ ## Programmatic use
77
+
78
+ The tool can be imported as module into existing JavaScript or TypeScript code. Therefor it is necessary to install it via npm or yarn:
79
+
80
+ NPM:
81
+
82
+ ```
83
+ npm install --save-dev changelog-machine
84
+ ```
85
+
86
+ Yarn:
87
+
88
+ ```
89
+ yarn add --dev changelog-machine
90
+ ```
91
+
92
+ The module can be imported like this:
93
+
94
+ ```ts
95
+ import { printMarkdown } from 'changelog-machine';
96
+
97
+ // usage with default config
98
+ printMarkdown();
99
+
100
+ // usage with customizations
101
+ printMarkdown({
102
+ filePath: './changelog/CHANGES.md',
103
+ description: 'List of changes',
104
+ title: 'All releases',
105
+ blacklistPattern: '^Release', // excludes all commits that start with "Release"
106
+ repositoryUrl: 'https://github.com/PKief/vscode-material-icon-theme',
107
+ });
108
+ ```
package/bin/cli.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('../lib/cli/index.js');
@@ -0,0 +1,2 @@
1
+ declare const printHelp: () => void;
2
+ export { printHelp };
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.printHelp = void 0;
4
+ const printHelp = () => {
5
+ return console.log(`
6
+ Usage
7
+ $ npx changelog-machine -c changelog.config.json
8
+
9
+ Options
10
+ --config, -c Path to the configuration file
11
+ --version, -v Show version
12
+ --help, -h Show help
13
+ `);
14
+ };
15
+ exports.printHelp = printHelp;
@@ -0,0 +1,3 @@
1
+ import { Config } from '../../models';
2
+ declare const printMarkdown: (config?: Config | undefined) => Promise<void>;
3
+ export { printMarkdown };
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.printMarkdown = void 0;
13
+ const async_1 = require("../../core/async");
14
+ const markdown_1 = require("../../core/markdown");
15
+ const default_1 = require("../../core/default");
16
+ const printMarkdown = (config) => __awaiter(void 0, void 0, void 0, function* () {
17
+ var _a;
18
+ const output = yield (0, markdown_1.createMarkdown)(config);
19
+ try {
20
+ yield (0, async_1.outputFileAsync)((_a = config === null || config === void 0 ? void 0 : config.filePath) !== null && _a !== void 0 ? _a : default_1.defaultConfig.outputFilename, output);
21
+ }
22
+ catch (error) {
23
+ console.error(error);
24
+ }
25
+ });
26
+ exports.printMarkdown = printMarkdown;
@@ -0,0 +1,2 @@
1
+ declare const printVersion: () => void;
2
+ export { printVersion };
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.printVersion = void 0;
4
+ const printVersion = () => {
5
+ return console.log(`${process.env.npm_package_name} v${process.env.npm_package_version}`);
6
+ };
7
+ exports.printVersion = printVersion;
@@ -0,0 +1,3 @@
1
+ import minimist from 'minimist';
2
+ declare const flags: minimist.Opts | undefined;
3
+ export { flags };
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.flags = void 0;
4
+ const flags = {
5
+ string: 'config',
6
+ boolean: ['version', 'help'],
7
+ alias: { v: 'version', h: 'help' },
8
+ unknown: (a) => {
9
+ console.log(`The argument '${a}' is invalid for this command. Please use --help to read the description of this command.`);
10
+ return false;
11
+ },
12
+ };
13
+ exports.flags = flags;
@@ -0,0 +1,3 @@
1
+ import { Config } from '../../models';
2
+ declare const readConfigFile: (configFilePath: string) => Promise<Config>;
3
+ export { readConfigFile };
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.readConfigFile = void 0;
13
+ const async_1 = require("../../core/async");
14
+ const readConfigFile = (configFilePath) => __awaiter(void 0, void 0, void 0, function* () {
15
+ var _a;
16
+ try {
17
+ const file = yield (0, async_1.readFileAsync)(configFilePath);
18
+ return JSON.parse(file.toLocaleString());
19
+ }
20
+ catch (error) {
21
+ throw new Error((_a = `Unable to read the config file at the location ${configFilePath}\n` +
22
+ error) !== null && _a !== void 0 ? _a : '');
23
+ }
24
+ });
25
+ exports.readConfigFile = readConfigFile;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const minimist_1 = __importDefault(require("minimist"));
16
+ const default_1 = require("../core/default");
17
+ const printHelp_1 = require("./commands/printHelp");
18
+ const printMarkdown_1 = require("./commands/printMarkdown");
19
+ const printVersion_1 = require("./commands/printVersion");
20
+ const options_1 = require("./config/options");
21
+ const readConfigFile_1 = require("./config/readConfigFile");
22
+ const run = () => __awaiter(void 0, void 0, void 0, function* () {
23
+ const args = (0, minimist_1.default)(process.argv.slice(2), options_1.flags);
24
+ if (args.version) {
25
+ (0, printVersion_1.printVersion)();
26
+ return;
27
+ }
28
+ if (args.help) {
29
+ (0, printHelp_1.printHelp)();
30
+ return;
31
+ }
32
+ let config = default_1.defaultConfig;
33
+ if (args.config) {
34
+ config = Object.assign(Object.assign({}, default_1.defaultConfig), (yield (0, readConfigFile_1.readConfigFile)(args.config)));
35
+ }
36
+ yield (0, printMarkdown_1.printMarkdown)(config);
37
+ });
38
+ run();
@@ -0,0 +1,8 @@
1
+ /// <reference types="node" />
2
+ import { exec } from 'child_process';
3
+ import { readFile, writeFile } from 'fs';
4
+ declare const execAsync: typeof exec.__promisify__;
5
+ declare const writeFileAsync: typeof writeFile.__promisify__;
6
+ declare const readFileAsync: typeof readFile.__promisify__;
7
+ declare const outputFileAsync: (path: string, contents: string) => Promise<void>;
8
+ export { execAsync, writeFileAsync, readFileAsync, outputFileAsync };
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.outputFileAsync = exports.readFileAsync = exports.writeFileAsync = exports.execAsync = void 0;
13
+ const child_process_1 = require("child_process");
14
+ const fs_1 = require("fs");
15
+ const path_1 = require("path");
16
+ const util_1 = require("util");
17
+ const execAsync = (0, util_1.promisify)(child_process_1.exec);
18
+ exports.execAsync = execAsync;
19
+ const writeFileAsync = (0, util_1.promisify)(fs_1.writeFile);
20
+ exports.writeFileAsync = writeFileAsync;
21
+ const readFileAsync = (0, util_1.promisify)(fs_1.readFile);
22
+ exports.readFileAsync = readFileAsync;
23
+ const mkdirAsync = (0, util_1.promisify)(fs_1.mkdir);
24
+ const outputFileAsync = (path, contents) => __awaiter(void 0, void 0, void 0, function* () {
25
+ yield mkdirAsync((0, path_1.dirname)(path), { recursive: true });
26
+ yield writeFileAsync(path, contents);
27
+ });
28
+ exports.outputFileAsync = outputFileAsync;
@@ -0,0 +1,6 @@
1
+ declare const defaultConfig: {
2
+ outputFilename: string;
3
+ title: string;
4
+ description: string;
5
+ };
6
+ export { defaultConfig };
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultConfig = void 0;
4
+ const defaultConfig = {
5
+ outputFilename: 'CHANGELOG.md',
6
+ title: 'Changelog',
7
+ description: 'All notable changes to this project will be documented in this file. Dates are displayed in UTC.',
8
+ };
9
+ exports.defaultConfig = defaultConfig;
@@ -0,0 +1,8 @@
1
+ import { Commit } from '../models';
2
+ declare const groupCommitsByTags: (blacklistPattern: string | undefined) => Promise<{
3
+ commits: Commit[];
4
+ previousTag: string;
5
+ tag: string;
6
+ date: Date;
7
+ }[]>;
8
+ export { groupCommitsByTags };
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __asyncValues = (this && this.__asyncValues) || function (o) {
12
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
13
+ var m = o[Symbol.asyncIterator], i;
14
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
15
+ function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
16
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
17
+ };
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.groupCommitsByTags = void 0;
20
+ const async_1 = require("./async");
21
+ const getReleaseTags = () => __awaiter(void 0, void 0, void 0, function* () {
22
+ const command = `git tag -l --sort=-creatordate --format="%(creatordate:short),%(refname:short)"`;
23
+ const result = yield (0, async_1.execAsync)(command);
24
+ return result.stdout
25
+ .split('\n')
26
+ .filter((tag) => !!tag)
27
+ .map((tag) => {
28
+ const value = tag.split(',');
29
+ return {
30
+ creatorDate: value[0],
31
+ tag: value[1],
32
+ };
33
+ });
34
+ });
35
+ const getReleaseCommits = (toTag, fromTag, blacklistPattern) => __awaiter(void 0, void 0, void 0, function* () {
36
+ const separator = '_||_';
37
+ const command = `git log ${fromTag}..${toTag} --no-merges --pretty=format:"%ad${separator}%h${separator}%ae${separator}%s"`;
38
+ const logResult = yield (0, async_1.execAsync)(command);
39
+ return logResult.stdout
40
+ .split('\n')
41
+ .filter((message) => !!message)
42
+ .map((message) => {
43
+ const data = message.split(separator);
44
+ return {
45
+ date: new Date(data[0]),
46
+ hash: data[1],
47
+ author: data[2],
48
+ subject: data[3],
49
+ };
50
+ })
51
+ .filter((commit) => {
52
+ if (!blacklistPattern) {
53
+ return true;
54
+ }
55
+ return !new RegExp(blacklistPattern, 'gm').test(commit.subject);
56
+ });
57
+ });
58
+ const groupCommitsByTags = (blacklistPattern) => __awaiter(void 0, void 0, void 0, function* () {
59
+ var e_1, _a;
60
+ const releaseCommits = [];
61
+ const headTag = {
62
+ creatorDate: new Date().toISOString().slice(0, 10),
63
+ tag: 'HEAD',
64
+ };
65
+ const allTags = [headTag, ...(yield getReleaseTags())];
66
+ try {
67
+ for (var _b = __asyncValues(allTags.slice(0, -1).entries()), _c; _c = yield _b.next(), !_c.done;) {
68
+ const [index, value] = _c.value;
69
+ const previousTag = allTags[index + 1].tag;
70
+ const commits = yield getReleaseCommits(value.tag, previousTag, blacklistPattern);
71
+ releaseCommits.push({
72
+ commits,
73
+ previousTag,
74
+ tag: value.tag,
75
+ date: new Date(value.creatorDate),
76
+ });
77
+ }
78
+ }
79
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
80
+ finally {
81
+ try {
82
+ if (_c && !_c.done && (_a = _b.return)) yield _a.call(_b);
83
+ }
84
+ finally { if (e_1) throw e_1.error; }
85
+ }
86
+ return releaseCommits;
87
+ });
88
+ exports.groupCommitsByTags = groupCommitsByTags;
@@ -0,0 +1,8 @@
1
+ import { Config } from '../models';
2
+ /**
3
+ * Returns a changelog formatted in Markdown syntax
4
+ * @param config Config
5
+ * @returns Text in Markdown syntax
6
+ */
7
+ declare const createMarkdown: (config?: Config | undefined) => Promise<string>;
8
+ export { createMarkdown };
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.createMarkdown = void 0;
13
+ const default_1 = require("./default");
14
+ const git_1 = require("./git");
15
+ const createLink = (linkText, url) => {
16
+ return `[${linkText}](${url})`;
17
+ };
18
+ const formatDate = (date) => {
19
+ return date.toLocaleString('en', {
20
+ month: 'long',
21
+ day: 'numeric',
22
+ year: 'numeric',
23
+ });
24
+ };
25
+ const ticketRecognition = (commitMessage) => {
26
+ var _a, _b;
27
+ return (_b = (_a = commitMessage.match(/\((?<ticket>#\d+)\)/)) === null || _a === void 0 ? void 0 : _a.groups) === null || _b === void 0 ? void 0 : _b.ticket;
28
+ };
29
+ const createReleaseSubtitle = (group, repository) => {
30
+ const latestTag = 'v' + process.env.npm_package_version;
31
+ const latestVersion = latestTag === group.previousTag ? 'Unreleased changes' : latestTag;
32
+ const subtitleLinkText = group.tag === 'HEAD' ? latestVersion : group.tag;
33
+ const subtitleLink = `${repository}/compare/${group.previousTag}...${group.tag}`;
34
+ const subtitle = `${createLink(subtitleLinkText, subtitleLink)}`;
35
+ return `#### ${repository ? subtitle : subtitleLinkText}`;
36
+ };
37
+ const createDateInformation = (group) => {
38
+ return `> ${formatDate(group.date)}`;
39
+ };
40
+ const createCommitList = (group, repository) => {
41
+ return group.commits.reduce((result, commit) => {
42
+ const ticket = ticketRecognition(commit.subject);
43
+ let reference = '';
44
+ if (ticket) {
45
+ commit.subject = commit.subject.replace(`(${ticket})`, ''); // remove ticket number
46
+ const ticketLinkText = `\`${ticket}\``;
47
+ reference = repository
48
+ ? createLink(ticketLinkText, `${repository}/pull/${ticket.slice(1)}`)
49
+ : ticketLinkText;
50
+ }
51
+ else {
52
+ const commitHashText = `\`${commit.hash}\``;
53
+ reference = repository
54
+ ? createLink(commitHashText, `${repository}/commit/${commit.hash}`)
55
+ : commitHashText;
56
+ }
57
+ return (result +
58
+ `- ${commit.subject.replace(/[<<]/, '&lt;').trim()} ${reference}\n`);
59
+ }, '');
60
+ };
61
+ /**
62
+ * Returns a changelog formatted in Markdown syntax
63
+ * @param config Config
64
+ * @returns Text in Markdown syntax
65
+ */
66
+ const createMarkdown = (config) => __awaiter(void 0, void 0, void 0, function* () {
67
+ var _a, _b;
68
+ const title = `### ${(_a = config === null || config === void 0 ? void 0 : config.title) !== null && _a !== void 0 ? _a : default_1.defaultConfig.title} \n\n ${(_b = config === null || config === void 0 ? void 0 : config.description) !== null && _b !== void 0 ? _b : default_1.defaultConfig.description}\n\n`;
69
+ const tagGroups = yield (0, git_1.groupCommitsByTags)(config === null || config === void 0 ? void 0 : config.blacklistPattern);
70
+ return (title +
71
+ tagGroups.reduce((markdown, group) => {
72
+ const subtitle = createReleaseSubtitle(group, config === null || config === void 0 ? void 0 : config.repositoryUrl);
73
+ const date = createDateInformation(group);
74
+ const commitList = createCommitList(group, config === null || config === void 0 ? void 0 : config.repositoryUrl);
75
+ return `${markdown} \n${subtitle} \n\n${date} \n\n${commitList}`;
76
+ }, ''));
77
+ });
78
+ exports.createMarkdown = createMarkdown;
@@ -0,0 +1,6 @@
1
+ import { MockedFunction } from 'ts-jest/dist/utils/testing';
2
+ export declare const createExecAsyncMock: () => MockedFunction<() => Promise<{
3
+ stdout: string;
4
+ stderr: string;
5
+ }>>;
6
+ export declare const mockNewDateTime: () => void;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mockNewDateTime = exports.createExecAsyncMock = void 0;
4
+ const jest_mock_1 = require("jest-mock");
5
+ const async_1 = require("./async");
6
+ const createExecAsyncMock = () => {
7
+ const mockExecAsync = (0, jest_mock_1.mocked)(async_1.execAsync);
8
+ return mockExecAsync;
9
+ };
10
+ exports.createExecAsyncMock = createExecAsyncMock;
11
+ const mockNewDateTime = () => {
12
+ jest.useFakeTimers().setSystemTime(new Date('2022-02-08').getTime());
13
+ };
14
+ exports.mockNewDateTime = mockNewDateTime;
package/lib/index.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './core/markdown';
package/lib/index.js ADDED
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
10
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ __exportStar(require("./core/markdown"), exports);
@@ -0,0 +1,6 @@
1
+ export interface Commit {
2
+ date: Date;
3
+ hash: string;
4
+ author: string;
5
+ subject: string;
6
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,30 @@
1
+ export interface Config {
2
+ /**
3
+ * Name of the file in which the output should be written. Can also include a path name.
4
+ * @default `CHANGELOG.md`
5
+ * @optional
6
+ */
7
+ filePath?: string;
8
+ /**
9
+ * Title of the page
10
+ * @default `Changelog`
11
+ * @optional
12
+ */
13
+ title?: string;
14
+ /**
15
+ * Description of the page
16
+ * @default `All notable changes to this project will be documented in this file. Dates are displayed in UTC.`
17
+ * @optional
18
+ */
19
+ description?: string;
20
+ /**
21
+ * URL of the repository
22
+ * @optional If not set, no links will be provided.
23
+ */
24
+ repositoryUrl?: string;
25
+ /**
26
+ * Regular expression pattern to exclude commit messages
27
+ * @optional
28
+ */
29
+ blacklistPattern?: string;
30
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,3 @@
1
+ export * from './commit';
2
+ export * from './config';
3
+ export * from './tagGroup';
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
10
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ __exportStar(require("./commit"), exports);
14
+ __exportStar(require("./config"), exports);
15
+ __exportStar(require("./tagGroup"), exports);
@@ -0,0 +1,7 @@
1
+ import { Commit } from './commit';
2
+ export interface TagGroup {
3
+ commits: Commit[];
4
+ previousTag: string;
5
+ tag: string;
6
+ date: Date;
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "changelog-machine",
3
+ "version": "1.0.0",
4
+ "description": "Changelog generator based on Git commit messages and tags",
5
+ "main": "./lib/index.js",
6
+ "module": "./lib/index.js",
7
+ "bin": {
8
+ "changelog-machine": "./bin/cli.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc -p tsconfig.json",
12
+ "test": "jest",
13
+ "lint": "eslint -c .eslintrc.json --ext .ts ./src/**/*.ts",
14
+ "changelog": "ts-node src/cli/index.ts --config changelog.config.json",
15
+ "prepublish": "npm run build",
16
+ "version": "npm run changelog && git add CHANGELOG.md"
17
+ },
18
+ "files": [
19
+ "lib/"
20
+ ],
21
+ "keywords": [
22
+ "Changelog",
23
+ "Generator"
24
+ ],
25
+ "engines": {
26
+ "node": ">=4.2.0"
27
+ },
28
+ "author": "Philipp Kief",
29
+ "license": "MIT",
30
+ "devDependencies": {
31
+ "@types/jest": "^27.4.0",
32
+ "@types/minimist": "^1.2.2",
33
+ "@typescript-eslint/eslint-plugin": "^5.4.0",
34
+ "@typescript-eslint/parser": "^5.4.0",
35
+ "eslint": "^8.3.0",
36
+ "eslint-config-prettier": "^8.3.0",
37
+ "eslint-plugin-prettier": "^4.0.0",
38
+ "jest": "^27.5.0",
39
+ "ts-jest": "^27.1.3",
40
+ "ts-node": "^10.4.0",
41
+ "typescript": "^4.5.5"
42
+ },
43
+ "dependencies": {
44
+ "minimist": "^1.2.5"
45
+ }
46
+ }