@xrow/docusaurus-changelog 4.173.0 → 4.174.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/README.md +4 -0
- package/index.d.ts +11 -0
- package/index.js +151 -15
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,4 +20,8 @@ The CI Tools Docusaurus build image registers the component in Docusaurus
|
|
|
20
20
|
The feed is loaded in the browser, so the static Docusaurus build remains stable
|
|
21
21
|
even when the release feed is temporarily unavailable.
|
|
22
22
|
|
|
23
|
+
GitLab API descriptions produced by semantic-release are displayed as release
|
|
24
|
+
cards with their full categorized notes and commit links. Atom feeds fall back to
|
|
25
|
+
their summary because they do not expose the structured GitLab description.
|
|
26
|
+
|
|
23
27
|
The package is published to npmjs.com from ci-tools semver tag pipelines when `NPM_TOKEN` is configured.
|
package/index.d.ts
CHANGED
|
@@ -5,6 +5,15 @@ export interface ReleaseEntry {
|
|
|
5
5
|
href: string;
|
|
6
6
|
updated: string;
|
|
7
7
|
summary: string;
|
|
8
|
+
description: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface ReleaseNotes {
|
|
12
|
+
intro: string[];
|
|
13
|
+
sections: Array<{
|
|
14
|
+
title: string;
|
|
15
|
+
items: string[];
|
|
16
|
+
}>;
|
|
8
17
|
}
|
|
9
18
|
|
|
10
19
|
export interface ChangelogProps {
|
|
@@ -17,4 +26,6 @@ export function releasesFromAtomDocument(document: Document): ReleaseEntry[];
|
|
|
17
26
|
|
|
18
27
|
export function releasesFromGitLabApiResponse(releases: unknown[]): ReleaseEntry[];
|
|
19
28
|
|
|
29
|
+
export function releaseNotesFromMarkdown(value: string, releaseTitle?: string): ReleaseNotes;
|
|
30
|
+
|
|
20
31
|
export default function Changelog(props: ChangelogProps): ReactNode;
|
package/index.js
CHANGED
|
@@ -21,6 +21,7 @@ export function releasesFromAtomDocument(document) {
|
|
|
21
21
|
href: releaseLink(entry),
|
|
22
22
|
updated: elementText(entry, 'updated') || elementText(entry, 'published'),
|
|
23
23
|
summary: elementText(entry, 'summary') || elementText(entry, 'content'),
|
|
24
|
+
description: '',
|
|
24
25
|
}));
|
|
25
26
|
}
|
|
26
27
|
|
|
@@ -45,9 +46,111 @@ export function releasesFromGitLabApiResponse(releases) {
|
|
|
45
46
|
href: release?._links?.self || release?.assets?.links?.[0]?.url || '',
|
|
46
47
|
updated: release.released_at || release.created_at || '',
|
|
47
48
|
summary: plainSummary(release.description),
|
|
49
|
+
description: release.description || '',
|
|
48
50
|
}));
|
|
49
51
|
}
|
|
50
52
|
|
|
53
|
+
function inlineMarkdownText(value) {
|
|
54
|
+
return (value ?? '')
|
|
55
|
+
.replace(/!\[([^\]]*)]\([^)]+\)/g, '$1')
|
|
56
|
+
.replace(/\[([^\]]+)]\([^)]+\)/g, '$1')
|
|
57
|
+
.replace(/[*_`~]/g, '');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function plainInlineMarkdown(value) {
|
|
61
|
+
return inlineMarkdownText(value).trim();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function releaseNotesFromMarkdown(value, releaseTitle = '') {
|
|
65
|
+
const intro = [];
|
|
66
|
+
const sections = [];
|
|
67
|
+
let currentSection;
|
|
68
|
+
|
|
69
|
+
for (const rawLine of (value ?? '').split('\n')) {
|
|
70
|
+
const line = rawLine.trim();
|
|
71
|
+
if (!line || /^-{3,}$/.test(line)) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const heading = line.match(/^#{1,6}\s+(.+)$/);
|
|
76
|
+
if (heading) {
|
|
77
|
+
const title = plainInlineMarkdown(heading[1]);
|
|
78
|
+
if (sections.length === 0 && intro.length === 0 && releaseTitle && title.startsWith(releaseTitle)) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
currentSection = {title, items: []};
|
|
82
|
+
sections.push(currentSection);
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const listItem = line.match(/^(?:[-*+] |\d+[.)] )(.+)$/);
|
|
87
|
+
const item = listItem?.[1] ?? line;
|
|
88
|
+
if (currentSection) {
|
|
89
|
+
currentSection.items.push(item);
|
|
90
|
+
} else {
|
|
91
|
+
intro.push(item);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
intro,
|
|
97
|
+
sections: sections.filter((section) => section.title || section.items.length > 0),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function inlineMarkdown(value) {
|
|
102
|
+
const nodes = [];
|
|
103
|
+
const linkPattern = /\[([^\]]+)]\((https?:\/\/[^)\s]+)\)/g;
|
|
104
|
+
let cursor = 0;
|
|
105
|
+
let match;
|
|
106
|
+
|
|
107
|
+
while ((match = linkPattern.exec(value)) !== null) {
|
|
108
|
+
if (match.index > cursor) {
|
|
109
|
+
nodes.push(inlineMarkdownText(value.slice(cursor, match.index)));
|
|
110
|
+
}
|
|
111
|
+
nodes.push(React.createElement('a', {href: match[2], key: `${match.index}-${match[2]}`}, match[1]));
|
|
112
|
+
cursor = match.index + match[0].length;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (cursor < value.length) {
|
|
116
|
+
nodes.push(inlineMarkdownText(value.slice(cursor)));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return nodes;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function ReleaseNotes({description, releaseTitle, summary}) {
|
|
123
|
+
const notes = releaseNotesFromMarkdown(description, releaseTitle);
|
|
124
|
+
|
|
125
|
+
if (notes.intro.length === 0 && notes.sections.length === 0) {
|
|
126
|
+
return summary ? React.createElement('p', null, summary) : null;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return React.createElement(
|
|
130
|
+
'div',
|
|
131
|
+
{className: 'ci-tools-changelog__notes'},
|
|
132
|
+
notes.intro.map((line, index) =>
|
|
133
|
+
React.createElement('p', {key: `intro-${index}`}, inlineMarkdown(line)),
|
|
134
|
+
),
|
|
135
|
+
notes.sections.map((section, sectionIndex) =>
|
|
136
|
+
React.createElement(
|
|
137
|
+
'section',
|
|
138
|
+
{className: 'ci-tools-changelog__section', key: `${section.title}-${sectionIndex}`},
|
|
139
|
+
React.createElement('h4', null, section.title),
|
|
140
|
+
section.items.length > 0
|
|
141
|
+
? React.createElement(
|
|
142
|
+
'ul',
|
|
143
|
+
null,
|
|
144
|
+
section.items.map((item, itemIndex) =>
|
|
145
|
+
React.createElement('li', {key: `${itemIndex}-${item}`}, inlineMarkdown(item)),
|
|
146
|
+
),
|
|
147
|
+
)
|
|
148
|
+
: null,
|
|
149
|
+
),
|
|
150
|
+
),
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
51
154
|
function parseAtomFeed(text) {
|
|
52
155
|
if (typeof DOMParser === 'undefined') {
|
|
53
156
|
throw new Error('DOMParser is not available in this environment.');
|
|
@@ -148,26 +251,59 @@ export default function Changelog({url, children, limit = 10}) {
|
|
|
148
251
|
state.status === 'ready' && state.releases.length > 0
|
|
149
252
|
? React.createElement(
|
|
150
253
|
'ol',
|
|
151
|
-
{
|
|
254
|
+
{
|
|
255
|
+
className: 'ci-tools-changelog__list',
|
|
256
|
+
style: {display: 'grid', gap: '1.5rem', listStyle: 'none', padding: 0},
|
|
257
|
+
},
|
|
152
258
|
state.releases.map((release) =>
|
|
153
259
|
React.createElement(
|
|
154
260
|
'li',
|
|
155
|
-
{
|
|
261
|
+
{
|
|
262
|
+
key: release.href || release.title,
|
|
263
|
+
className: 'ci-tools-changelog__item',
|
|
264
|
+
style: {
|
|
265
|
+
border: '1px solid var(--ifm-color-emphasis-300, #d0d7de)',
|
|
266
|
+
borderRadius: 'var(--ifm-card-border-radius, 0.5rem)',
|
|
267
|
+
padding: '1.25rem 1.5rem',
|
|
268
|
+
},
|
|
269
|
+
},
|
|
156
270
|
React.createElement(
|
|
157
|
-
'
|
|
158
|
-
|
|
159
|
-
|
|
271
|
+
'article',
|
|
272
|
+
null,
|
|
273
|
+
React.createElement(
|
|
274
|
+
'header',
|
|
275
|
+
{
|
|
276
|
+
style: {
|
|
277
|
+
alignItems: 'baseline',
|
|
278
|
+
display: 'flex',
|
|
279
|
+
flexWrap: 'wrap',
|
|
280
|
+
gap: '0.5rem 1rem',
|
|
281
|
+
justifyContent: 'space-between',
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
React.createElement(
|
|
285
|
+
'h3',
|
|
286
|
+
{style: {marginBottom: '0.5rem'}},
|
|
287
|
+
React.createElement(
|
|
288
|
+
'a',
|
|
289
|
+
{href: release.href || url},
|
|
290
|
+
release.title,
|
|
291
|
+
),
|
|
292
|
+
),
|
|
293
|
+
release.updated
|
|
294
|
+
? React.createElement(
|
|
295
|
+
'time',
|
|
296
|
+
{dateTime: release.updated},
|
|
297
|
+
formatDate(release.updated),
|
|
298
|
+
)
|
|
299
|
+
: null,
|
|
300
|
+
),
|
|
301
|
+
React.createElement(ReleaseNotes, {
|
|
302
|
+
description: release.description,
|
|
303
|
+
releaseTitle: release.title,
|
|
304
|
+
summary: release.summary,
|
|
305
|
+
}),
|
|
160
306
|
),
|
|
161
|
-
release.updated
|
|
162
|
-
? React.createElement(
|
|
163
|
-
'time',
|
|
164
|
-
{dateTime: release.updated},
|
|
165
|
-
formatDate(release.updated),
|
|
166
|
-
)
|
|
167
|
-
: null,
|
|
168
|
-
release.summary
|
|
169
|
-
? React.createElement('p', null, release.summary)
|
|
170
|
-
: null,
|
|
171
307
|
),
|
|
172
308
|
),
|
|
173
309
|
)
|