From 3221ea70ea3a513207150c2b056953dd724aee08 Mon Sep 17 00:00:00 2001 From: scarf Date: Wed, 13 Mar 2024 00:26:34 +0900 Subject: [PATCH] feat: feature parity --- deno.lock | 29 +++++++++++++++++++++++ scripts/changelog/changelog_test.ts | 6 ++--- scripts/changelog/mod.ts | 25 ++++++++++---------- scripts/changelog/render_bbcode.ts | 1 + scripts/changelog/render_markdown.ts | 16 +++++++++++++ scripts/changelog/render_sts.ts | 20 ++++++++++++++++ scripts/changelog/semver.ts | 17 ++++++++++++++ scripts/changelog/semver_test.ts | 35 ++++++++++++++++++++++++++++ 8 files changed, 133 insertions(+), 16 deletions(-) create mode 100644 scripts/changelog/render_markdown.ts create mode 100644 scripts/changelog/render_sts.ts create mode 100644 scripts/changelog/semver.ts create mode 100644 scripts/changelog/semver_test.ts diff --git a/deno.lock b/deno.lock index 4692111..b5bc827 100644 --- a/deno.lock +++ b/deno.lock @@ -268,6 +268,35 @@ "https://deno.land/std@0.219.0/path/windows/resolve.ts": "8dae1dadfed9d46ff46cc337c9525c0c7d959fb400a6308f34595c45bdca1972", "https://deno.land/std@0.219.0/path/windows/to_file_url.ts": "40e560ee4854fe5a3d4d12976cef2f4e8914125c81b11f1108e127934ced502e", "https://deno.land/std@0.219.0/path/windows/to_namespaced_path.ts": "4ffa4fb6fae321448d5fe810b3ca741d84df4d7897e61ee29be961a6aac89a4c", + "https://deno.land/std@0.219.0/semver/_constants.ts": "5ef89c5f33e6095546ae3e57920592feefcb8372d4cc05542f6bf15a1977e3c9", + "https://deno.land/std@0.219.0/semver/_shared.ts": "5c53a675225cba9ad74ae2e17c124e333728fc2b551a13e8a32b99433b90c1c2", + "https://deno.land/std@0.219.0/semver/can_parse.ts": "d4a26f74be078f3ab10293b07bf022021a2f362b3e21b58422c214e7268110b2", + "https://deno.land/std@0.219.0/semver/compare.ts": "e8871844a35cc8fe16e883c16e5237e06a93aa4830ae10d06501abe63586fc57", + "https://deno.land/std@0.219.0/semver/constants.ts": "a0daa58502949654af044928f86288d8b27bd1880218e9faba7733ec0bde63ab", + "https://deno.land/std@0.219.0/semver/difference.ts": "be4f01b7745406408a16b708185a48c1c652cc87e0244b12a5ca75c5585db668", + "https://deno.land/std@0.219.0/semver/equals.ts": "8b9b18260c9a55feee9d3f9250fba345be922380f2e8f8009e455c394ce5e81d", + "https://deno.land/std@0.219.0/semver/format.ts": "26d3a357ac5abd73dee0fe7dbbac6107fbdce0a844370c7b1bcb673c92e46bf6", + "https://deno.land/std@0.219.0/semver/format_range.ts": "6ad2d0c27aac63dfb7efca6286a6ab7742accfb986cc53662047740f17dacfe5", + "https://deno.land/std@0.219.0/semver/greater_or_equal.ts": "89c26f68070896944676eb9704cbb617febc6ed693720282741d6859c3d1fe80", + "https://deno.land/std@0.219.0/semver/greater_than.ts": "d8c4a227cd28ea80a1de9c80215d7f3f95786fe1b196f0cb5ec91d6567adad27", + "https://deno.land/std@0.219.0/semver/increment.ts": "427a043be71d6481e45c1a3939b955e800924d70779cb297b872d9cbf9f0e46d", + "https://deno.land/std@0.219.0/semver/is_range.ts": "15dd9a8d6a8dee56dea6799d8c8210e06c0a38cc1a9aa6152aeea39ce45e2111", + "https://deno.land/std@0.219.0/semver/is_semver.ts": "57914027d6141e593eb04418aaabbfd6f4562a1c53c6c33a1743fa50ada8d849", + "https://deno.land/std@0.219.0/semver/less_or_equal.ts": "7dbf8190f37f3281048c30cf11e072a7af18685534ae88d295baa170b485bd90", + "https://deno.land/std@0.219.0/semver/less_than.ts": "b0c7902c54cecadcc7c1c80afc2f6a0f1bf0b3f53c8d2bfd11f01a3a414cccfe", + "https://deno.land/std@0.219.0/semver/max_satisfying.ts": "03e5182a7424c308ddbb410e4b927da0dabc4e07d4b5a72f7e9b26fb18a02152", + "https://deno.land/std@0.219.0/semver/min_satisfying.ts": "b6fadc9af17278289481c416e1eb135614f88063f4fc2b7b72b43eb3baa2f08f", + "https://deno.land/std@0.219.0/semver/mod.ts": "6e1f8854cec50c027037a597d3dd54af72e063f763ec0cbc4ea1e534a627ffae", + "https://deno.land/std@0.219.0/semver/not_equals.ts": "17147a6f68b9d14f4643c1e2150378ccf6954710309f9618f75b411752a8e13d", + "https://deno.land/std@0.219.0/semver/parse.ts": "b64052ff8ce0b0bba9ed97b835a224c828fc7ad227585c3e8c2bac72a07bf572", + "https://deno.land/std@0.219.0/semver/parse_range.ts": "5190afffc90cc14410ce2478fb81ed83b55d7e96b6fbbd69fc715c457082ec94", + "https://deno.land/std@0.219.0/semver/range_intersects.ts": "2c358f7c27b51960a9889be5462ec1cac44feeb5e40041a5c5a03700c0ddc017", + "https://deno.land/std@0.219.0/semver/range_max.ts": "4c43d018841ba67d018e515f0aef32658dab611a39fdc74e31b1e48709be281c", + "https://deno.land/std@0.219.0/semver/range_min.ts": "37c5e3dac7bd63812ae249add9ea815a351826f510d2baf391c225d1d8272d17", + "https://deno.land/std@0.219.0/semver/test_range.ts": "72ba2af827e4ad94db9a29e22e86cbec9b3f8519fc36fd6ce0d4308717536c70", + "https://deno.land/std@0.219.0/semver/try_parse.ts": "7e2a3594212445d9d6f6154f02288d66a0c0b79ce3e859c41f3d47e29dfa439a", + "https://deno.land/std@0.219.0/semver/try_parse_range.ts": "4f211f0ff4f5fdaa85622ab96c360123bbcf0e5a91a57eb7a8258af6b7a3c704", + "https://deno.land/std@0.219.0/semver/types.ts": "13e1e0c64a4ac76f0add74afee6240c92a7dba184e63e0bd4cb456afed8c7291", "https://deno.land/std@0.219.0/testing/asserts.ts": "0cb9c745d9b157bed062a4aa8647168d2221f6456c385a548b0ca24de9e0f3ca", "https://deno.land/x/cliffy@v1.0.0-rc.3/_utils/distance.ts": "02af166952c7c358ac83beae397aa2fbca4ad630aecfcd38d92edb1ea429f004", "https://deno.land/x/cliffy@v1.0.0-rc.3/command/_argument_types.ts": "ab269dacea2030f865a07c2a1e953ec437a64419a05bad1f1ddaab3f99752ead", diff --git a/scripts/changelog/changelog_test.ts b/scripts/changelog/changelog_test.ts index 17b287d..480d9de 100644 --- a/scripts/changelog/changelog_test.ts +++ b/scripts/changelog/changelog_test.ts @@ -6,7 +6,7 @@ import { renderBBCode } from "./render_bbcode.ts" export const exampleCommits = parseCommits([ "feat: asdf (#1234)", "feat!: test (#123)", - "fix(L10n): language stuff (#415)", + "fix(L10n): `language` stuff (#415)", ]) const exampleSections = getSections(exampleCommits) @@ -30,7 +30,7 @@ Deno.test("parseCommits() correctly parse commits", () => { type: "fix", scopes: "L10n", breaking: undefined, - subject: "language stuff", + subject: "`language` stuff", pr: "415", }, ]) @@ -55,7 +55,7 @@ Deno.test("renderBBCode() outputs identical text", () => [h2]Fixes[/h2] [list] - [*] language stuff ([url=https://github.com/scarf005/marisa/pull/415]#415[/url]) + [*] [i]language[/i] stuff ([url=https://github.com/scarf005/marisa/pull/415]#415[/url]) [/list] `, )) diff --git a/scripts/changelog/mod.ts b/scripts/changelog/mod.ts index eb2eceb..44183d0 100644 --- a/scripts/changelog/mod.ts +++ b/scripts/changelog/mod.ts @@ -3,6 +3,9 @@ import { typedRegEx } from "https://deno.land/x/typed_regex@0.2.0/mod.ts" import type { RegExCaptureResult } from "https://deno.land/x/typed_regex@0.2.0/type_parser.ts" import { renderBBCode } from "./render_bbcode.ts" +import { getNextVersion } from "./semver.ts" +import { renderMarkdown } from "./render_markdown.ts" +import { renderStS } from "./render_sts.ts" export type Commit = RegExCaptureResult export type Sections = Record @@ -33,17 +36,13 @@ export const getSections = (commits: Commit[]): Sections => ({ if (import.meta.main) { const [latestTag] = await getTags() const commits = await getCommits({ from: latestTag, to: "main" }).then(parseCommits) - - const sections: Sections = getSections(commits) - - console.log(latestTag) - console.log(sections) - console.log(commits) - console.log( - renderBBCode({ - version: "v1.0.0", - date: new Date().toISOString().split("T")[0], - sections, - }), - ) + const option = { + version: getNextVersion(latestTag, commits), + date: new Date().toISOString().split("T")[0], + sections: getSections(commits), + } + + for (const render of [renderBBCode, renderMarkdown, renderStS]) { + console.log(render(option), "\n") + } } diff --git a/scripts/changelog/render_bbcode.ts b/scripts/changelog/render_bbcode.ts index f3842ee..cb38f27 100644 --- a/scripts/changelog/render_bbcode.ts +++ b/scripts/changelog/render_bbcode.ts @@ -4,6 +4,7 @@ import { ChangelogRenderer, renderSections, SectionFormatter } from "./render.ts const fmtCommit = (x: Commit) => ` [*] ${x.subject} ([url=https://github.com/scarf005/marisa/pull/${x.pr}]#${x.pr}[/url])` + .replace(/`([^`]+)`/g, "[i]$1[/i]") const fmtSection: SectionFormatter = ([section, commits]) => `[h2]${section}[/h2]\n` + "[list]\n" + commits.map(fmtCommit).join("\n") + "\n[/list]" diff --git a/scripts/changelog/render_markdown.ts b/scripts/changelog/render_markdown.ts new file mode 100644 index 0000000..20f84a7 --- /dev/null +++ b/scripts/changelog/render_markdown.ts @@ -0,0 +1,16 @@ +import { outdent } from "$dax/src/deps.ts" +import { Commit } from "./mod.ts" +import { ChangelogRenderer, renderSections, SectionFormatter } from "./render.ts" + +const fmtCommit = (x: Commit) => + `- ${x.subject} (#${x.pr})` + +const fmtSection: SectionFormatter = ([section, commits]) => + `## ${section}\n\n` + commits.map(fmtCommit).join("\n") + +export const renderMarkdown: ChangelogRenderer = ({ version, date, sections }) => + outdent` + # ${version} (${date}) + + ${renderSections({ fmtSection, sections })} + ` diff --git a/scripts/changelog/render_sts.ts b/scripts/changelog/render_sts.ts new file mode 100644 index 0000000..13f31bc --- /dev/null +++ b/scripts/changelog/render_sts.ts @@ -0,0 +1,20 @@ +import { outdent } from "$dax/src/deps.ts" +import { Commit } from "./mod.ts" +import { ChangelogRenderer, renderSections, SectionFormatter } from "./render.ts" + +const fmtCommit = (x: Commit) => + `- ${x.subject}` + .replace(/`([^`]+)`/g, "[i]$1[/i]") + .replace(/\(#(\d+)\)/g, "") + +const fmtSection: SectionFormatter = ([section, commits]) => + `* ${section}\n\n` + commits.map(fmtCommit).join("\n") + +export const renderStS: ChangelogRenderer = ({ version, date, sections }) => + outdent` + What's new in ${version} (${date}) + + ${renderSections({ fmtSection, sections })} + + please visit https://github.com/scarf005/Marisa/releases/latest for more info + ` diff --git a/scripts/changelog/semver.ts b/scripts/changelog/semver.ts new file mode 100644 index 0000000..9882d98 --- /dev/null +++ b/scripts/changelog/semver.ts @@ -0,0 +1,17 @@ +import type { SemVer } from "$std/semver/types.ts" +import type { Commit } from "./mod.ts" + +import { format, increment, parse } from "$std/semver/mod.ts" + +const increaseBy = (commit: Commit): "major" | "minor" | "patch" => + commit.breaking ? "major" : commit.type === "feat" ? "minor" : "patch" + +export const increaseVersion = (begin: SemVer, commits: Commit[]): SemVer => + commits.reduce(({ ver, count }, commit) => { + const by = increaseBy(commit) + count[by]++ + return (count[by] > 1) ? { ver, count } : { ver: increment(ver, increaseBy(commit)), count } + }, { ver: begin, count: { major: 0, minor: 0, patch: 0 } }).ver + +export const getNextVersion = (latest: string, commits: Commit[]): string => + "v" + format(increaseVersion(parse(latest), commits)) diff --git a/scripts/changelog/semver_test.ts b/scripts/changelog/semver_test.ts new file mode 100644 index 0000000..c5558a0 --- /dev/null +++ b/scripts/changelog/semver_test.ts @@ -0,0 +1,35 @@ +import { assertObjectMatch } from "$std/assert/assert_object_match.ts" +import { assertEquals } from "$std/assert/assert_equals.ts" +import { getNextVersion, increaseVersion } from "./semver.ts" + +const major = { type: "fix", breaking: "!", subject: "big stuff", pr: "123", scopes: undefined } +const minor = { type: "feat", breaking: undefined, subject: "feat", pr: "124", scopes: undefined } +const patch = { type: "fix", breaking: undefined, subject: "fix", pr: "125", scopes: undefined } + +Deno.test("increaseVersion() only increases biggest change", async (t) => { + await t.step("major", () => { + assertObjectMatch( + increaseVersion({ major: 1, minor: 0, patch: 0 }, [ + minor, + patch, + major, + ]), + { major: 2, minor: 0, patch: 0 }, + ) + }) + + await t.step("minor", () => { + assertObjectMatch( + increaseVersion({ major: 1, minor: 0, patch: 0 }, [patch, minor]), + { major: 1, minor: 1, patch: 0 }, + ) + }) +}) + +Deno.test("nextVersion() returns correct version", () => { + assertEquals(getNextVersion("v1.0.0", [minor, patch]), "v1.1.1") +}) + +Deno.test("nextVersion() handles multiple patch in single release", () => { + assertEquals(getNextVersion("v1.0.0", [patch, patch, patch]), "v1.0.1") +})