From c1b05b2e31786b677b0094b62be3681db14dd4d9 Mon Sep 17 00:00:00 2001 From: Aaron Axvig Date: Mon, 16 Mar 2026 20:52:49 -0500 Subject: [PATCH] Fix parsing --- web/js/issues.js | 33 +++++++++++++++++++++++---- web/js/markdown.js | 7 ++++++ web/js/process.js | 57 +++++++++++++--------------------------------- 3 files changed, 51 insertions(+), 46 deletions(-) diff --git a/web/js/issues.js b/web/js/issues.js index f48dd6d..5e6e4ad 100644 --- a/web/js/issues.js +++ b/web/js/issues.js @@ -86,7 +86,8 @@ function loadIssuesFromFiles(fileRefs, issueType, elementId, applyIssueSearchFil allIssues.push({ id: issue.id || '', summary: issue.summary || '', - caveat: issue.caveat || '', + resolved: issue.resolved || '', + caveat: issue.caveat || '', sourceVersion }); }); @@ -157,6 +158,7 @@ function parseMarkdownIssues(markdownText) { const issues = []; let currentIssueId = ''; let currentIssueBodyParts = []; + let currentIssueResolvedBlocks = []; let currentIssueCaveatBlocks = []; const finalizeIssue = () => { @@ -170,11 +172,13 @@ function parseMarkdownIssues(markdownText) { .trim(); const summary = summaryBody; + const resolved = currentIssueResolvedBlocks.join('\n\n').trim(); const caveat = currentIssueCaveatBlocks.join('\n\n').trim(); issues.push({ id: currentIssueId, summary, + resolved, caveat }); }; @@ -184,6 +188,7 @@ function parseMarkdownIssues(markdownText) { finalizeIssue(); currentIssueId = String(token.text || '').trim(); currentIssueBodyParts = []; + currentIssueResolvedBlocks = []; currentIssueCaveatBlocks = []; return; } @@ -192,6 +197,14 @@ function parseMarkdownIssues(markdownText) { return; } + if (token.type === 'code' && String(token.lang || '').trim().toLowerCase() === 'resolved') { + const resolvedText = String(token.text || '').trim(); + if (resolvedText) { + currentIssueResolvedBlocks.push(resolvedText); + } + return; + } + if (token.type === 'code' && String(token.lang || '').trim().toLowerCase() === 'caveat') { const caveatText = String(token.text || '').trim(); if (caveatText) { @@ -234,6 +247,7 @@ function normalizeIssuesFromPayload(data) { return { id: String(item.id).trim(), summary: String(item.summary || item.description).trim(), + resolved: String(item.resolved || '').trim(), caveat: String(item.caveat || '').trim() }; } @@ -251,6 +265,7 @@ function normalizeIssuesFromPayload(data) { return { id: String(issue.id).trim(), summary: String(issue.description).trim(), + resolved: String(issue.resolved || '').trim(), caveat: String(issue.caveat || '').trim() }; } @@ -390,17 +405,21 @@ function dedupeIssues(issues, versionKey) { issues.forEach(issue => { const id = (issue.id || '').trim(); const summary = (issue.summary || '').trim(); + const resolved = (issue.resolved || '').trim(); const caveat = (issue.caveat || '').trim(); if (!id) return; if (!map.has(id)) { - map.set(id, { id, summary, caveat, [versionKey]: [] }); + map.set(id, { id, summary, resolved, caveat, [versionKey]: [] }); } const entry = map.get(id); if (!entry.summary && summary) { entry.summary = summary; } + if (!entry.resolved && resolved) { + entry.resolved = resolved; + } if (!entry.caveat && caveat) { entry.caveat = caveat; } @@ -441,7 +460,7 @@ function getSourceVersionFromFileName(fileName) { } function renderSummaryCell(cell, issue) { - cell.innerHTML = markdownSummaryToHtml(issue.summary, issue.caveat); + cell.innerHTML = markdownSummaryToHtml(issue.summary, issue.resolved, issue.caveat); const refs = getSocialRefsForIssue(issue.id); if (!refs.length) { @@ -504,15 +523,19 @@ function normalizeSocialRefs(data) { return map; } -function markdownSummaryToHtml(summaryText, caveatText) { +function markdownSummaryToHtml(summaryText, resolvedText, caveatText) { const input = String(summaryText || '').trim(); + const resolved = String(resolvedText || '').trim(); const caveat = String(caveatText || '').trim(); - if (!input && !caveat) { + if (!input && !resolved && !caveat) { return ''; } const htmlParts = []; + if (resolved) { + htmlParts.push(`
Resolved: ${escapeHtml(resolved)}
`); + } if (caveat) { htmlParts.push(`
Caveat: ${escapeHtml(caveat)}
`); } diff --git a/web/js/markdown.js b/web/js/markdown.js index e231983..7171fdc 100644 --- a/web/js/markdown.js +++ b/web/js/markdown.js @@ -17,6 +17,13 @@ export function buildIssueMarkdownDocument(payload) { lines.push(`## ${issue.id}`); lines.push(''); + if (issue.resolved) { + lines.push('```resolved'); + lines.push(issue.resolved); + lines.push('```'); + lines.push(''); + } + if (issue.caveat) { lines.push('```caveat'); lines.push(issue.caveat); diff --git a/web/js/process.js b/web/js/process.js index 02e56d5..7dcc102 100644 --- a/web/js/process.js +++ b/web/js/process.js @@ -10,6 +10,7 @@ let activeDownloadUrl = null; const PROCESS_FORM_STATE_KEY = 'bugmedley.process.formState.v1'; const ISSUE_ID_PATTERN = /\b((?:[A-Z]{2,6}|WF500)-\d{4,8})\b/i; const BLOCK_CONTAINER_TAGS = new Set(['ARTICLE', 'ASIDE', 'BLOCKQUOTE', 'DIV', 'P', 'PRE', 'SECTION']); +const RESOLVED_LINE_PATTERN = /^resolved\s+in\b/i; function loadProducts() { fetch('data/products.json') @@ -60,7 +61,7 @@ function generateJSON() { return; } - const parsedIssues = parseIssuesInput(inputText); + const parsedIssues = parseIssuesFromHtmlTable(inputText); if (parsedIssues.length === 0) { document.getElementById('markdownOutput').value = ''; @@ -72,6 +73,7 @@ function generateJSON() { const issues = parsedIssues.map(issue => ({ id: issue.id, description: issue.description, + resolved: issue.resolved || '', caveat: issue.caveat || '' })); @@ -87,15 +89,6 @@ function generateJSON() { setParseStatus(`Parsed ${issues.length} issues from input.`); } -function parseIssuesInput(inputText) { - const fromHtml = parseIssuesFromHtmlTable(inputText); - if (fromHtml.length > 0) { - return fromHtml; - } - - return parseIssuesFromLinePairs(inputText); -} - function parseIssuesFromHtmlTable(htmlText) { const parser = new DOMParser(); const doc = parser.parseFromString(htmlText, 'text/html'); @@ -105,16 +98,20 @@ function parseIssuesFromHtmlTable(htmlText) { return []; } - const rows = table.querySelectorAll(':scope > tr, :scope > tbody > tr, :scope > thead > tr, :scope > tfoot > tr'); + const rows = Array.from(table.querySelectorAll('tr')); const issues = []; rows.forEach(row => { - const cells = row.querySelectorAll('td, th'); + const cells = Array.from(row.children).filter(cell => { + const tag = (cell.tagName || '').toUpperCase(); + return tag === 'TD' || tag === 'TH'; + }); + if (cells.length < 2) { return; } - const leftCellText = normalizeWhitespace(cells[0].textContent || ''); + const leftCellText = extractCellText(cells[0]); const issueDetails = extractIssueDetails(cells[1]); const rightCellText = issueDetails.description; @@ -128,6 +125,10 @@ function parseIssuesFromHtmlTable(htmlText) { } const id = issueIdMatch[1].toUpperCase(); + const leftCellTrailingText = normalizeWhitespace( + leftCellText.replace(issueIdMatch[0], '').replace(/^[-:;,.\s]+/, '') + ); + const resolved = RESOLVED_LINE_PATTERN.test(leftCellTrailingText) ? leftCellTrailingText : ''; const description = rightCellText; if (!description) { @@ -137,7 +138,8 @@ function parseIssuesFromHtmlTable(htmlText) { issues.push({ id, description, - caveat: issueDetails.caveat + resolved, + caveat: issueDetails.caveat || (resolved ? '' : leftCellTrailingText) }); }); @@ -330,33 +332,6 @@ function sanitizeTableCellText(text) { return normalizeWhitespace(text).replace(/\|/g, '\\|'); } -function parseIssuesFromLinePairs(rawText) { - const lines = rawText - .split(/\r?\n/) - .map(line => line.trim()) - .filter(Boolean); - - const issues = []; - - for (let i = 0; i < lines.length; i += 2) { - if (i + 1 >= lines.length) { - continue; - } - - const issueIdMatch = lines[i].match(ISSUE_ID_PATTERN); - if (!issueIdMatch) { - continue; - } - - issues.push({ - id: issueIdMatch[1].toUpperCase(), - description: lines[i + 1] - }); - } - - return issues; -} - function normalizeWhitespace(value) { return value.replace(/\s+/g, ' ').trim(); }