diff --git a/.github/scripts/issue-version-triage.cjs b/.github/scripts/issue-version-triage.cjs index 4eee3e6027..bd4d9539b3 100644 --- a/.github/scripts/issue-version-triage.cjs +++ b/.github/scripts/issue-version-triage.cjs @@ -59,7 +59,47 @@ function stripHTMLComments(value) { let previous; do { previous = stripped; - stripped = stripped.replace(/|$)/g, ""); + let fence = null; + let inComment = false; + // Strip hidden template text, not literal markers in pasted code. In + // particular, an unfinished HTML response must not swallow the real form + // fields after its closing Markdown fence. Match the same fences and + // indentation that declarationLines excludes from metadata declarations. + stripped = stripped.split(/(\r?\n)/).map((text, index) => { + if (index % 2) return text; + const marker = text.match(/^ {0,3}(`{3,}|~{3,})(.*)$/); + if (!inComment) { + if (fence) { + if (marker && marker[1][0] === fence.character && + marker[1].length >= fence.length && !marker[2].trim()) { + fence = null; + } + return text; + } + if (marker && (marker[1][0] === "~" || !marker[2].includes("`"))) { + fence = { character: marker[1][0], length: marker[1].length }; + return text; + } + if (/^(?: {4}|\t)/.test(text)) return text; + } + let visible = ""; + let offset = 0; + while (offset < text.length) { + if (inComment) { + const end = text.indexOf("-->", offset); + if (end === -1) break; + offset = end + 3; + inComment = false; + } else { + const start = text.indexOf("", "-->"]) { + const body = [open, marker, "### Pulse version", "6.4.1", close, "", + "### Pulse version", "6.5.0", "### Feedback type", "Documentation issue", + "### Additional actionable topics", "Missing disk reading"].join(newline); + assert.equal(extractPulseVersion("Upgrade from v6.4.5", body), "6.5.0", body); + assert.equal(classifyV6FeedbackType(body), "documentation", body); + assert.equal(classifyAdditionalActionableTopics(body), true, body); + } + } + for (const indent of [" ", "\t"]) { + const body = [`${indent}", ...visible].join(newline); + assert.equal(extractPulseVersion("Upgrade from v6.4.5", closed), "6.5.0"); + assert.equal(classifyV6FeedbackType(closed), "documentation"); + assert.equal(classifyAdditionalActionableTopics(closed), false); + const unfinished = [...hidden, ...visible].join(newline); + assert.equal(extractPulseVersion("Bug", unfinished), null); + assert.equal(classifyV6FeedbackType(unfinished), null); + assert.equal(classifyAdditionalActionableTopics(unfinished), null); + } +}); + +test("pasted HTML keeps genuine topic values without turning copied headings into fields", () => { + const body = ["### Additional actionable topics", "```html", "", "None\n\n"]) { assert.equal(triage.internals.classifyAdditionalActionableTopics(