@ckeditor/ckeditor5-dev-changelog 51.0.0 → 52.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/dist/index.js CHANGED
@@ -188,14 +188,16 @@ function groupEntriesBySection(options) {
188
188
  return files.reduce((sections, entry) => {
189
189
  const { validatedEntry, isValid } = validateEntry(entry, packageNames, isSinglePackage);
190
190
  const validatedData = validatedEntry.data;
191
+ const closesLinks = filterLinks(validatedData.closes, validatedEntry);
192
+ const closes = getIssuesLinks(closesLinks, 'Closes');
193
+ const seeLinks = filterLinks(validatedData.see, validatedEntry);
194
+ const see = getIssuesLinks(seeLinks, 'See');
191
195
  const scope = isSinglePackage ? null : getScopesLinks(validatedData.scope, transformScope);
192
- const closes = getIssuesLinks(validatedData.closes, 'Closes', validatedEntry.gitHubUrl);
193
- const see = getIssuesLinks(validatedData.see, 'See', validatedEntry.gitHubUrl);
194
196
  const section = getSection({ entry: validatedEntry, isSinglePackage, isValid });
195
197
  const contentWithCommunityCredits = getContentWithCommunityCredits(validatedEntry.content, validatedData.communityCredits);
196
198
  const content = linkToGitHubUser(contentWithCommunityCredits);
197
199
  const [mainContent, ...restContent] = formatContent(content);
198
- const changeMessage = getChangeMessage({ restContent, scope, mainContent, entry, see, closes });
200
+ const changeMessage = getChangeMessage({ restContent, scope, mainContent, see, closes });
199
201
  const newEntry = {
200
202
  message: changeMessage,
201
203
  data: {
@@ -203,8 +205,8 @@ function groupEntriesBySection(options) {
203
205
  restContent,
204
206
  type: validatedData.type,
205
207
  scope: validatedData.scope,
206
- see: validatedData.see.map(see => getIssueLinkObject(see, validatedEntry.gitHubUrl)),
207
- closes: validatedData.closes.map(closes => getIssueLinkObject(closes, validatedEntry.gitHubUrl)),
208
+ see: seeLinks,
209
+ closes: closesLinks,
208
210
  validations: validatedData.validations,
209
211
  communityCredits: validatedData.communityCredits
210
212
  },
@@ -217,13 +219,18 @@ function groupEntriesBySection(options) {
217
219
  return sections;
218
220
  }, getInitialSectionsWithEntries());
219
221
  }
220
- function getChangeMessage({ restContent, scope, mainContent, entry, see, closes }) {
222
+ function filterLinks(links, entry) {
223
+ return links
224
+ .map(link => getIssueLinkObject(link, entry.gitHubUrl))
225
+ .filter(({ link }) => entry.linkFilter(link));
226
+ }
227
+ function getChangeMessage({ restContent, scope, mainContent, see, closes }) {
221
228
  const messageFirstLine = [
222
229
  '*',
223
230
  scope ? `**${scope}**:` : null,
224
231
  mainContent,
225
- !entry.shouldSkipLinks && see.length ? see : null,
226
- !entry.shouldSkipLinks && closes.length ? closes : null
232
+ see.length ? see : null,
233
+ closes.length ? closes : null
227
234
  ].filter(Boolean).join(' ');
228
235
  if (!restContent || !restContent.length) {
229
236
  return messageFirstLine;
@@ -238,7 +245,8 @@ function getChangeMessage({ restContent, scope, mainContent, entry, see, closes
238
245
  function formatContent(content) {
239
246
  const lines = content.trim()
240
247
  .split('\n')
241
- .map(line => line.trimEnd());
248
+ .map(line => line.trimEnd())
249
+ .map(line => normalizeListMarker(line));
242
250
  const mainIndex = lines.findIndex(line => line.trim() !== '');
243
251
  const mainContent = lines.at(mainIndex);
244
252
  let restContent = lines.slice(mainIndex + 1);
@@ -290,14 +298,11 @@ function getIssueLinkObject(issue, gitHubUrl) {
290
298
  }
291
299
  return { displayName: '', link: '' };
292
300
  }
293
- function getIssuesLinks(issues, prefix, gitHubUrl) {
301
+ function getIssuesLinks(issues, prefix) {
294
302
  if (!issues.length) {
295
303
  return '';
296
304
  }
297
- const links = issues.map(String).map(issue => {
298
- const { displayName, link } = getIssueLinkObject(issue, gitHubUrl);
299
- return `[${displayName}](${link})`;
300
- });
305
+ const links = issues.map(issue => `[${issue.displayName}](${issue.link})`);
301
306
  return `${prefix} ${links.join(', ')}.`;
302
307
  }
303
308
  function getSection(options) {
@@ -329,6 +334,10 @@ function getInitialSectionsWithEntries() {
329
334
  }
330
335
  return sections;
331
336
  }
337
+ function normalizeListMarker(line) {
338
+ const listMarkerRegexp = /^(\s*)[-+](\s*)/;
339
+ return line.replace(listMarkerRegexp, '$1*$2');
340
+ }
332
341
 
333
342
  /**
334
343
  * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
@@ -900,7 +909,7 @@ function getPackageName(value) {
900
909
  * Gathers changelog entry file paths (Markdown files) from the main repository and any configured external repositories.
901
910
  */
902
911
  async function findChangelogEntryPaths(options) {
903
- const { cwd, externalRepositories, shouldSkipLinks, includeSubdirectories = true } = options;
912
+ const { cwd, externalRepositories, includeSubdirectories = true } = options;
904
913
  const globPattern = includeSubdirectories ? '**/*.md' : '*.md';
905
914
  return AsyncArray
906
915
  .from(Promise.resolve(externalRepositories))
@@ -912,7 +921,7 @@ async function findChangelogEntryPaths(options) {
912
921
  return {
913
922
  filePaths: changesetGlob.map(p => upath.normalize(p)),
914
923
  gitHubUrl: await workspaces.getRepositoryUrl(repo.cwd, { async: true }),
915
- shouldSkipLinks: !!repo.shouldSkipLinks,
924
+ linkFilter: getLinkFilter(repo),
916
925
  cwd: repo.cwd,
917
926
  isRoot: false
918
927
  };
@@ -925,13 +934,19 @@ async function findChangelogEntryPaths(options) {
925
934
  const mainEntry = {
926
935
  filePaths: mainChangesetGlob.map(p => upath.normalize(p)),
927
936
  gitHubUrl: await workspaces.getRepositoryUrl(cwd, { async: true }),
928
- shouldSkipLinks,
937
+ linkFilter: getLinkFilter(options),
929
938
  cwd,
930
939
  isRoot: true
931
940
  };
932
941
  return [mainEntry, ...externalResults];
933
942
  });
934
943
  }
944
+ function getLinkFilter(options) {
945
+ if (typeof options.shouldSkipLinks === 'boolean') {
946
+ return () => !options.shouldSkipLinks;
947
+ }
948
+ return options.linkFilter || (() => true);
949
+ }
935
950
 
936
951
  /**
937
952
  * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
@@ -1037,19 +1052,19 @@ function toArray(input) {
1037
1052
  * Reads and processes input files to extract changelog entries.
1038
1053
  */
1039
1054
  function parseChangelogEntries(entryPaths, isSinglePackage) {
1040
- const fileEntries = entryPaths.reduce((acc, { filePaths, gitHubUrl, shouldSkipLinks }) => {
1055
+ const fileEntries = entryPaths.reduce((acc, { filePaths, gitHubUrl, linkFilter }) => {
1041
1056
  for (const changesetPath of filePaths) {
1042
- acc.push({ changesetPath, gitHubUrl, shouldSkipLinks });
1057
+ acc.push({ changesetPath, gitHubUrl, linkFilter });
1043
1058
  }
1044
1059
  return acc;
1045
1060
  }, []);
1046
1061
  return AsyncArray
1047
1062
  .from(Promise.resolve(fileEntries))
1048
- .map(async ({ changesetPath, gitHubUrl, shouldSkipLinks }) => ({
1063
+ .map(async ({ changesetPath, gitHubUrl, linkFilter }) => ({
1049
1064
  ...matter(await fs$1.readFile(changesetPath, 'utf-8')),
1050
1065
  gitHubUrl,
1051
1066
  changesetPath,
1052
- shouldSkipLinks,
1067
+ linkFilter,
1053
1068
  createdAt: extractDateFromFilename(changesetPath)
1054
1069
  }))
1055
1070
  .map(entry => normalizeEntry(entry, isSinglePackage))
@@ -1307,7 +1322,7 @@ function getReleaseType(currentVersion, nextVersion) {
1307
1322
  * and the assembled changelog object will be returned instead.
1308
1323
  */
1309
1324
  const main = async (options) => {
1310
- const { nextVersion, packagesDirectory, isSinglePackage, transformScope, npmPackageToCheck, cwd = process.cwd(), externalRepositories = [], date = format(new Date(), 'yyyy-MM-dd'), shouldSkipLinks = false, shouldIgnoreRootPackage = false, disableFilesystemOperations = false } = options;
1325
+ const { nextVersion, packagesDirectory, isSinglePackage, transformScope, npmPackageToCheck, linkFilter, shouldSkipLinks, cwd = process.cwd(), externalRepositories = [], date = format(new Date(), 'yyyy-MM-dd'), shouldIgnoreRootPackage = false, disableFilesystemOperations = false } = options;
1311
1326
  const { version: currentVersion, name: rootPackageName } = await workspaces.getPackageJson(cwd, { async: true });
1312
1327
  const packagesMetadata = await findPackages({
1313
1328
  cwd,
@@ -1319,6 +1334,7 @@ const main = async (options) => {
1319
1334
  const entryPaths = await findChangelogEntryPaths({
1320
1335
  cwd,
1321
1336
  externalRepositories,
1337
+ linkFilter,
1322
1338
  shouldSkipLinks,
1323
1339
  includeSubdirectories: releaseType === 'latest' || releaseType === 'prerelease-promote'
1324
1340
  });
@@ -1422,7 +1438,7 @@ function isExpectedError(error) {
1422
1438
  * For licensing, see LICENSE.md.
1423
1439
  */
1424
1440
  const generateChangelogForMonoRepository = async (options) => {
1425
- const { date, cwd, externalRepositories, nextVersion, disableFilesystemOperations, npmPackageToCheck, packagesDirectory, shouldSkipLinks, shouldIgnoreRootPackage, transformScope } = options;
1441
+ const { date, cwd, externalRepositories, nextVersion, disableFilesystemOperations, npmPackageToCheck, packagesDirectory, linkFilter, shouldSkipLinks, shouldIgnoreRootPackage, transformScope } = options;
1426
1442
  return generateChangelog({
1427
1443
  nextVersion,
1428
1444
  cwd,
@@ -1430,6 +1446,7 @@ const generateChangelogForMonoRepository = async (options) => {
1430
1446
  externalRepositories,
1431
1447
  transformScope,
1432
1448
  date,
1449
+ linkFilter,
1433
1450
  shouldSkipLinks,
1434
1451
  disableFilesystemOperations,
1435
1452
  ...(shouldIgnoreRootPackage && npmPackageToCheck ?
@@ -1444,12 +1461,13 @@ const generateChangelogForMonoRepository = async (options) => {
1444
1461
  * For licensing, see LICENSE.md.
1445
1462
  */
1446
1463
  const generateChangelogForSingleRepository = async (options) => {
1447
- const { cwd, date, externalRepositories, nextVersion, disableFilesystemOperations, shouldSkipLinks } = options;
1464
+ const { cwd, date, externalRepositories, nextVersion, disableFilesystemOperations, linkFilter, shouldSkipLinks } = options;
1448
1465
  return generateChangelog({
1449
1466
  nextVersion,
1450
1467
  cwd,
1451
1468
  externalRepositories,
1452
1469
  date,
1470
+ linkFilter,
1453
1471
  shouldSkipLinks,
1454
1472
  disableFilesystemOperations,
1455
1473
  isSinglePackage: true,
package/dist/types.d.ts CHANGED
@@ -41,6 +41,12 @@ export type RepositoryConfig = {
41
41
  * The directory containing the packages. Defaults to 'packages'.
42
42
  */
43
43
  packagesDirectory: null | string;
44
+ /**
45
+ * Function that decides whether to filter out a link in the changelog entry.
46
+ * If `shouldSkipLinks` flag is set, the `shouldSkipLinks` flag takes precedence over the `linkFilter` function.
47
+ * No links are skipped by default.
48
+ */
49
+ linkFilter?: LinkFilter;
44
50
  /**
45
51
  * Whether to skip links in the changelog entries. Defaults to false.
46
52
  */
@@ -73,7 +79,7 @@ export type ParsedFile<T = FileMetadata> = {
73
79
  changesetPath: string;
74
80
  createdAt: Date;
75
81
  gitHubUrl: string;
76
- shouldSkipLinks: boolean;
82
+ linkFilter: LinkFilter;
77
83
  };
78
84
  export type Section = {
79
85
  entries: Array<Entry>;
@@ -94,7 +100,7 @@ export type TransformScope = (name: string) => {
94
100
  export type ChangesetPathsWithGithubUrl = {
95
101
  filePaths: Array<string>;
96
102
  gitHubUrl: string;
97
- shouldSkipLinks: boolean;
103
+ linkFilter: LinkFilter;
98
104
  cwd: string;
99
105
  isRoot: boolean;
100
106
  };
@@ -109,6 +115,7 @@ export type LinkObject = {
109
115
  displayName: string;
110
116
  link: string;
111
117
  };
118
+ export type LinkFilter = (resourceUrl: string) => boolean;
112
119
  export type FileMetadata = {
113
120
  type: string;
114
121
  scope: Array<string>;
@@ -2,11 +2,12 @@
2
2
  * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md.
4
4
  */
5
- import type { ChangesetPathsWithGithubUrl, RepositoryConfig } from '../types.js';
5
+ import type { ChangesetPathsWithGithubUrl, LinkFilter, RepositoryConfig } from '../types.js';
6
6
  type FindChangelogEntryPathsOptions = {
7
7
  cwd: string;
8
8
  externalRepositories: Array<RepositoryConfig>;
9
- shouldSkipLinks: boolean;
9
+ linkFilter?: LinkFilter;
10
+ shouldSkipLinks?: boolean;
10
11
  includeSubdirectories?: boolean;
11
12
  };
12
13
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ckeditor/ckeditor5-dev-changelog",
3
- "version": "51.0.0",
3
+ "version": "52.0.0",
4
4
  "description": "A CKEditor 5 development tool for handling changelogs.",
5
5
  "keywords": [],
6
6
  "author": "CKSource (http://cksource.com/)",
@@ -28,7 +28,7 @@
28
28
  "ckeditor5-dev-changelog-create-entry": "bin/generate-template.js"
29
29
  },
30
30
  "dependencies": {
31
- "@ckeditor/ckeditor5-dev-utils": "^51.0.0",
31
+ "@ckeditor/ckeditor5-dev-utils": "^52.0.0",
32
32
  "chalk": "^5.0.0",
33
33
  "date-fns": "^4.0.0",
34
34
  "fs-extra": "^11.0.0",