///|
/// A compact status badge for README, CI summary, or release notes.
pub(all) struct StatusBadge {
label : String
message : String
color : String
link : String
} derive(Eq, Debug)
///|
/// Create a status badge.
pub fn StatusBadge::new(
label : String,
message : String,
color? : String = "blue",
link? : String = "",
) -> StatusBadge {
{ label, message, color, link }
}
///|
/// Render a shields.io badge URL.
pub fn StatusBadge::url(self : StatusBadge) -> String {
"https://img.shields.io/badge/" +
badge_escape(self.label) +
"-" +
badge_escape(self.message) +
"-" +
badge_escape(self.color)
}
///|
fn badge_escape(value : String) -> String {
value
.replace(old="-", new="--")
.replace(old=" ", new="%20")
.replace(old="_", new="__")
.replace(old="/", new="%2F")
}
///|
/// Render badge Markdown.
pub fn StatusBadge::to_markdown(self : StatusBadge) -> String {
let image = "})"
if self.link == "" {
image
} else {
"[\{image}](\{self.link})"
}
}
///|
/// Render badge JSON.
pub fn StatusBadge::to_json(self : StatusBadge) -> String {
"{" +
"\"label\":\"\{escape_json(self.label)}\"," +
"\"message\":\"\{escape_json(self.message)}\"," +
"\"color\":\"\{escape_json(self.color)}\"," +
"\"link\":\"\{escape_json(self.link)}\"," +
"\"url\":\"\{escape_json(self.url())}\"" +
"}"
}
///|
/// A collection of badges.
pub(all) struct BadgeSet {
badges : Array[StatusBadge]
} derive(Eq, Debug)
///|
/// Create an empty badge set.
pub fn BadgeSet::new() -> BadgeSet {
{ badges: [] }
}
///|
/// Append a badge.
pub fn BadgeSet::add(self : BadgeSet, badge : StatusBadge) -> BadgeSet {
let badges = self.badges.copy()
badges.push(badge)
{ badges, }
}
///|
/// Number of badges.
pub fn BadgeSet::count(self : BadgeSet) -> Int {
self.badges.length()
}
///|
/// Render all badges as one Markdown line.
pub fn BadgeSet::to_markdown(self : BadgeSet) -> String {
let mut body = ""
for i in 0.. 0 {
body = body + " "
}
body = body + self.badges[i].to_markdown()
}
body
}
///|
/// Render badges as JSON.
pub fn BadgeSet::to_json(self : BadgeSet) -> String {
let mut body = "{\"badges\":["
for i in 0.. 0 {
body = body + ","
}
body = body + self.badges[i].to_json()
}
body + "]}"
}
///|
/// Standard badges for MoonBench.
pub fn BadgeSet::moonbench_standard() -> BadgeSet {
BadgeSet::new()
.add(
StatusBadge::new(
"MoonBit",
"0.1.20260703",
color="blue",
link="https://www.moonbitlang.com/",
),
)
.add(
StatusBadge::new(
"tests",
"passing",
color="brightgreen",
link="https://github.com/Han-Wentao/moonbench/actions",
),
)
.add(
StatusBadge::new(
"mooncakes",
"published",
color="success",
link="https://mooncakes.io/docs/Han-Wentao/moonbench",
),
)
.add(StatusBadge::new("license", "MIT", color="green", link="LICENSE"))
}
///|
/// A release note entry.
pub(all) struct ReleaseNoteEntry {
kind : String
title : String
detail : String
issue : String
} derive(Eq, Debug)
///|
/// Create a release note entry.
pub fn ReleaseNoteEntry::new(
kind : String,
title : String,
detail? : String = "",
issue? : String = "",
) -> ReleaseNoteEntry {
{ kind, title, detail, issue }
}
///|
/// Render release note entry as Markdown bullet.
pub fn ReleaseNoteEntry::to_markdown(self : ReleaseNoteEntry) -> String {
let mut body = "- **\{escape_markdown(self.kind)}**: \{escape_markdown(self.title)}"
if self.issue != "" {
body = body + " (\{escape_markdown(self.issue)})"
}
if self.detail != "" {
body = body + "\n \{escape_markdown(self.detail)}"
}
body + "\n"
}
///|
/// Render release note entry as JSON.
pub fn ReleaseNoteEntry::to_json(self : ReleaseNoteEntry) -> String {
"{" +
"\"kind\":\"\{escape_json(self.kind)}\"," +
"\"title\":\"\{escape_json(self.title)}\"," +
"\"detail\":\"\{escape_json(self.detail)}\"," +
"\"issue\":\"\{escape_json(self.issue)}\"" +
"}"
}
///|
/// Release notes for a package version.
pub(all) struct ReleaseNotes {
version : String
date : String
entries : Array[ReleaseNoteEntry]
} derive(Eq, Debug)
///|
/// Create release notes.
pub fn ReleaseNotes::new(version : String, date? : String = "") -> ReleaseNotes {
{ version, date, entries: [] }
}
///|
/// Append a release note entry.
pub fn ReleaseNotes::add(
self : ReleaseNotes,
entry : ReleaseNoteEntry,
) -> ReleaseNotes {
let entries = self.entries.copy()
entries.push(entry)
{ ..self, entries, }
}
///|
/// Count entries.
pub fn ReleaseNotes::count(self : ReleaseNotes) -> Int {
self.entries.length()
}
///|
/// Count entries by kind.
pub fn ReleaseNotes::count_kind(self : ReleaseNotes, kind : String) -> Int {
for entry in self.entries; acc = 0 {
if entry.kind == kind {
continue acc + 1
} else {
continue acc
}
} nobreak {
acc
}
}
///|
/// Render release notes as Markdown.
pub fn ReleaseNotes::to_markdown(self : ReleaseNotes) -> String {
let mut body = "## Version \{escape_markdown(self.version)}\n\n"
if self.date != "" {
body = body + "- Date: \{escape_markdown(self.date)}\n"
}
body = body + "- Entries: \{self.count()}\n\n"
for entry in self.entries {
body = body + entry.to_markdown()
}
body
}
///|
/// Render release notes as JSON.
pub fn ReleaseNotes::to_json(self : ReleaseNotes) -> String {
let mut body = "{"
body = body + "\"version\":\"\{escape_json(self.version)}\","
body = body + "\"date\":\"\{escape_json(self.date)}\","
body = body + "\"entries\":["
for i in 0.. 0 {
body = body + ","
}
body = body + self.entries[i].to_json()
}
body + "]}"
}
///|
/// Standard release notes for MoonBench 0.2.0.
pub fn ReleaseNotes::moonbench_0_2_0() -> ReleaseNotes {
ReleaseNotes::new("0.2.0", date="2026-07-08")
.add(
ReleaseNoteEntry::new(
"feature",
"BenchmarkSuite multi-result reporting",
detail="Render grouped benchmark results as Markdown, JSON, and CSV.",
),
)
.add(
ReleaseNoteEntry::new(
"feature",
"Trend analysis and quality gates",
detail="Analyze noisy samples and evaluate performance regressions with threshold policies.",
),
)
.add(
ReleaseNoteEntry::new(
"feature",
"Submission artifact helpers",
detail="Describe contest artifacts, checklists, badges, and generated reports.",
),
)
.add(
ReleaseNoteEntry::new(
"feature",
"Scenario catalog",
detail="Provide a reusable catalog of benchmark workload scenarios.",
),
)
.add(
ReleaseNoteEntry::new(
"test",
"Expanded test coverage",
detail="Cover suite, baseline, gate, artifact, and scenario behavior.",
),
)
.add(
ReleaseNoteEntry::new(
"docs",
"Chinese contest documentation",
detail="Rewrite README, package docs, project proposal, and development report in Chinese.",
),
)
}
///|
/// Standard release notes for MoonBench 0.3.0.
pub fn ReleaseNotes::moonbench_0_3_0() -> ReleaseNotes {
ReleaseNotes::new("0.3.0", date="2026-07-14")
.add(
ReleaseNoteEntry::new(
"feature",
"Portable baseline files",
detail="Import and export version-controlled name=mean_us baseline documents.",
),
)
.add(
ReleaseNoteEntry::new(
"feature",
"Baseline parse diagnostics",
detail="Report invalid line numbers and reasons while preserving valid entries.",
),
)
.add(
ReleaseNoteEntry::new(
"fix",
"Standards-compliant JSON escaping",
detail="Escape common control characters in generated JSON documents.",
),
)
.add(
ReleaseNoteEntry::new(
"test",
"Baseline round-trip coverage",
detail="Cover duplicate replacement, malformed values, and control characters.",
),
)
.add(
ReleaseNoteEntry::new(
"docs",
"Baseline workflow documentation",
detail="Document local and CI baseline sharing in package and repository guides.",
),
)
}
///|
/// A summary card for judges and project reviewers.
pub(all) struct ReviewerSummary {
project : String
package_name : String
version : String
github_url : String
package_url : String
highlights : Array[String]
verification : Array[String]
} derive(Eq, Debug)
///|
/// Create a reviewer summary.
pub fn ReviewerSummary::new(
project? : String = "MoonBench",
package_name? : String = "Han-Wentao/moonbench",
version? : String = "0.3.0",
github_url? : String = "https://github.com/Han-Wentao/moonbench",
package_url? : String = "https://mooncakes.io/docs/Han-Wentao/moonbench",
) -> ReviewerSummary {
{
project,
package_name,
version,
github_url,
package_url,
highlights: [],
verification: [],
}
}
///|
/// Add a highlight.
pub fn ReviewerSummary::add_highlight(
self : ReviewerSummary,
highlight : String,
) -> ReviewerSummary {
let highlights = self.highlights.copy()
highlights.push(highlight)
{ ..self, highlights, }
}
///|
/// Add a verification command or evidence line.
pub fn ReviewerSummary::add_verification(
self : ReviewerSummary,
line : String,
) -> ReviewerSummary {
let verification = self.verification.copy()
verification.push(line)
{ ..self, verification, }
}
///|
/// Render reviewer summary as Markdown.
pub fn ReviewerSummary::to_markdown(self : ReviewerSummary) -> String {
let mut body = "## \{escape_markdown(self.project)} 评审摘要\n\n"
body = body + "- 包名:`\{escape_markdown(self.package_name)}`\n"
body = body + "- 版本:`\{escape_markdown(self.version)}`\n"
body = body + "- GitHub:\{self.github_url}\n"
body = body + "- mooncakes.io:\{self.package_url}\n\n"
body = body + "### 亮点\n\n"
for highlight in self.highlights {
body = body + "- \{escape_markdown(highlight)}\n"
}
body = body + "\n### 验证\n\n"
for line in self.verification {
body = body + "- `\{escape_markdown(line)}`\n"
}
body
}
///|
/// Render reviewer summary as JSON.
pub fn ReviewerSummary::to_json(self : ReviewerSummary) -> String {
"{" +
"\"project\":\"\{escape_json(self.project)}\"," +
"\"package_name\":\"\{escape_json(self.package_name)}\"," +
"\"version\":\"\{escape_json(self.version)}\"," +
"\"github_url\":\"\{escape_json(self.github_url)}\"," +
"\"package_url\":\"\{escape_json(self.package_url)}\"," +
"\"highlights\":\{string_array_to_json(self.highlights)}," +
"\"verification\":\{string_array_to_json(self.verification)}" +
"}"
}
///|
/// Standard reviewer summary for MoonBench.
pub fn ReviewerSummary::moonbench_standard() -> ReviewerSummary {
ReviewerSummary::new()
.add_highlight("MoonBit 原生实现的性能报告工具包")
.add_highlight(
"支持 Stopwatch、SampleStats、BenchmarkRunner、BenchmarkSuite",
)
.add_highlight("支持 Markdown、JSON、CSV 三类输出")
.add_highlight("支持历史基线对比、趋势分析和质量门禁")
.add_highlight("支持可版本控制的基线文本和逐行解析诊断")
.add_highlight(
"提供中文 README、开发报告、项目方案和提交清单",
)
.add_verification("moon check")
.add_verification("moon test")
.add_verification("moon run cmd/main")
.add_verification("moon run examples/basic")
.add_verification("moon package")
}
///|
/// A GitHub step summary document.
pub(all) struct GitHubStepSummary {
title : String
badges : BadgeSet
reviewer_summary : ReviewerSummary
suite : BenchmarkSuite
gate : GateReport
} derive(Eq, Debug)
///|
/// Create a GitHub step summary.
pub fn GitHubStepSummary::new(
title? : String = "MoonBench CI Summary",
badges? : BadgeSet = BadgeSet::moonbench_standard(),
reviewer_summary? : ReviewerSummary = ReviewerSummary::moonbench_standard(),
suite? : BenchmarkSuite = BenchmarkSuite::new(title="Empty Suite"),
gate? : GateReport = GateReport::new(),
) -> GitHubStepSummary {
{ title, badges, reviewer_summary, suite, gate }
}
///|
/// Render GitHub step summary Markdown.
pub fn GitHubStepSummary::to_markdown(self : GitHubStepSummary) -> String {
"# \{escape_markdown(self.title)}\n\n" +
self.badges.to_markdown() +
"\n\n" +
self.reviewer_summary.to_markdown() +
"\n\n" +
self.suite.to_markdown() +
"\n\n" +
self.gate.to_markdown()
}
///|
/// Render GitHub step summary JSON metadata.
pub fn GitHubStepSummary::to_json(self : GitHubStepSummary) -> String {
"{" +
"\"title\":\"\{escape_json(self.title)}\"," +
"\"badges\":\{self.badges.to_json()}," +
"\"reviewer_summary\":\{self.reviewer_summary.to_json()}," +
"\"suite\":\{self.suite.to_json()}," +
"\"gate\":\{self.gate.to_json()}" +
"}"
}