@ckeditor/ckeditor5-dev-changelog 50.3.1 → 51.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.
- package/dist/index.js +284 -107
- package/dist/types.d.ts +15 -4
- package/dist/utils/composechangelog.d.ts +2 -5
- package/dist/utils/constants.d.ts +1 -0
- package/dist/utils/detectreleasechannel.d.ts +9 -0
- package/dist/utils/determinenextversion.d.ts +5 -9
- package/dist/utils/findchangelogentrypaths.d.ts +4 -2
- package/dist/utils/getreleasetype.d.ts +6 -0
- package/dist/utils/internalerror.d.ts +0 -1
- package/dist/utils/movechangelogentryfiles.d.ts +11 -0
- package/dist/utils/promptreleasetype.d.ts +9 -0
- package/dist/utils/providenewversion.d.ts +3 -0
- package/dist/utils/validateinputversion.d.ts +14 -0
- package/package.json +2 -2
- package/template/template.md +2 -2
package/dist/index.js
CHANGED
|
@@ -18,6 +18,7 @@ const CHANGELOG_HEADER = 'Changelog\n=========';
|
|
|
18
18
|
const NPM_URL = 'https://www.npmjs.com/package';
|
|
19
19
|
const VERSIONING_POLICY_URL = 'https://ckeditor.com/docs/ckeditor5/latest/framework/guides/support/versioning-policy.html';
|
|
20
20
|
const CHANGESET_DIRECTORY = '.changelog';
|
|
21
|
+
const PRE_RELEASE_DIRECTORY = 'pre-release';
|
|
21
22
|
upath.join(import.meta.dirname, '../template/template.md');
|
|
22
23
|
const SECTIONS = {
|
|
23
24
|
major: {
|
|
@@ -187,14 +188,16 @@ function groupEntriesBySection(options) {
|
|
|
187
188
|
return files.reduce((sections, entry) => {
|
|
188
189
|
const { validatedEntry, isValid } = validateEntry(entry, packageNames, isSinglePackage);
|
|
189
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');
|
|
190
195
|
const scope = isSinglePackage ? null : getScopesLinks(validatedData.scope, transformScope);
|
|
191
|
-
const closes = getIssuesLinks(validatedData.closes, 'Closes', validatedEntry.gitHubUrl);
|
|
192
|
-
const see = getIssuesLinks(validatedData.see, 'See', validatedEntry.gitHubUrl);
|
|
193
196
|
const section = getSection({ entry: validatedEntry, isSinglePackage, isValid });
|
|
194
197
|
const contentWithCommunityCredits = getContentWithCommunityCredits(validatedEntry.content, validatedData.communityCredits);
|
|
195
198
|
const content = linkToGitHubUser(contentWithCommunityCredits);
|
|
196
199
|
const [mainContent, ...restContent] = formatContent(content);
|
|
197
|
-
const changeMessage = getChangeMessage({ restContent, scope, mainContent,
|
|
200
|
+
const changeMessage = getChangeMessage({ restContent, scope, mainContent, see, closes });
|
|
198
201
|
const newEntry = {
|
|
199
202
|
message: changeMessage,
|
|
200
203
|
data: {
|
|
@@ -202,8 +205,8 @@ function groupEntriesBySection(options) {
|
|
|
202
205
|
restContent,
|
|
203
206
|
type: validatedData.type,
|
|
204
207
|
scope: validatedData.scope,
|
|
205
|
-
see:
|
|
206
|
-
closes:
|
|
208
|
+
see: seeLinks,
|
|
209
|
+
closes: closesLinks,
|
|
207
210
|
validations: validatedData.validations,
|
|
208
211
|
communityCredits: validatedData.communityCredits
|
|
209
212
|
},
|
|
@@ -216,13 +219,18 @@ function groupEntriesBySection(options) {
|
|
|
216
219
|
return sections;
|
|
217
220
|
}, getInitialSectionsWithEntries());
|
|
218
221
|
}
|
|
219
|
-
function
|
|
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 }) {
|
|
220
228
|
const messageFirstLine = [
|
|
221
229
|
'*',
|
|
222
230
|
scope ? `**${scope}**:` : null,
|
|
223
231
|
mainContent,
|
|
224
|
-
|
|
225
|
-
|
|
232
|
+
see.length ? see : null,
|
|
233
|
+
closes.length ? closes : null
|
|
226
234
|
].filter(Boolean).join(' ');
|
|
227
235
|
if (!restContent || !restContent.length) {
|
|
228
236
|
return messageFirstLine;
|
|
@@ -237,7 +245,8 @@ function getChangeMessage({ restContent, scope, mainContent, entry, see, closes
|
|
|
237
245
|
function formatContent(content) {
|
|
238
246
|
const lines = content.trim()
|
|
239
247
|
.split('\n')
|
|
240
|
-
.map(line => line.trimEnd())
|
|
248
|
+
.map(line => line.trimEnd())
|
|
249
|
+
.map(line => normalizeListMarker(line));
|
|
241
250
|
const mainIndex = lines.findIndex(line => line.trim() !== '');
|
|
242
251
|
const mainContent = lines.at(mainIndex);
|
|
243
252
|
let restContent = lines.slice(mainIndex + 1);
|
|
@@ -282,18 +291,18 @@ function getIssueLinkObject(issue, gitHubUrl) {
|
|
|
282
291
|
const repoUrlMatch = issue.match(ISSUE_URL_PATTERN);
|
|
283
292
|
if (repoUrlMatch) {
|
|
284
293
|
const { owner, repository, number } = repoUrlMatch.groups;
|
|
294
|
+
if (issue.startsWith(gitHubUrl)) {
|
|
295
|
+
return { displayName: `#${number}`, link: issue };
|
|
296
|
+
}
|
|
285
297
|
return { displayName: `${owner}/${repository}#${number}`, link: issue };
|
|
286
298
|
}
|
|
287
299
|
return { displayName: '', link: '' };
|
|
288
300
|
}
|
|
289
|
-
function getIssuesLinks(issues, prefix
|
|
301
|
+
function getIssuesLinks(issues, prefix) {
|
|
290
302
|
if (!issues.length) {
|
|
291
303
|
return '';
|
|
292
304
|
}
|
|
293
|
-
const links = issues.map(
|
|
294
|
-
const { displayName, link } = getIssueLinkObject(issue, gitHubUrl);
|
|
295
|
-
return `[${displayName}](${link})`;
|
|
296
|
-
});
|
|
305
|
+
const links = issues.map(issue => `[${issue.displayName}](${issue.link})`);
|
|
297
306
|
return `${prefix} ${links.join(', ')}.`;
|
|
298
307
|
}
|
|
299
308
|
function getSection(options) {
|
|
@@ -325,6 +334,10 @@ function getInitialSectionsWithEntries() {
|
|
|
325
334
|
}
|
|
326
335
|
return sections;
|
|
327
336
|
}
|
|
337
|
+
function normalizeListMarker(line) {
|
|
338
|
+
const listMarkerRegexp = /^(\s*)[-+](\s*)/;
|
|
339
|
+
return line.replace(listMarkerRegexp, '$1*$2');
|
|
340
|
+
}
|
|
328
341
|
|
|
329
342
|
/**
|
|
330
343
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
|
@@ -529,6 +542,49 @@ function prepareChangelogContent(existingChangelog, newChangelog) {
|
|
|
529
542
|
class UserAbortError extends Error {
|
|
530
543
|
}
|
|
531
544
|
|
|
545
|
+
/**
|
|
546
|
+
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
|
547
|
+
* For licensing, see LICENSE.md.
|
|
548
|
+
*/
|
|
549
|
+
async function validateInputVersion(options) {
|
|
550
|
+
const { newVersion, version, releaseType, packageName, suggestedVersion } = options;
|
|
551
|
+
const [newChannel] = semver.prerelease(newVersion) || ['latest'];
|
|
552
|
+
const [currentChannel] = semver.prerelease(version) || ['latest'];
|
|
553
|
+
// Generic semantic‑version checks.
|
|
554
|
+
if (!semver.valid(newVersion)) {
|
|
555
|
+
return 'Please provide a valid version.';
|
|
556
|
+
}
|
|
557
|
+
if (!semver.gt(newVersion, version)) {
|
|
558
|
+
return `Provided version must be higher than "${version}".`;
|
|
559
|
+
}
|
|
560
|
+
if (!(await npm.checkVersionAvailability(newVersion, packageName))) {
|
|
561
|
+
return 'Given version is already taken.';
|
|
562
|
+
}
|
|
563
|
+
// Rules that depend on release type.
|
|
564
|
+
const isPrerelease = releaseType === 'prerelease';
|
|
565
|
+
const isPrereleasePromote = releaseType === 'prerelease-promote';
|
|
566
|
+
const isLatest = releaseType === 'latest';
|
|
567
|
+
// Pre‑release types must always include a channel suffix.
|
|
568
|
+
if ((isPrerelease || isPrereleasePromote) && newChannel === 'latest') {
|
|
569
|
+
return 'You chose the "pre-release" release type. Please provide a version with a channel suffix.';
|
|
570
|
+
}
|
|
571
|
+
// Promoting a pre‑release: new version ≥ suggested version.
|
|
572
|
+
if (isPrereleasePromote && !semver.gte(newVersion, suggestedVersion)) {
|
|
573
|
+
return `Provided version must be higher or equal to "${suggestedVersion}".`;
|
|
574
|
+
}
|
|
575
|
+
// Continuing a pre‑release stream: channel cannot change.
|
|
576
|
+
if (isPrerelease &&
|
|
577
|
+
currentChannel !== 'latest' &&
|
|
578
|
+
currentChannel !== newChannel) {
|
|
579
|
+
return `Provided channel must be the same existing channel ${currentChannel}.`;
|
|
580
|
+
}
|
|
581
|
+
// Latest release must not carry a channel suffix.
|
|
582
|
+
if (isLatest && newChannel !== 'latest') {
|
|
583
|
+
return 'You chose the "latest" release type. Please provide a version without a channel suffix.';
|
|
584
|
+
}
|
|
585
|
+
return true;
|
|
586
|
+
}
|
|
587
|
+
|
|
532
588
|
/**
|
|
533
589
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
|
534
590
|
* For licensing, see LICENSE.md.
|
|
@@ -584,39 +640,69 @@ async function askContinueConfirmation(indentLevel = 0) {
|
|
|
584
640
|
* Creates a prompt question for version input with validation.
|
|
585
641
|
*/
|
|
586
642
|
function createVersionQuestion(options) {
|
|
587
|
-
const { version, packageName, bumpType, indentLevel = 0 } = options;
|
|
588
|
-
const suggestedVersion =
|
|
643
|
+
const { version, packageName, bumpType, releaseChannel, releaseType, indentLevel = 0 } = options;
|
|
644
|
+
const suggestedVersion = getSuggestedVersion(bumpType, version, releaseChannel) || version;
|
|
589
645
|
const message = 'Type the new version ' +
|
|
590
|
-
`(current: "${version}", suggested: "${suggestedVersion}"
|
|
646
|
+
`(current: "${version}", suggested: "${suggestedVersion}":`;
|
|
591
647
|
return [{
|
|
592
648
|
type: 'input',
|
|
593
649
|
name: 'version',
|
|
594
650
|
default: suggestedVersion,
|
|
595
651
|
message,
|
|
596
652
|
filter: (newVersion) => newVersion.trim(),
|
|
597
|
-
|
|
598
|
-
// Allow 'internal' as a special version.
|
|
599
|
-
if (newVersion === 'internal') {
|
|
600
|
-
return true;
|
|
601
|
-
}
|
|
602
|
-
// Require a semver valid version, e.g., `1.0.0`, `1.0.0-alpha.0`, etc.
|
|
603
|
-
if (!semver.valid(newVersion)) {
|
|
604
|
-
return 'Please provide a valid version or "internal" for internal changes.';
|
|
605
|
-
}
|
|
606
|
-
// The provided version must be higher than the current version.
|
|
607
|
-
if (!semver.gt(newVersion, version)) {
|
|
608
|
-
return `Provided version must be higher than "${version}".`;
|
|
609
|
-
}
|
|
610
|
-
const isAvailable = await npm.checkVersionAvailability(newVersion, packageName);
|
|
611
|
-
// Check against availability in the npm registry.
|
|
612
|
-
if (!isAvailable) {
|
|
613
|
-
return 'Given version is already taken.';
|
|
614
|
-
}
|
|
615
|
-
return true;
|
|
616
|
-
},
|
|
653
|
+
validate: (newVersion) => validateInputVersion({ newVersion, version, releaseType, packageName, suggestedVersion }),
|
|
617
654
|
prefix: ' '.repeat(indentLevel * CLI_INDENT_SIZE) + chalk.cyan('?')
|
|
618
655
|
}];
|
|
619
656
|
}
|
|
657
|
+
function getSuggestedVersion(bumpType, version, releaseChannel) {
|
|
658
|
+
if (bumpType === 'prerelease' && releaseChannel !== 'latest') {
|
|
659
|
+
return semver.inc(version, bumpType, releaseChannel);
|
|
660
|
+
}
|
|
661
|
+
else if (bumpType === 'prerelease' && releaseChannel === 'latest') {
|
|
662
|
+
// Using 'premajor` and `alpha` channel for a case, when introducing a prerelease for the next major.
|
|
663
|
+
// E.g. 1.0.0 -> 2.0.0-alpha.0.
|
|
664
|
+
return semver.inc(version, 'premajor', 'alpha');
|
|
665
|
+
}
|
|
666
|
+
else {
|
|
667
|
+
return semver.inc(version, bumpType);
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
|
673
|
+
* For licensing, see LICENSE.md.
|
|
674
|
+
*/
|
|
675
|
+
/**
|
|
676
|
+
* Detects the release channel from a version string.
|
|
677
|
+
*/
|
|
678
|
+
function detectReleaseChannel(version, promotePrerelease = false) {
|
|
679
|
+
const prerelease = semver.prerelease(version);
|
|
680
|
+
if (!prerelease) {
|
|
681
|
+
return 'latest';
|
|
682
|
+
}
|
|
683
|
+
const currentChannel = prerelease[0];
|
|
684
|
+
if (promotePrerelease) {
|
|
685
|
+
if (currentChannel === 'alpha') {
|
|
686
|
+
return 'beta';
|
|
687
|
+
}
|
|
688
|
+
if (currentChannel === 'beta') {
|
|
689
|
+
return 'rc';
|
|
690
|
+
}
|
|
691
|
+
logInfo(chalk.yellow(`Warning! Unknown release channel to promote from ${currentChannel}.`));
|
|
692
|
+
return 'alpha';
|
|
693
|
+
}
|
|
694
|
+
return currentChannel;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
/**
|
|
698
|
+
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
|
699
|
+
* For licensing, see LICENSE.md.
|
|
700
|
+
*/
|
|
701
|
+
/**
|
|
702
|
+
* Custom error class for handling validation errors in the changelog generation process.
|
|
703
|
+
*/
|
|
704
|
+
class InternalError extends Error {
|
|
705
|
+
}
|
|
620
706
|
|
|
621
707
|
/**
|
|
622
708
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
|
@@ -624,27 +710,39 @@ function createVersionQuestion(options) {
|
|
|
624
710
|
*/
|
|
625
711
|
/**
|
|
626
712
|
* Determines the next version for a single package or a mono-repository setup based on
|
|
627
|
-
* the change sections,
|
|
713
|
+
* the change sections, user input, and semantic versioning rules.
|
|
628
714
|
*
|
|
629
715
|
* The function handles:
|
|
630
716
|
* * Automatic version bump calculation from categorized changelog sections (major, minor, patch).
|
|
631
|
-
* *
|
|
717
|
+
* * Version bump for prerelease channels.
|
|
632
718
|
* * User prompts for version input when no explicit version is provided.
|
|
633
719
|
*/
|
|
634
720
|
async function determineNextVersion(options) {
|
|
635
|
-
const { sections, currentVersion, packageName, nextVersion } = options;
|
|
636
|
-
if (nextVersion === 'internal') {
|
|
637
|
-
const internalVersionBump = getInternalVersionBump(currentVersion);
|
|
638
|
-
logInfo(`○ ${chalk.cyan(`Determined the next version to be ${internalVersionBump.newVersion}.`)}`);
|
|
639
|
-
return internalVersionBump;
|
|
640
|
-
}
|
|
721
|
+
const { sections, currentVersion, packageName, nextVersion, releaseType } = options;
|
|
641
722
|
if (nextVersion) {
|
|
642
723
|
logInfo(`○ ${chalk.cyan(`Determined the next version to be ${nextVersion}.`)}`);
|
|
643
|
-
|
|
724
|
+
const isNightlyVersion = nextVersion.startsWith('0.0.0-');
|
|
725
|
+
if (isNightlyVersion) {
|
|
726
|
+
return nextVersion;
|
|
727
|
+
}
|
|
728
|
+
const validationResult = await validateInputVersion({
|
|
729
|
+
newVersion: nextVersion,
|
|
730
|
+
suggestedVersion: nextVersion,
|
|
731
|
+
version: currentVersion,
|
|
732
|
+
releaseType,
|
|
733
|
+
packageName
|
|
734
|
+
});
|
|
735
|
+
if (typeof validationResult === 'string') {
|
|
736
|
+
throw new InternalError(validationResult);
|
|
737
|
+
}
|
|
738
|
+
return nextVersion;
|
|
644
739
|
}
|
|
645
740
|
logInfo(`○ ${chalk.cyan('Determining the new version...')}`);
|
|
646
741
|
let bumpType = 'patch';
|
|
647
|
-
if (
|
|
742
|
+
if (releaseType === 'prerelease' || releaseType === 'prerelease-promote') {
|
|
743
|
+
bumpType = 'prerelease';
|
|
744
|
+
}
|
|
745
|
+
else if (sections.major.entries.length || sections.breaking.entries.length) {
|
|
648
746
|
bumpType = 'major';
|
|
649
747
|
}
|
|
650
748
|
else if (sections.minor.entries.length || sections.feature.entries.length) {
|
|
@@ -655,20 +753,12 @@ async function determineNextVersion(options) {
|
|
|
655
753
|
const userProvidedVersion = await provideNewVersion({
|
|
656
754
|
packageName,
|
|
657
755
|
bumpType,
|
|
756
|
+
releaseType,
|
|
658
757
|
version: currentVersion,
|
|
758
|
+
releaseChannel: detectReleaseChannel(currentVersion, releaseType === 'prerelease-promote'),
|
|
659
759
|
displayValidationWarning: areErrorsPresent || areWarningsPresent
|
|
660
760
|
});
|
|
661
|
-
|
|
662
|
-
return getInternalVersionBump(currentVersion);
|
|
663
|
-
}
|
|
664
|
-
return { newVersion: userProvidedVersion, isInternal: false };
|
|
665
|
-
}
|
|
666
|
-
function getInternalVersionBump(currentVersion) {
|
|
667
|
-
const version = semver.inc(currentVersion, 'patch');
|
|
668
|
-
if (!version) {
|
|
669
|
-
throw new Error('Unable to determine new version based on the version in root package.json.');
|
|
670
|
-
}
|
|
671
|
-
return { newVersion: version, isInternal: true };
|
|
761
|
+
return userProvidedVersion;
|
|
672
762
|
}
|
|
673
763
|
|
|
674
764
|
/**
|
|
@@ -819,37 +909,44 @@ function getPackageName(value) {
|
|
|
819
909
|
* Gathers changelog entry file paths (Markdown files) from the main repository and any configured external repositories.
|
|
820
910
|
*/
|
|
821
911
|
async function findChangelogEntryPaths(options) {
|
|
822
|
-
const { cwd, externalRepositories,
|
|
912
|
+
const { cwd, externalRepositories, includeSubdirectories = true } = options;
|
|
913
|
+
const globPattern = includeSubdirectories ? '**/*.md' : '*.md';
|
|
823
914
|
return AsyncArray
|
|
824
915
|
.from(Promise.resolve(externalRepositories))
|
|
825
916
|
.map(async (repo) => {
|
|
826
|
-
const changesetGlob = await glob(
|
|
917
|
+
const changesetGlob = await glob(globPattern, {
|
|
827
918
|
cwd: upath.join(repo.cwd, CHANGESET_DIRECTORY),
|
|
828
919
|
absolute: true
|
|
829
920
|
});
|
|
830
921
|
return {
|
|
831
922
|
filePaths: changesetGlob.map(p => upath.normalize(p)),
|
|
832
923
|
gitHubUrl: await workspaces.getRepositoryUrl(repo.cwd, { async: true }),
|
|
833
|
-
|
|
924
|
+
linkFilter: getLinkFilter(repo),
|
|
834
925
|
cwd: repo.cwd,
|
|
835
926
|
isRoot: false
|
|
836
927
|
};
|
|
837
928
|
})
|
|
838
929
|
.then(async (externalResults) => {
|
|
839
|
-
const mainChangesetGlob = await glob(
|
|
930
|
+
const mainChangesetGlob = await glob(globPattern, {
|
|
840
931
|
cwd: upath.join(cwd, CHANGESET_DIRECTORY),
|
|
841
932
|
absolute: true
|
|
842
933
|
});
|
|
843
934
|
const mainEntry = {
|
|
844
935
|
filePaths: mainChangesetGlob.map(p => upath.normalize(p)),
|
|
845
936
|
gitHubUrl: await workspaces.getRepositoryUrl(cwd, { async: true }),
|
|
846
|
-
|
|
937
|
+
linkFilter: getLinkFilter(options),
|
|
847
938
|
cwd,
|
|
848
939
|
isRoot: true
|
|
849
940
|
};
|
|
850
941
|
return [mainEntry, ...externalResults];
|
|
851
942
|
});
|
|
852
943
|
}
|
|
944
|
+
function getLinkFilter(options) {
|
|
945
|
+
if (typeof options.shouldSkipLinks === 'boolean') {
|
|
946
|
+
return () => !options.shouldSkipLinks;
|
|
947
|
+
}
|
|
948
|
+
return options.linkFilter || (() => true);
|
|
949
|
+
}
|
|
853
950
|
|
|
854
951
|
/**
|
|
855
952
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
|
@@ -955,19 +1052,19 @@ function toArray(input) {
|
|
|
955
1052
|
* Reads and processes input files to extract changelog entries.
|
|
956
1053
|
*/
|
|
957
1054
|
function parseChangelogEntries(entryPaths, isSinglePackage) {
|
|
958
|
-
const fileEntries = entryPaths.reduce((acc, { filePaths, gitHubUrl,
|
|
1055
|
+
const fileEntries = entryPaths.reduce((acc, { filePaths, gitHubUrl, linkFilter }) => {
|
|
959
1056
|
for (const changesetPath of filePaths) {
|
|
960
|
-
acc.push({ changesetPath, gitHubUrl,
|
|
1057
|
+
acc.push({ changesetPath, gitHubUrl, linkFilter });
|
|
961
1058
|
}
|
|
962
1059
|
return acc;
|
|
963
1060
|
}, []);
|
|
964
1061
|
return AsyncArray
|
|
965
1062
|
.from(Promise.resolve(fileEntries))
|
|
966
|
-
.map(async ({ changesetPath, gitHubUrl,
|
|
1063
|
+
.map(async ({ changesetPath, gitHubUrl, linkFilter }) => ({
|
|
967
1064
|
...matter(await fs$1.readFile(changesetPath, 'utf-8')),
|
|
968
1065
|
gitHubUrl,
|
|
969
1066
|
changesetPath,
|
|
970
|
-
|
|
1067
|
+
linkFilter,
|
|
971
1068
|
createdAt: extractDateFromFilename(changesetPath)
|
|
972
1069
|
}))
|
|
973
1070
|
.map(entry => normalizeEntry(entry, isSinglePackage))
|
|
@@ -994,25 +1091,6 @@ function extractDateFromFilename(changesetPath) {
|
|
|
994
1091
|
return parsedDate;
|
|
995
1092
|
}
|
|
996
1093
|
|
|
997
|
-
/**
|
|
998
|
-
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
|
999
|
-
* For licensing, see LICENSE.md.
|
|
1000
|
-
*/
|
|
1001
|
-
/**
|
|
1002
|
-
* Custom error class for handling validation errors in the changelog generation process.
|
|
1003
|
-
*/
|
|
1004
|
-
class InternalError extends Error {
|
|
1005
|
-
constructor() {
|
|
1006
|
-
const message = 'No valid entries were found. Please ensure that:\n' +
|
|
1007
|
-
'1) Input files exist in the `.changelog/` directory.\n' +
|
|
1008
|
-
'2) The `cwd` parameter points to the root of your project.\n' +
|
|
1009
|
-
'3) The `packagesDirectory` parameter correctly specifies the packages folder.\n' +
|
|
1010
|
-
'If no errors appear in the console but inputs are present, your project configuration may be incorrect.\n' +
|
|
1011
|
-
'If validation errors are shown, please resolve them according to the details provided.\n';
|
|
1012
|
-
super(message);
|
|
1013
|
-
}
|
|
1014
|
-
}
|
|
1015
|
-
|
|
1016
1094
|
/**
|
|
1017
1095
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
|
1018
1096
|
* For licensing, see LICENSE.md.
|
|
@@ -1031,7 +1109,13 @@ function filterVisibleSections(sectionsWithEntries) {
|
|
|
1031
1109
|
})
|
|
1032
1110
|
.map(([, section]) => section);
|
|
1033
1111
|
if (!sectionsToDisplay.length) {
|
|
1034
|
-
|
|
1112
|
+
const message = 'No valid entries were found. Please ensure that:\n' +
|
|
1113
|
+
'1) Input files exist in the `.changelog/` directory.\n' +
|
|
1114
|
+
'2) The `cwd` parameter points to the root of your project.\n' +
|
|
1115
|
+
'3) The `packagesDirectory` parameter correctly specifies the packages folder.\n' +
|
|
1116
|
+
'If no errors appear in the console but inputs are present, your project configuration may be incorrect.\n' +
|
|
1117
|
+
'If validation errors are shown, please resolve them according to the details provided.\n';
|
|
1118
|
+
throw new InternalError(message);
|
|
1035
1119
|
}
|
|
1036
1120
|
return sectionsToDisplay;
|
|
1037
1121
|
}
|
|
@@ -1058,13 +1142,12 @@ function getDateFormatted(date) {
|
|
|
1058
1142
|
* * A version header with a link to the GitHub comparison view (except for an initial version).
|
|
1059
1143
|
* * Sections with grouped changelog entries and their messages.
|
|
1060
1144
|
* * A collapsible summary of released packages and their version bumps for a mono-repository setup.
|
|
1061
|
-
* * Special handling for
|
|
1145
|
+
* * Special handling for single-package repositories.
|
|
1062
1146
|
*/
|
|
1063
1147
|
async function composeChangelog(options) {
|
|
1064
|
-
const { cwd, date, currentVersion, newVersion, sections, releasedPackagesInfo,
|
|
1148
|
+
const { cwd, date, currentVersion, newVersion, sections, releasedPackagesInfo, isSinglePackage } = options;
|
|
1065
1149
|
const gitHubUrl = await workspaces.getRepositoryUrl(cwd, { async: true });
|
|
1066
1150
|
const dateFormatted = getDateFormatted(date);
|
|
1067
|
-
const packagesNames = [...packagesMetadata.keys()];
|
|
1068
1151
|
const header = currentVersion === '0.0.1' ?
|
|
1069
1152
|
`## ${newVersion} (${dateFormatted})` :
|
|
1070
1153
|
`## [${newVersion}](${gitHubUrl}/compare/v${currentVersion}...v${newVersion}) (${dateFormatted})`;
|
|
@@ -1080,19 +1163,13 @@ async function composeChangelog(options) {
|
|
|
1080
1163
|
'',
|
|
1081
1164
|
...packages.map(packageName => `* [${packageName}](${NPM_URL}/${packageName}/v/${newVersion}): ${version}`)
|
|
1082
1165
|
])).flat().join('\n');
|
|
1083
|
-
const internalVersionsBumps = [
|
|
1084
|
-
'',
|
|
1085
|
-
SECTIONS.other.title + ':',
|
|
1086
|
-
'',
|
|
1087
|
-
packagesNames.map(name => `* [${name}](${NPM_URL}/${name}/v/${newVersion}): v${currentVersion} => v${newVersion}`)
|
|
1088
|
-
].flat().join('\n');
|
|
1089
1166
|
const changelog = [
|
|
1090
1167
|
header,
|
|
1091
1168
|
'',
|
|
1092
|
-
|
|
1169
|
+
sectionsAsString
|
|
1093
1170
|
];
|
|
1094
1171
|
if (!isSinglePackage) {
|
|
1095
|
-
changelog.push('### Released packages', '', `Check out the [Versioning policy](${VERSIONING_POLICY_URL}) guide for more information.`, '', '<details>', '<summary>Released packages (summary)</summary>',
|
|
1172
|
+
changelog.push('### Released packages', '', `Check out the [Versioning policy](${VERSIONING_POLICY_URL}) guide for more information.`, '', '<details>', '<summary>Released packages (summary)</summary>', packagesVersionBumps, '</details>', '');
|
|
1096
1173
|
}
|
|
1097
1174
|
return changelog.join('\n');
|
|
1098
1175
|
}
|
|
@@ -1112,6 +1189,40 @@ async function removeChangelogEntryFiles(entryPaths) {
|
|
|
1112
1189
|
.map(file => fs$1.unlink(file)));
|
|
1113
1190
|
}
|
|
1114
1191
|
|
|
1192
|
+
/**
|
|
1193
|
+
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
|
1194
|
+
* For licensing, see LICENSE.md.
|
|
1195
|
+
*/
|
|
1196
|
+
/**
|
|
1197
|
+
* Moves changelog entry files to cycle-specific directories instead of deleting them.
|
|
1198
|
+
* This preserves the history of changes across prerelease cycles.
|
|
1199
|
+
* Returns an array of entry paths that were modified by the move operation
|
|
1200
|
+
*/
|
|
1201
|
+
async function moveChangelogEntryFiles(entryPaths) {
|
|
1202
|
+
const targetDir = PRE_RELEASE_DIRECTORY;
|
|
1203
|
+
const modifiedEntryPaths = [];
|
|
1204
|
+
logInfo(`○ ${chalk.cyan(`Moving changelog entries to ${targetDir}/ directory...`)}`);
|
|
1205
|
+
for (const repo of entryPaths) {
|
|
1206
|
+
const { cwd, filePaths } = repo;
|
|
1207
|
+
const changelogDir = upath.join(cwd, CHANGESET_DIRECTORY);
|
|
1208
|
+
const targetPath = upath.join(changelogDir, targetDir);
|
|
1209
|
+
await fs$1.ensureDir(targetPath);
|
|
1210
|
+
const modifiedFilePaths = [];
|
|
1211
|
+
for (const filePath of filePaths) {
|
|
1212
|
+
const fileName = upath.basename(filePath);
|
|
1213
|
+
const targetFilePath = upath.join(targetPath, fileName);
|
|
1214
|
+
await fs$1.rename(filePath, targetFilePath);
|
|
1215
|
+
modifiedFilePaths.push(targetFilePath);
|
|
1216
|
+
modifiedFilePaths.push(filePath);
|
|
1217
|
+
}
|
|
1218
|
+
modifiedEntryPaths.push({
|
|
1219
|
+
...repo,
|
|
1220
|
+
filePaths: modifiedFilePaths
|
|
1221
|
+
});
|
|
1222
|
+
}
|
|
1223
|
+
return modifiedEntryPaths;
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1115
1226
|
/**
|
|
1116
1227
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
|
1117
1228
|
* For licensing, see LICENSE.md.
|
|
@@ -1134,6 +1245,61 @@ async function commitChanges(version, repositories) {
|
|
|
1134
1245
|
}
|
|
1135
1246
|
}
|
|
1136
1247
|
|
|
1248
|
+
/**
|
|
1249
|
+
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
|
1250
|
+
* For licensing, see LICENSE.md.
|
|
1251
|
+
*/
|
|
1252
|
+
/**
|
|
1253
|
+
* Prompts the user to choose between latest or prerelease
|
|
1254
|
+
*/
|
|
1255
|
+
async function promptReleaseType(currentVersion) {
|
|
1256
|
+
const { releaseType } = await inquirer.prompt([
|
|
1257
|
+
{
|
|
1258
|
+
type: 'list',
|
|
1259
|
+
name: 'releaseType',
|
|
1260
|
+
message: 'Please select the release type.',
|
|
1261
|
+
choices: getQuestions(currentVersion)
|
|
1262
|
+
}
|
|
1263
|
+
]);
|
|
1264
|
+
return releaseType;
|
|
1265
|
+
}
|
|
1266
|
+
function getQuestions(currentVersion) {
|
|
1267
|
+
const currentVersionPrerelease = semver.prerelease(currentVersion);
|
|
1268
|
+
if (!currentVersionPrerelease) {
|
|
1269
|
+
return [
|
|
1270
|
+
{ name: 'Latest (stable) release (e.g. 1.0.0 -> 2.0.0)', value: 'latest' },
|
|
1271
|
+
{ name: 'Pre-release (e.g. 1.0.0 -> 2.0.0-alpha.0)', value: 'prerelease' }
|
|
1272
|
+
];
|
|
1273
|
+
}
|
|
1274
|
+
if (currentVersionPrerelease[0] === 'rc') {
|
|
1275
|
+
return [
|
|
1276
|
+
{ name: 'Latest (stable) release (e.g. 1.0.0-beta.2 -> 1.0.0)', value: 'latest' },
|
|
1277
|
+
{ name: 'Pre-release continuation (e.g. 1.0.0-alpha.0 -> 1.0.0-alpha.1)', value: 'prerelease' }
|
|
1278
|
+
];
|
|
1279
|
+
}
|
|
1280
|
+
return [
|
|
1281
|
+
{ name: 'Latest (stable) release (e.g. 1.0.0-beta.2 -> 1.0.0)', value: 'latest' },
|
|
1282
|
+
{ name: 'Pre-release continuation (e.g. 1.0.0-alpha.0 -> 1.0.0-alpha.1)', value: 'prerelease' },
|
|
1283
|
+
{ name: 'Pre-release promotion (e.g. 1.0.0-alpha.1 -> 1.0.0-beta.0)', value: 'prerelease-promote' }
|
|
1284
|
+
];
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
/**
|
|
1288
|
+
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
|
1289
|
+
* For licensing, see LICENSE.md.
|
|
1290
|
+
*/
|
|
1291
|
+
function getReleaseType(currentVersion, nextVersion) {
|
|
1292
|
+
const [currentChannel] = semver.prerelease(currentVersion) || ['latest'];
|
|
1293
|
+
const [nextChannel] = semver.prerelease(nextVersion) || ['latest'];
|
|
1294
|
+
if (nextChannel === 'latest') {
|
|
1295
|
+
return 'latest';
|
|
1296
|
+
}
|
|
1297
|
+
if (nextChannel === currentChannel) {
|
|
1298
|
+
return 'prerelease';
|
|
1299
|
+
}
|
|
1300
|
+
return 'prerelease-promote';
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1137
1303
|
/**
|
|
1138
1304
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
|
1139
1305
|
* For licensing, see LICENSE.md.
|
|
@@ -1156,7 +1322,7 @@ async function commitChanges(version, repositories) {
|
|
|
1156
1322
|
* and the assembled changelog object will be returned instead.
|
|
1157
1323
|
*/
|
|
1158
1324
|
const main = async (options) => {
|
|
1159
|
-
const { nextVersion, packagesDirectory, isSinglePackage, transformScope, npmPackageToCheck, cwd = process.cwd(), externalRepositories = [], date = format(new Date(), 'yyyy-MM-dd'),
|
|
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;
|
|
1160
1326
|
const { version: currentVersion, name: rootPackageName } = await workspaces.getPackageJson(cwd, { async: true });
|
|
1161
1327
|
const packagesMetadata = await findPackages({
|
|
1162
1328
|
cwd,
|
|
@@ -1164,10 +1330,13 @@ const main = async (options) => {
|
|
|
1164
1330
|
shouldIgnoreRootPackage,
|
|
1165
1331
|
externalRepositories
|
|
1166
1332
|
});
|
|
1333
|
+
const releaseType = nextVersion ? getReleaseType(currentVersion, nextVersion) : await promptReleaseType(currentVersion);
|
|
1167
1334
|
const entryPaths = await findChangelogEntryPaths({
|
|
1168
1335
|
cwd,
|
|
1169
1336
|
externalRepositories,
|
|
1170
|
-
|
|
1337
|
+
linkFilter,
|
|
1338
|
+
shouldSkipLinks,
|
|
1339
|
+
includeSubdirectories: releaseType === 'latest' || releaseType === 'prerelease-promote'
|
|
1171
1340
|
});
|
|
1172
1341
|
const parsedChangesetFiles = await parseChangelogEntries(entryPaths, isSinglePackage);
|
|
1173
1342
|
const sectionsWithEntries = groupEntriesBySection({
|
|
@@ -1191,9 +1360,10 @@ const main = async (options) => {
|
|
|
1191
1360
|
});
|
|
1192
1361
|
}
|
|
1193
1362
|
// Display a prompt to provide a new version in the console.
|
|
1194
|
-
const
|
|
1363
|
+
const newVersion = await determineNextVersion({
|
|
1195
1364
|
currentVersion,
|
|
1196
1365
|
nextVersion,
|
|
1366
|
+
releaseType,
|
|
1197
1367
|
sections: sectionsWithEntries,
|
|
1198
1368
|
packageName: shouldIgnoreRootPackage ? npmPackageToCheck : rootPackageName
|
|
1199
1369
|
});
|
|
@@ -1208,18 +1378,23 @@ const main = async (options) => {
|
|
|
1208
1378
|
cwd,
|
|
1209
1379
|
date,
|
|
1210
1380
|
newVersion,
|
|
1211
|
-
isInternal,
|
|
1212
1381
|
isSinglePackage,
|
|
1213
|
-
packagesMetadata,
|
|
1214
1382
|
releasedPackagesInfo,
|
|
1215
1383
|
sections: filterVisibleSections(sectionsWithEntries)
|
|
1216
1384
|
});
|
|
1217
1385
|
if (disableFilesystemOperations) {
|
|
1218
1386
|
return newChangelog;
|
|
1219
1387
|
}
|
|
1220
|
-
|
|
1388
|
+
let pathsToCommit = entryPaths;
|
|
1389
|
+
// Handle changelog entry files based on release type.
|
|
1390
|
+
if (releaseType === 'latest') {
|
|
1391
|
+
await removeChangelogEntryFiles(entryPaths);
|
|
1392
|
+
}
|
|
1393
|
+
else {
|
|
1394
|
+
pathsToCommit = await moveChangelogEntryFiles(entryPaths);
|
|
1395
|
+
}
|
|
1221
1396
|
await modifyChangelog(newChangelog, cwd);
|
|
1222
|
-
await commitChanges(newVersion,
|
|
1397
|
+
await commitChanges(newVersion, pathsToCommit.map(({ cwd, isRoot, filePaths }) => ({ cwd, isRoot, filePaths })));
|
|
1223
1398
|
logInfo('○ ' + chalk.green('Done!'));
|
|
1224
1399
|
};
|
|
1225
1400
|
/**
|
|
@@ -1263,7 +1438,7 @@ function isExpectedError(error) {
|
|
|
1263
1438
|
* For licensing, see LICENSE.md.
|
|
1264
1439
|
*/
|
|
1265
1440
|
const generateChangelogForMonoRepository = async (options) => {
|
|
1266
|
-
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;
|
|
1267
1442
|
return generateChangelog({
|
|
1268
1443
|
nextVersion,
|
|
1269
1444
|
cwd,
|
|
@@ -1271,6 +1446,7 @@ const generateChangelogForMonoRepository = async (options) => {
|
|
|
1271
1446
|
externalRepositories,
|
|
1272
1447
|
transformScope,
|
|
1273
1448
|
date,
|
|
1449
|
+
linkFilter,
|
|
1274
1450
|
shouldSkipLinks,
|
|
1275
1451
|
disableFilesystemOperations,
|
|
1276
1452
|
...(shouldIgnoreRootPackage && npmPackageToCheck ?
|
|
@@ -1285,12 +1461,13 @@ const generateChangelogForMonoRepository = async (options) => {
|
|
|
1285
1461
|
* For licensing, see LICENSE.md.
|
|
1286
1462
|
*/
|
|
1287
1463
|
const generateChangelogForSingleRepository = async (options) => {
|
|
1288
|
-
const { cwd, date, externalRepositories, nextVersion, disableFilesystemOperations, shouldSkipLinks } = options;
|
|
1464
|
+
const { cwd, date, externalRepositories, nextVersion, disableFilesystemOperations, linkFilter, shouldSkipLinks } = options;
|
|
1289
1465
|
return generateChangelog({
|
|
1290
1466
|
nextVersion,
|
|
1291
1467
|
cwd,
|
|
1292
1468
|
externalRepositories,
|
|
1293
1469
|
date,
|
|
1470
|
+
linkFilter,
|
|
1294
1471
|
shouldSkipLinks,
|
|
1295
1472
|
disableFilesystemOperations,
|
|
1296
1473
|
isSinglePackage: true,
|
package/dist/types.d.ts
CHANGED
|
@@ -6,9 +6,9 @@ import type { SECTIONS } from './utils/constants.js';
|
|
|
6
6
|
export type ConfigBase = RepositoryConfig & {
|
|
7
7
|
/**
|
|
8
8
|
* The next version number to use. If not provided, will be calculated based on changes.
|
|
9
|
-
*
|
|
9
|
+
* Must be a valid version in terms of the semantic versioning specification.
|
|
10
10
|
*/
|
|
11
|
-
nextVersion?: string
|
|
11
|
+
nextVersion?: string;
|
|
12
12
|
/**
|
|
13
13
|
* Array of external repository configurations to include in the changelog.
|
|
14
14
|
*/
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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>;
|
|
@@ -117,4 +124,8 @@ export type FileMetadata = {
|
|
|
117
124
|
communityCredits: Array<string>;
|
|
118
125
|
validations: Array<string>;
|
|
119
126
|
};
|
|
127
|
+
export type ChangelogReleaseType = 'latest' | // e.g. 1.0.0 -> 2.0.0 or 2.0.0-beta.1 -> 2.0.0.
|
|
128
|
+
'prerelease' | // e.g. 1.0.0 -> 2.0.0-alpha.0 or 2.0.0-alpha.0 -> 2.0.0-alpha.1.
|
|
129
|
+
'prerelease-promote';
|
|
130
|
+
export type ReleaseChannel = 'alpha' | 'beta' | 'rc' | 'latest';
|
|
120
131
|
export {};
|
|
@@ -3,16 +3,14 @@
|
|
|
3
3
|
* For licensing, see LICENSE.md.
|
|
4
4
|
*/
|
|
5
5
|
import type { ReleaseInfo, Section } from '../types.js';
|
|
6
|
-
type ComposeChangelogOptions = {
|
|
6
|
+
export type ComposeChangelogOptions = {
|
|
7
7
|
cwd: string;
|
|
8
8
|
date: string;
|
|
9
9
|
currentVersion: string;
|
|
10
10
|
newVersion: string;
|
|
11
11
|
sections: Array<Section>;
|
|
12
12
|
releasedPackagesInfo: Array<ReleaseInfo>;
|
|
13
|
-
isInternal: boolean;
|
|
14
13
|
isSinglePackage: boolean;
|
|
15
|
-
packagesMetadata: Map<string, string>;
|
|
16
14
|
};
|
|
17
15
|
/**
|
|
18
16
|
* Generates a formatted changelog string for a new version release.
|
|
@@ -21,7 +19,6 @@ type ComposeChangelogOptions = {
|
|
|
21
19
|
* * A version header with a link to the GitHub comparison view (except for an initial version).
|
|
22
20
|
* * Sections with grouped changelog entries and their messages.
|
|
23
21
|
* * A collapsible summary of released packages and their version bumps for a mono-repository setup.
|
|
24
|
-
* * Special handling for
|
|
22
|
+
* * Special handling for single-package repositories.
|
|
25
23
|
*/
|
|
26
24
|
export declare function composeChangelog(options: ComposeChangelogOptions): Promise<string>;
|
|
27
|
-
export {};
|
|
@@ -7,6 +7,7 @@ export declare const CHANGELOG_HEADER = "Changelog\n=========";
|
|
|
7
7
|
export declare const NPM_URL = "https://www.npmjs.com/package";
|
|
8
8
|
export declare const VERSIONING_POLICY_URL = "https://ckeditor.com/docs/ckeditor5/latest/framework/guides/support/versioning-policy.html";
|
|
9
9
|
export declare const CHANGESET_DIRECTORY = ".changelog";
|
|
10
|
+
export declare const PRE_RELEASE_DIRECTORY = "pre-release";
|
|
10
11
|
export declare const TEMPLATE_FILE: string;
|
|
11
12
|
export declare const SECTIONS: {
|
|
12
13
|
readonly major: {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
|
+
* For licensing, see LICENSE.md.
|
|
4
|
+
*/
|
|
5
|
+
import type { ReleaseChannel } from '../types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Detects the release channel from a version string.
|
|
8
|
+
*/
|
|
9
|
+
export declare function detectReleaseChannel(version: string, promotePrerelease?: boolean): ReleaseChannel;
|
|
@@ -2,25 +2,21 @@
|
|
|
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 { SectionsWithEntries } from '../types.js';
|
|
6
|
-
type NextVersionOutput = {
|
|
7
|
-
isInternal: boolean;
|
|
8
|
-
newVersion: string;
|
|
9
|
-
};
|
|
5
|
+
import type { ChangelogReleaseType, SectionsWithEntries } from '../types.js';
|
|
10
6
|
export type DetermineNextVersionOptions = {
|
|
11
7
|
sections: SectionsWithEntries;
|
|
12
8
|
currentVersion: string;
|
|
13
9
|
packageName: string;
|
|
14
10
|
nextVersion: string | undefined;
|
|
11
|
+
releaseType: ChangelogReleaseType;
|
|
15
12
|
};
|
|
16
13
|
/**
|
|
17
14
|
* Determines the next version for a single package or a mono-repository setup based on
|
|
18
|
-
* the change sections,
|
|
15
|
+
* the change sections, user input, and semantic versioning rules.
|
|
19
16
|
*
|
|
20
17
|
* The function handles:
|
|
21
18
|
* * Automatic version bump calculation from categorized changelog sections (major, minor, patch).
|
|
22
|
-
* *
|
|
19
|
+
* * Version bump for prerelease channels.
|
|
23
20
|
* * User prompts for version input when no explicit version is provided.
|
|
24
21
|
*/
|
|
25
|
-
export declare function determineNextVersion(options: DetermineNextVersionOptions): Promise<
|
|
26
|
-
export {};
|
|
22
|
+
export declare function determineNextVersion(options: DetermineNextVersionOptions): Promise<string>;
|
|
@@ -2,11 +2,13 @@
|
|
|
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
|
-
|
|
9
|
+
linkFilter?: LinkFilter;
|
|
10
|
+
shouldSkipLinks?: boolean;
|
|
11
|
+
includeSubdirectories?: boolean;
|
|
10
12
|
};
|
|
11
13
|
/**
|
|
12
14
|
* Gathers changelog entry file paths (Markdown files) from the main repository and any configured external repositories.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
|
+
* For licensing, see LICENSE.md.
|
|
4
|
+
*/
|
|
5
|
+
import { type ChangelogReleaseType } from '../types.js';
|
|
6
|
+
export declare function getReleaseType(currentVersion: string, nextVersion: string): ChangelogReleaseType;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
|
+
* For licensing, see LICENSE.md.
|
|
4
|
+
*/
|
|
5
|
+
import type { ChangesetPathsWithGithubUrl } from '../types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Moves changelog entry files to cycle-specific directories instead of deleting them.
|
|
8
|
+
* This preserves the history of changes across prerelease cycles.
|
|
9
|
+
* Returns an array of entry paths that were modified by the move operation
|
|
10
|
+
*/
|
|
11
|
+
export declare function moveChangelogEntryFiles(entryPaths: Array<ChangesetPathsWithGithubUrl>): Promise<Array<ChangesetPathsWithGithubUrl>>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
|
+
* For licensing, see LICENSE.md.
|
|
4
|
+
*/
|
|
5
|
+
import type { ChangelogReleaseType } from '../types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Prompts the user to choose between latest or prerelease
|
|
8
|
+
*/
|
|
9
|
+
export declare function promptReleaseType(currentVersion: string): Promise<ChangelogReleaseType>;
|
|
@@ -3,12 +3,15 @@
|
|
|
3
3
|
* For licensing, see LICENSE.md.
|
|
4
4
|
*/
|
|
5
5
|
import { type ReleaseType } from 'semver';
|
|
6
|
+
import type { ChangelogReleaseType, ReleaseChannel } from '../types.js';
|
|
6
7
|
type Options = {
|
|
7
8
|
packageName: string;
|
|
8
9
|
version: string;
|
|
9
10
|
bumpType: ReleaseType;
|
|
11
|
+
releaseChannel: ReleaseChannel;
|
|
10
12
|
indentLevel?: number;
|
|
11
13
|
displayValidationWarning: boolean;
|
|
14
|
+
releaseType: ChangelogReleaseType;
|
|
12
15
|
};
|
|
13
16
|
/**
|
|
14
17
|
* Prompts the user to provide a new version for a package.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
|
+
* For licensing, see LICENSE.md.
|
|
4
|
+
*/
|
|
5
|
+
import type { ChangelogReleaseType } from '../types.js';
|
|
6
|
+
type ValidateOptions = {
|
|
7
|
+
newVersion: string;
|
|
8
|
+
version: string;
|
|
9
|
+
releaseType: ChangelogReleaseType;
|
|
10
|
+
packageName: string;
|
|
11
|
+
suggestedVersion: string;
|
|
12
|
+
};
|
|
13
|
+
export declare function validateInputVersion(options: ValidateOptions): Promise<string | true>;
|
|
14
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ckeditor/ckeditor5-dev-changelog",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "51.1.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": "^
|
|
31
|
+
"@ckeditor/ckeditor5-dev-utils": "^51.1.0",
|
|
32
32
|
"chalk": "^5.0.0",
|
|
33
33
|
"date-fns": "^4.0.0",
|
|
34
34
|
"fs-extra": "^11.0.0",
|
package/template/template.md
CHANGED
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
#
|
|
10
10
|
# For guidance on breaking changes, see:
|
|
11
11
|
# https://ckeditor.com/docs/ckeditor5/latest/updating/versioning-policy.html#major-and-minor-breaking-changes
|
|
12
|
-
type:
|
|
12
|
+
type:
|
|
13
13
|
|
|
14
14
|
# Optional: Affected package(s), using short names.
|
|
15
|
-
#
|
|
15
|
+
# Leave empty when used in a single-package repository.
|
|
16
16
|
# Example: ckeditor5-core
|
|
17
17
|
scope:
|
|
18
18
|
-
|