diff --git a/packages/plugin-changelog/src/index.test.ts b/packages/plugin-changelog/src/index.test.ts index 11a6a4f..0f608ff 100644 --- a/packages/plugin-changelog/src/index.test.ts +++ b/packages/plugin-changelog/src/index.test.ts @@ -65,6 +65,8 @@ stuff readme_olderEntriesFooter: `Older entries are in [CHANGELOG_OLD.md](CHANGELOG_OLD.md).`, readme_olderEntriesFooterVariant: `Older entries have been moved to [CHANGELOG_OLD.md](CHANGELOG_OLD.md).`, readme_olderEntriesFooterCustomLabel: `See [the older changelog](CHANGELOG_OLD.md) for previous releases.`, + readme_trailingSection: `## License +MIT License`, }; describe("Changelog plugin", () => { @@ -366,6 +368,43 @@ ${fixtures.changelog_old_testParse2}`, expect(changelogAfter).toBe(`\n\n${fixtures.readme_olderEntriesFooterCustomLabel}`); }); + it("keeps the blank-line separation between the footer and a following section", async () => { + const changelogPlugin = new ChangelogPlugin(); + const context = createMockContext({ + plugins: [changelogPlugin], + cwd: testFSRoot, + }); + + await testFS.create({ + "README.md": `${fixtures.readme_testParseHeader} +${fixtures.readme_testParse1} + +${fixtures.readme_testParse2} + +${fixtures.readme_testParse3} + +${fixtures.readme_olderEntriesFooter} + +${fixtures.readme_trailingSection}`, + "CHANGELOG_OLD.md": `${fixtures.changelog_old_testParseHeader} +${fixtures.changelog_old_testParse1} + +${fixtures.changelog_old_testParse2}`, + }); + + await changelogPlugin.executeStage(context, DefaultStages.check); + expect(context.errors).toHaveLength(0); + + const entries = context.getData("changelog_entries"); + expect(entries[2]).toBe(fixtures.readme_testParse3); + + // The footer must keep one blank line before the following section + const changelogAfter = context.getData("changelog_after"); + expect(changelogAfter).toBe( + `\n\n${fixtures.readme_olderEntriesFooter}\n\n${fixtures.readme_trailingSection}`, + ); + }); + it("correctly handles changelogs with sub-sections", async () => { const changelogPlugin = new ChangelogPlugin(); const context = createMockContext({ @@ -608,6 +647,52 @@ ${fixtures.changelog_old_testParse1} ${fixtures.changelog_old_testParse2}`); }); + it("keeps a blank line between the footer and a following section when rotating", async () => { + const changelogPlugin = new ChangelogPlugin(); + const context = createMockContext({ + plugins: [changelogPlugin], + cwd: testFSRoot, + argv: { + numChangelogEntries: 2, + }, + }); + + context.setData("changelog_filename", "README.md"); + context.setData("changelog_location", "readme"); + context.setData("changelog_before", fixtures.readme_testParseHeader); + context.setData("changelog_entries", [ + fixtures.readme_testParse1, + fixtures.readme_testParse2, + fixtures.readme_testParse3, + fixtures.changelog_old_testParse1, + fixtures.changelog_old_testParse2, + ]); + // As produced by the check stage: footer followed by a trailing section + context.setData( + "changelog_after", + `\n\n${fixtures.readme_olderEntriesFooter}\n\n${fixtures.readme_trailingSection}`, + ); + context.setData("changelog_final_newline", false); + context.setData("changelog_old_before", fixtures.changelog_old_testParseHeader); + context.setData("changelog_old_after", ""); + context.setData("changelog_entry_prefix", "###"); + context.setData("version_new", "2.3.4"); + + await changelogPlugin.executeStage(context, DefaultStages.edit); + + const readmeContent = await fs.readFile(path.join(testFSRoot, "README.md"), "utf8"); + + // The footer and the following section must each keep one blank line around them + expect(readmeContent).toBe(`${fixtures.readme_testParseHeader} +${fixtures.readme_testReplaced} + +${fixtures.readme_testParse2} + +${fixtures.readme_olderEntriesFooter} + +${fixtures.readme_trailingSection}`); + }); + it("removes unnecessary blank linkes from the changelog", async () => { const changelogPlugin = new ChangelogPlugin(); const context = createMockContext({ diff --git a/packages/plugin-changelog/src/index.ts b/packages/plugin-changelog/src/index.ts index 4ddc275..a833fc3 100644 --- a/packages/plugin-changelog/src/index.ts +++ b/packages/plugin-changelog/src/index.ts @@ -168,7 +168,13 @@ class ChangelogPlugin implements Plugin { const footerMatch = olderEntriesFooterRegex.exec(parsed.entries[lastIndex]); if (footerMatch) { parsed.entries[lastIndex] = parsed.entries[lastIndex].slice(0, footerMatch.index); - parsed.after = "\n\n" + footerMatch[1] + parsed.after; + // Sections following the footer (e.g. a "## License" heading) were + // separated from it by a blank line that entry parsing trimmed away. + // Restore that separation so the footer doesn't get glued onto the + // next section. + const trailingSection = parsed.after.trimStart(); + parsed.after = + "\n\n" + footerMatch[1] + (trailingSection ? "\n\n" + trailingSection : ""); } }