keep-a-changelog 0.10.3 → 2.0.1

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.
Files changed (92) hide show
  1. package/CHANGELOG.md +13 -185
  2. package/LICENSE +1 -1
  3. package/README.md +93 -63
  4. package/esm/_dnt.shims.js +62 -0
  5. package/esm/bin.js +114 -0
  6. package/esm/deps/deno_land/std_0.120.0/_util/assert.js +13 -0
  7. package/esm/deps/deno_land/std_0.120.0/_util/os.js +15 -0
  8. package/esm/deps/deno_land/std_0.120.0/flags/mod.js +255 -0
  9. package/esm/deps/deno_land/std_0.120.0/path/_constants.js +45 -0
  10. package/esm/deps/deno_land/std_0.120.0/path/_interface.js +3 -0
  11. package/esm/deps/deno_land/std_0.120.0/path/_util.js +114 -0
  12. package/esm/deps/deno_land/std_0.120.0/path/common.js +36 -0
  13. package/esm/deps/deno_land/std_0.120.0/path/glob.js +361 -0
  14. package/esm/deps/deno_land/std_0.120.0/path/mod.js +14 -0
  15. package/esm/deps/deno_land/std_0.120.0/path/posix.js +493 -0
  16. package/esm/deps/deno_land/std_0.120.0/path/separator.js +5 -0
  17. package/esm/deps/deno_land/std_0.120.0/path/win32.js +963 -0
  18. package/esm/deps/deno_land/std_0.51.0/fs/eol.js +29 -0
  19. package/esm/deps/deno_land/x/ini_v2.1.0/ini.js +226 -0
  20. package/esm/deps/deno_land/x/ini_v2.1.0/mod.js +1 -0
  21. package/esm/deps/deno_land/x/semver_v1.4.0/mod.js +1527 -0
  22. package/esm/mod.js +5 -0
  23. package/esm/package.json +3 -0
  24. package/esm/src/Change.js +48 -0
  25. package/esm/src/Changelog.js +137 -0
  26. package/esm/src/Release.js +204 -0
  27. package/esm/src/deps.js +1 -0
  28. package/esm/src/parser.js +159 -0
  29. package/esm/test/changelog.custom.type.md +24 -0
  30. package/esm/test/changelog.expected.md +169 -0
  31. package/esm/test/changelog.md +200 -0
  32. package/esm/test/empty.expected.md +6 -0
  33. package/package.json +26 -24
  34. package/types/_dnt.shims.d.ts +9 -0
  35. package/types/bin.d.ts +2 -0
  36. package/types/deps/deno_land/std_0.120.0/_util/assert.d.ts +5 -0
  37. package/types/deps/deno_land/std_0.120.0/_util/os.d.ts +3 -0
  38. package/types/deps/deno_land/std_0.120.0/flags/mod.d.ts +50 -0
  39. package/types/deps/deno_land/std_0.120.0/path/_constants.d.ts +39 -0
  40. package/types/deps/deno_land/std_0.120.0/path/_interface.d.ts +26 -0
  41. package/types/deps/deno_land/std_0.120.0/path/_util.d.ts +8 -0
  42. package/types/deps/deno_land/std_0.120.0/path/common.d.ts +13 -0
  43. package/types/deps/deno_land/std_0.120.0/path/glob.d.ts +78 -0
  44. package/types/deps/deno_land/std_0.120.0/path/mod.d.ts +9 -0
  45. package/types/deps/deno_land/std_0.120.0/path/posix.d.ts +80 -0
  46. package/types/deps/deno_land/std_0.120.0/path/separator.d.ts +2 -0
  47. package/types/deps/deno_land/std_0.120.0/path/win32.d.ts +87 -0
  48. package/types/deps/deno_land/std_0.51.0/fs/eol.d.ts +12 -0
  49. package/types/deps/deno_land/x/ini_v2.1.0/ini.d.ts +53 -0
  50. package/types/deps/deno_land/x/ini_v2.1.0/mod.d.ts +1 -0
  51. package/types/deps/deno_land/x/semver_v1.4.0/mod.d.ts +116 -0
  52. package/types/mod.d.ts +5 -0
  53. package/types/src/Change.d.ts +8 -0
  54. package/types/src/Changelog.d.ts +18 -0
  55. package/types/src/Release.d.ts +25 -0
  56. package/types/src/deps.d.ts +1 -0
  57. package/types/src/parser.d.ts +11 -0
  58. package/umd/_dnt.shims.js +76 -0
  59. package/umd/bin.js +145 -0
  60. package/umd/deps/deno_land/std_0.120.0/_util/assert.js +28 -0
  61. package/umd/deps/deno_land/std_0.120.0/_util/os.js +47 -0
  62. package/umd/deps/deno_land/std_0.120.0/flags/mod.js +269 -0
  63. package/umd/deps/deno_land/std_0.120.0/path/_constants.js +58 -0
  64. package/umd/deps/deno_land/std_0.120.0/path/_interface.js +14 -0
  65. package/umd/deps/deno_land/std_0.120.0/path/_util.js +134 -0
  66. package/umd/deps/deno_land/std_0.120.0/path/common.js +50 -0
  67. package/umd/deps/deno_land/std_0.120.0/path/glob.js +397 -0
  68. package/umd/deps/deno_land/std_0.120.0/path/mod.js +51 -0
  69. package/umd/deps/deno_land/std_0.120.0/path/posix.js +538 -0
  70. package/umd/deps/deno_land/std_0.120.0/path/separator.js +18 -0
  71. package/umd/deps/deno_land/std_0.120.0/path/win32.js +1008 -0
  72. package/umd/deps/deno_land/std_0.51.0/fs/eol.js +44 -0
  73. package/umd/deps/deno_land/x/ini_v2.1.0/ini.js +262 -0
  74. package/umd/deps/deno_land/x/ini_v2.1.0/mod.js +23 -0
  75. package/umd/deps/deno_land/x/semver_v1.4.0/mod.js +1578 -0
  76. package/umd/mod.js +24 -0
  77. package/umd/package.json +3 -0
  78. package/umd/src/Change.js +61 -0
  79. package/umd/src/Changelog.js +150 -0
  80. package/umd/src/Release.js +220 -0
  81. package/umd/src/deps.js +19 -0
  82. package/umd/src/parser.js +175 -0
  83. package/umd/test/changelog.custom.type.md +24 -0
  84. package/umd/test/changelog.expected.md +169 -0
  85. package/umd/test/changelog.md +200 -0
  86. package/umd/test/empty.expected.md +6 -0
  87. package/bin.js +0 -114
  88. package/src/Change.js +0 -40
  89. package/src/Changelog.js +0 -121
  90. package/src/Release.js +0 -220
  91. package/src/index.js +0 -6
  92. package/src/parser.js +0 -182
package/esm/mod.js ADDED
@@ -0,0 +1,5 @@
1
+ import parser from "./src/parser.js";
2
+ import Change from "./src/Change.js";
3
+ import Changelog from "./src/Changelog.js";
4
+ import Release from "./src/Release.js";
5
+ export { Change, Changelog, parser, Release };
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "module"
3
+ }
@@ -0,0 +1,48 @@
1
+ export default class Change {
2
+ constructor(title, description = "") {
3
+ Object.defineProperty(this, "title", {
4
+ enumerable: true,
5
+ configurable: true,
6
+ writable: true,
7
+ value: void 0
8
+ });
9
+ Object.defineProperty(this, "description", {
10
+ enumerable: true,
11
+ configurable: true,
12
+ writable: true,
13
+ value: void 0
14
+ });
15
+ Object.defineProperty(this, "issues", {
16
+ enumerable: true,
17
+ configurable: true,
18
+ writable: true,
19
+ value: []
20
+ });
21
+ this.title = Change.extractIssues(title, this.issues);
22
+ this.description = Change.extractIssues(description, this.issues);
23
+ }
24
+ static extractIssues(text, issues) {
25
+ return text
26
+ .replace(/(^|[^\\])\[#(\d+)\](?=[^\(]|$)/g, (_, start, index) => {
27
+ if (!issues.includes(index)) {
28
+ issues.push(index);
29
+ }
30
+ return `${start}[#${index}]`;
31
+ })
32
+ .replace(/(^|[\s,])#(\d+)(?=[\s,\.]|$)/g, (_, start, index) => {
33
+ if (!issues.includes(index)) {
34
+ issues.push(index);
35
+ }
36
+ return `${start}[#${index}]`;
37
+ });
38
+ }
39
+ toString() {
40
+ let t = this.title.split("\n").map((line) => ` ${line}`.trimEnd());
41
+ t[0] = "-" + t[0].substr(1);
42
+ if (this.description) {
43
+ t.push("");
44
+ t = t.concat(this.description.split("\n").map((line) => ` ${line}`.trimEnd()));
45
+ }
46
+ return t.join("\n").trim();
47
+ }
48
+ }
@@ -0,0 +1,137 @@
1
+ import { eq } from "./deps.js";
2
+ export default class Changelog {
3
+ constructor(title, description = "") {
4
+ Object.defineProperty(this, "flag", {
5
+ enumerable: true,
6
+ configurable: true,
7
+ writable: true,
8
+ value: void 0
9
+ });
10
+ Object.defineProperty(this, "title", {
11
+ enumerable: true,
12
+ configurable: true,
13
+ writable: true,
14
+ value: void 0
15
+ });
16
+ Object.defineProperty(this, "description", {
17
+ enumerable: true,
18
+ configurable: true,
19
+ writable: true,
20
+ value: void 0
21
+ });
22
+ Object.defineProperty(this, "head", {
23
+ enumerable: true,
24
+ configurable: true,
25
+ writable: true,
26
+ value: "HEAD"
27
+ });
28
+ Object.defineProperty(this, "footer", {
29
+ enumerable: true,
30
+ configurable: true,
31
+ writable: true,
32
+ value: void 0
33
+ });
34
+ Object.defineProperty(this, "url", {
35
+ enumerable: true,
36
+ configurable: true,
37
+ writable: true,
38
+ value: void 0
39
+ });
40
+ Object.defineProperty(this, "releases", {
41
+ enumerable: true,
42
+ configurable: true,
43
+ writable: true,
44
+ value: []
45
+ });
46
+ Object.defineProperty(this, "tagNameBuilder", {
47
+ enumerable: true,
48
+ configurable: true,
49
+ writable: true,
50
+ value: void 0
51
+ });
52
+ this.title = title;
53
+ this.description = description;
54
+ }
55
+ addRelease(release) {
56
+ this.releases.push(release);
57
+ this.sortReleases();
58
+ release.changelog = this;
59
+ return this;
60
+ }
61
+ findRelease(version) {
62
+ if (!version) {
63
+ return this.releases.find((release) => !release.version);
64
+ }
65
+ return this.releases.find((release) => release.version && eq(release.version, version));
66
+ }
67
+ sortReleases() {
68
+ this.releases.sort((a, b) => a.compare(b));
69
+ }
70
+ tagName(release) {
71
+ if (this.tagNameBuilder) {
72
+ return this.tagNameBuilder(release);
73
+ }
74
+ return `v${release.version}`;
75
+ }
76
+ toString() {
77
+ const t = [];
78
+ if (this.flag) {
79
+ t.push(`<!-- ${this.flag} -->`);
80
+ t.push("");
81
+ }
82
+ t.push(`# ${this.title}`);
83
+ const links = [];
84
+ const compareLinks = [];
85
+ const description = this.description.trim() ||
86
+ `All notable changes to this project will be documented in this file.
87
+
88
+ The format is based on [Keep a Changelog](http://keepachangelog.com/)
89
+ and this project adheres to [Semantic Versioning](http://semver.org/).`;
90
+ if (description) {
91
+ t.push("");
92
+ t.push(description);
93
+ }
94
+ this.releases.forEach((release) => {
95
+ t.push("");
96
+ t.push(release.toString(this));
97
+ release.getLinks(this).forEach((link) => {
98
+ if (!links.includes(link)) {
99
+ links.push(link);
100
+ }
101
+ });
102
+ const compareLink = release.getCompareLink(this);
103
+ if (compareLink) {
104
+ compareLinks.push(compareLink);
105
+ }
106
+ });
107
+ if (links.length) {
108
+ t.push("");
109
+ links.sort(compare);
110
+ links.forEach((link) => t.push(link));
111
+ }
112
+ if (compareLinks.length) {
113
+ t.push("");
114
+ compareLinks.forEach((link) => t.push(link));
115
+ }
116
+ t.push("");
117
+ if (this.footer) {
118
+ t.push("---");
119
+ t.push("");
120
+ t.push(this.footer);
121
+ t.push("");
122
+ }
123
+ return t.join("\n");
124
+ }
125
+ }
126
+ function compare(a, b) {
127
+ if (a === b) {
128
+ return 0;
129
+ }
130
+ const reg = /^\[#(\d+)\]:/;
131
+ const aNumber = a.match(reg);
132
+ const bNumber = b.match(reg);
133
+ if (aNumber && bNumber) {
134
+ return parseInt(aNumber[1]) - parseInt(bNumber[1]);
135
+ }
136
+ return a < b ? -1 : 1;
137
+ }
@@ -0,0 +1,204 @@
1
+ import { Semver } from "./deps.js";
2
+ import Change from "./Change.js";
3
+ export default class Release {
4
+ constructor(version, date, description = "") {
5
+ Object.defineProperty(this, "changelog", {
6
+ enumerable: true,
7
+ configurable: true,
8
+ writable: true,
9
+ value: void 0
10
+ });
11
+ Object.defineProperty(this, "version", {
12
+ enumerable: true,
13
+ configurable: true,
14
+ writable: true,
15
+ value: void 0
16
+ });
17
+ Object.defineProperty(this, "date", {
18
+ enumerable: true,
19
+ configurable: true,
20
+ writable: true,
21
+ value: void 0
22
+ });
23
+ Object.defineProperty(this, "description", {
24
+ enumerable: true,
25
+ configurable: true,
26
+ writable: true,
27
+ value: void 0
28
+ });
29
+ Object.defineProperty(this, "changes", {
30
+ enumerable: true,
31
+ configurable: true,
32
+ writable: true,
33
+ value: void 0
34
+ });
35
+ this.setVersion(version);
36
+ this.setDate(date);
37
+ this.description = description;
38
+ this.changes = new Map([
39
+ ["added", []],
40
+ ["changed", []],
41
+ ["deprecated", []],
42
+ ["removed", []],
43
+ ["fixed", []],
44
+ ["security", []],
45
+ ]);
46
+ }
47
+ compare(release) {
48
+ if (!this.version && release.version) {
49
+ return -1;
50
+ }
51
+ if (!release.version) {
52
+ return 1;
53
+ }
54
+ if (!this.date && release.date) {
55
+ return -1;
56
+ }
57
+ if (!release.date) {
58
+ return 1;
59
+ }
60
+ if (this.version && release.version) {
61
+ return -this.version.compare(release.version);
62
+ }
63
+ return 0;
64
+ }
65
+ isEmpty() {
66
+ if (this.description.trim()) {
67
+ return false;
68
+ }
69
+ return Array.from(this.changes.values()).every((change) => !change.length);
70
+ }
71
+ setVersion(version) {
72
+ if (typeof version === "string") {
73
+ version = new Semver(version);
74
+ }
75
+ this.version = version;
76
+ //Re-sort the releases of the parent changelog
77
+ if (this.changelog) {
78
+ this.changelog.sortReleases();
79
+ }
80
+ }
81
+ setDate(date) {
82
+ if (typeof date === "string") {
83
+ date = new Date(date);
84
+ }
85
+ this.date = date;
86
+ }
87
+ addChange(type, change) {
88
+ if (!(change instanceof Change)) {
89
+ change = new Change(change);
90
+ }
91
+ if (!this.changes.has(type)) {
92
+ throw new Error("Invalid change type");
93
+ }
94
+ this.changes.get(type).push(change);
95
+ return this;
96
+ }
97
+ added(change) {
98
+ return this.addChange("added", change);
99
+ }
100
+ changed(change) {
101
+ return this.addChange("changed", change);
102
+ }
103
+ deprecated(change) {
104
+ return this.addChange("deprecated", change);
105
+ }
106
+ removed(change) {
107
+ return this.addChange("removed", change);
108
+ }
109
+ fixed(change) {
110
+ return this.addChange("fixed", change);
111
+ }
112
+ security(change) {
113
+ return this.addChange("security", change);
114
+ }
115
+ toString(changelog) {
116
+ let t = [];
117
+ const hasCompareLink = this.getCompareLink(changelog) !== undefined;
118
+ if (this.version) {
119
+ if (hasCompareLink) {
120
+ t.push(`## [${this.version}] - ${formatDate(this.date)}`);
121
+ }
122
+ else {
123
+ t.push(`## ${this.version} - ${formatDate(this.date)}`);
124
+ }
125
+ }
126
+ else {
127
+ if (hasCompareLink) {
128
+ t.push("## [Unreleased]");
129
+ }
130
+ else {
131
+ t.push("## Unreleased");
132
+ }
133
+ }
134
+ if (this.description.trim()) {
135
+ t.push(this.description.trim());
136
+ t.push("");
137
+ }
138
+ this.changes.forEach((changes, type) => {
139
+ if (changes.length) {
140
+ t.push(`### ${type[0].toUpperCase()}${type.substring(1)}`);
141
+ t = t.concat(changes.map((change) => change.toString()));
142
+ t.push("");
143
+ }
144
+ });
145
+ return t.join("\n").trim();
146
+ }
147
+ getCompareLink(changelog) {
148
+ if (!changelog?.url) {
149
+ return;
150
+ }
151
+ const index = changelog.releases.indexOf(this);
152
+ if (index === -1) {
153
+ return;
154
+ }
155
+ let offset = 1;
156
+ let previous = changelog.releases[index + offset];
157
+ while (previous && !previous.date) {
158
+ ++offset;
159
+ previous = changelog.releases[index + offset];
160
+ }
161
+ if (!previous) {
162
+ if (!this.version || !this.date) {
163
+ return;
164
+ }
165
+ return `[${this.version}]: ${changelog.url}/releases/tag/${changelog.tagName(this)}`;
166
+ }
167
+ if (!this.version) {
168
+ return `[Unreleased]: ${changelog.url}/compare/${changelog.tagName(previous)}...${changelog.head}`;
169
+ }
170
+ if (!this.date) {
171
+ return `[${this.version}]: ${changelog.url}/compare/${changelog.tagName(previous)}...${changelog.head}`;
172
+ }
173
+ return `[${this.version}]: ${changelog.url}/compare/${changelog.tagName(previous)}...${changelog.tagName(this)}`;
174
+ }
175
+ getLinks(changelog) {
176
+ const links = [];
177
+ if (!changelog.url) {
178
+ return links;
179
+ }
180
+ this.changes.forEach((changes) => changes.forEach((change) => {
181
+ change.issues.forEach((issue) => {
182
+ if (!links.includes(issue)) {
183
+ links.push(`[#${issue}]: ${changelog.url}/issues/${issue}`);
184
+ }
185
+ });
186
+ }));
187
+ return links;
188
+ }
189
+ }
190
+ function formatDate(date) {
191
+ if (!date) {
192
+ return "Unreleased";
193
+ }
194
+ const year = date.getUTCFullYear();
195
+ let month = date.getUTCMonth() + 1;
196
+ let day = date.getUTCDate();
197
+ if (month < 10) {
198
+ month = "0" + month;
199
+ }
200
+ if (day < 10) {
201
+ day = "0" + day;
202
+ }
203
+ return `${year}-${month}-${day}`;
204
+ }
@@ -0,0 +1 @@
1
+ export { default as Semver, eq, } from "../deps/deno_land/x/semver_v1.4.0/mod.js";
@@ -0,0 +1,159 @@
1
+ import Changelog from "./Changelog.js";
2
+ import Release from "./Release.js";
3
+ const defaultOptions = {
4
+ releaseCreator: (version, date, description) => new Release(version, date, description),
5
+ };
6
+ /** Parse a markdown string */
7
+ export default function parser(markdown, options) {
8
+ const opts = Object.assign({}, defaultOptions, options);
9
+ const tokens = tokenize(markdown);
10
+ try {
11
+ return processTokens(tokens, opts);
12
+ }
13
+ catch (error) {
14
+ throw new Error(`Parse error in the line ${tokens[0][0]}: ${error.message}`);
15
+ }
16
+ }
17
+ /** Process an array of tokens to build the Changelog */
18
+ function processTokens(tokens, opts) {
19
+ const changelog = new Changelog("");
20
+ changelog.flag = getContent(tokens, "flag");
21
+ changelog.title = getContent(tokens, "h1", true);
22
+ changelog.description = getContent(tokens, "p");
23
+ //Releases
24
+ let release;
25
+ while ((release = getContent(tokens, "h2").toLowerCase())) {
26
+ const matches = release.match(/\[?([^\]]+)\]?\s*-\s*([\d]{4}-[\d]{1,2}-[\d]{1,2})$/);
27
+ if (matches) {
28
+ release = opts.releaseCreator(matches[1], matches[2]);
29
+ }
30
+ else if (release.includes("unreleased")) {
31
+ const matches = release.match(/\[?([^\]]+)\]?\s*-\s*unreleased$/);
32
+ release = matches
33
+ ? opts.releaseCreator(matches[1])
34
+ : opts.releaseCreator();
35
+ }
36
+ else {
37
+ throw new Error(`Syntax error in the release title`);
38
+ }
39
+ changelog.addRelease(release);
40
+ release.description = getContent(tokens, "p");
41
+ let type;
42
+ while ((type = getContent(tokens, "h3").toLowerCase())) {
43
+ let change;
44
+ while ((change = getContent(tokens, "li"))) {
45
+ release.addChange(type, change);
46
+ }
47
+ }
48
+ }
49
+ //Skip release links
50
+ let link = getContent(tokens, "link");
51
+ while (link) {
52
+ if (!changelog.url) {
53
+ const matches = link.match(/^\[.*\]\:\s*(http.*)\/compare\/.*$/);
54
+ if (matches) {
55
+ changelog.url = matches[1];
56
+ }
57
+ }
58
+ link = getContent(tokens, "link");
59
+ }
60
+ //Footer
61
+ if (getContent(tokens, "hr")) {
62
+ changelog.footer = getContent(tokens, "p");
63
+ }
64
+ if (tokens.length) {
65
+ throw new Error(`Unexpected content ${JSON.stringify(tokens)}`);
66
+ }
67
+ return changelog;
68
+ }
69
+ /** Returns the content of a token */
70
+ function getContent(tokens, type, required = false) {
71
+ if (!tokens[0] || tokens[0][1] !== type) {
72
+ if (required) {
73
+ throw new Error(`Required token missing in: "${tokens[0][0]}"`);
74
+ }
75
+ return "";
76
+ }
77
+ return tokens.shift()[2].join("\n");
78
+ }
79
+ /** Tokenize a markdown string */
80
+ function tokenize(markdown) {
81
+ const tokens = [];
82
+ markdown
83
+ .trim()
84
+ .split("\n")
85
+ .map((line, index, allLines) => {
86
+ const lineNumber = index + 1;
87
+ if (line.startsWith("---")) {
88
+ return [lineNumber, "hr", ["-"]];
89
+ }
90
+ if (line.startsWith("# ")) {
91
+ return [lineNumber, "h1", [line.substr(1).trim()]];
92
+ }
93
+ if (line.startsWith("## ")) {
94
+ return [lineNumber, "h2", [line.substr(2).trim()]];
95
+ }
96
+ if (line.startsWith("### ")) {
97
+ return [lineNumber, "h3", [line.substr(3).trim()]];
98
+ }
99
+ if (line.startsWith("-")) {
100
+ return [lineNumber, "li", [line.substr(1).trim()]];
101
+ }
102
+ if (line.startsWith("*")) {
103
+ return [lineNumber, "li", [line.substr(1).trim()]];
104
+ }
105
+ if (line.match(/^\[.*\]\:\s*http.*$/)) {
106
+ return [lineNumber, "link", [line.trim()]];
107
+ }
108
+ if (line.match(/^\[.*\]\:$/)) {
109
+ const nextLine = allLines[index + 1];
110
+ if (nextLine && nextLine.match(/\s+http.*$/)) {
111
+ // We found a multi-line link: treat it like a single line
112
+ allLines[index + 1] = "";
113
+ return [lineNumber, "link", [
114
+ line.trim() + "\n" + nextLine.trimEnd(),
115
+ ]];
116
+ }
117
+ }
118
+ const result = line.match(/^<!--(.*)-->$/);
119
+ if (result) {
120
+ return [lineNumber, "flag", [result[1].trim()]];
121
+ }
122
+ return [lineNumber, "p", [line.trimEnd()]];
123
+ })
124
+ .forEach((line, index) => {
125
+ const [lineNumber, type, [content]] = line;
126
+ if (index > 0) {
127
+ const prevType = tokens[0][1];
128
+ if (type === "p") {
129
+ if (prevType === "p") {
130
+ return tokens[0][2].push(content);
131
+ }
132
+ if (prevType === "li") {
133
+ return tokens[0][2].push(content.replace(/^\s\s/, ""));
134
+ }
135
+ }
136
+ }
137
+ tokens.unshift([lineNumber, type, [content]]);
138
+ });
139
+ return tokens
140
+ .filter((token) => !isEmpty(token[2]))
141
+ .map((token) => {
142
+ const content = token[2];
143
+ while (isEmpty(content[content.length - 1])) {
144
+ content.pop();
145
+ }
146
+ while (isEmpty(content[0])) {
147
+ content.shift();
148
+ }
149
+ return token;
150
+ })
151
+ .reverse();
152
+ }
153
+ /** Check if a string or array is empty */
154
+ function isEmpty(val) {
155
+ if (Array.isArray(val)) {
156
+ val = val.join("");
157
+ }
158
+ return !val || val.trim() === "";
159
+ }
@@ -0,0 +1,24 @@
1
+ # Changelog - demo
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
6
+ and this project adheres to
7
+ [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
8
+
9
+ ## [Unreleased]
10
+ ### Maintenance
11
+ - upgrade
12
+ - fix vulnerabilities
13
+
14
+ ## [2.0.0] - 2020-02-07
15
+ ### Added
16
+ - custom release
17
+
18
+ ## [1.0.0] - 2020-02-06
19
+ ### Maintenance
20
+ - fix naming
21
+
22
+ [Unreleased]: https://github.com/olivierlacan/keep-a-changelog/compare/v2.0.0...HEAD
23
+ [2.0.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v1.0.0...v2.0.0
24
+ [1.0.0]: https://github.com/olivierlacan/keep-a-changelog/releases/tag/v1.0.0