From 3dadea4b5c554fb4645722595bbb968e94361126 Mon Sep 17 00:00:00 2001 From: luvs01 Date: Sun, 9 Aug 2026 15:49:22 +0900 Subject: [PATCH] fix(issue-quality): include duplicate translated sections --- .github/scripts/issue-quality.cjs | 34 ++++++++++++++++++-------- .github/scripts/issue-quality.test.cjs | 6 +++-- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/.github/scripts/issue-quality.cjs b/.github/scripts/issue-quality.cjs index 1c0a6430a..907a62c7f 100644 --- a/.github/scripts/issue-quality.cjs +++ b/.github/scripts/issue-quality.cjs @@ -428,17 +428,22 @@ function canonicalise(raw) { } /** - * Extract the text content of a markdown ### section by heading name. - * Returns null when the heading is absent. + * Extract the text content of every markdown section with the given heading. */ -function extractSection(body, heading) { - if (typeof body !== "string") return null; +function extractSections(body, heading) { + if (typeof body !== "string") return []; const lines = body.split("\n"); const headingLower = heading.toLowerCase().trim(); let capturing = false; let sectionDepth = 0; let fence = null; - const out = []; + let out = []; + const sections = []; + const flush = () => { + sections.push(out.join("\n").trim()); + out = []; + capturing = false; + }; for (const line of lines) { if (fence) { if (new RegExp(`^[ \\t]{0,3}${fence.marker}{${fence.length},}[ \\t]*$`).test(line)) { @@ -458,7 +463,7 @@ function extractSection(body, heading) { const m = line.match(/^(#{2,4})\s+(.*)/); if (m) { const depth = m[1].length; - if (capturing && depth <= sectionDepth) break; + if (capturing && depth <= sectionDepth) flush(); if (!capturing && m[2].toLowerCase().trim() === headingLower) { capturing = true; sectionDepth = depth; @@ -467,8 +472,16 @@ function extractSection(body, heading) { } if (capturing) out.push(line); } - if (!capturing) return null; - return out.join("\n").trim(); + if (capturing) flush(); + return sections; +} + +/** + * Extract the first markdown section with the given heading. + * Returns null when the heading is absent. + */ +function extractSection(body, heading) { + return extractSections(body, heading)[0] ?? null; } /** @@ -790,8 +803,9 @@ function bodyForAreaHeuristics(body) { if (typeof body !== "string" || !body.trim()) return ""; const parts = []; for (const heading of AREA_HEURISTIC_BODY_HEADINGS) { - const section = extractSection(body, heading); - if (section) parts.push(section); + for (const section of extractSections(body, heading)) { + if (section) parts.push(section); + } } return parts.join("\n\n"); } diff --git a/.github/scripts/issue-quality.test.cjs b/.github/scripts/issue-quality.test.cjs index 4f22c4247..c9297d1c1 100644 --- a/.github/scripts/issue-quality.test.cjs +++ b/.github/scripts/issue-quality.test.cjs @@ -2002,11 +2002,13 @@ describe("detectAreaLabels", () => { assert.equal(labels.includes("platform"), false); }); - it("uses heuristicBody translation text when Area is Other", () => { + it("uses appended heuristicBody translation text when Area is Other", () => { + const sourceBody = ["### Area", "Other", "### Summary", "原始描述"].join("\n"); const labels = detectAreaLabels({ title: "问题报告", - body: ["### Area", "Other", "### Summary", "原始描述"].join("\n"), + body: sourceBody, heuristicBody: [ + sourceBody, "### Area", "Other", "### Summary",