fix: address code review - quote-aware CSV parsing, safer JSON handling, clearer comments

Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com>
Agent-Logs-Url: https://github.com/qinfendebingshuo/guanghulab/sessions/122c9353-e45b-46f7-aa46-9e50d0432f5c
This commit is contained in:
copilot-swe-agent[bot] 2026-03-24 01:01:50 +00:00
parent 76c375db18
commit 3732dc5e00
1 changed files with 54 additions and 9 deletions

View File

@ -130,6 +130,9 @@ async function handleMemo(auth, drive, folderId, issueTitle, issueBody, issueNum
console.log(`[semantic-landing] Updating existing doc: ${docId}`); console.log(`[semantic-landing] Updating existing doc: ${docId}`);
// 获取当前文档内容长度 // 获取当前文档内容长度
// Google Docs body content elements each have an endIndex; we need the max
// to know where existing content ends. Start at 1 because index 0 is reserved
// by Docs for the document root and content starts at index 1.
const docData = await docs.documents.get({ documentId: docId }); const docData = await docs.documents.get({ documentId: docId });
const endIndex = docData.data.body.content const endIndex = docData.data.body.content
.reduce((max, el) => Math.max(max, el.endIndex || 0), 1); .reduce((max, el) => Math.max(max, el.endIndex || 0), 1);
@ -207,7 +210,7 @@ function parseTableData(body) {
} }
// 1. 尝试 JSON 解析 // 1. 尝试 JSON 解析
const jsonMatch = body.match(/```(?:json)?\s*\n([\s\S]*?)\n```/); const jsonMatch = body.match(/```(?:json)?\s*\n([\s\S]*?)\n?```/);
if (jsonMatch) { if (jsonMatch) {
try { try {
const parsed = JSON.parse(jsonMatch[1].trim()); const parsed = JSON.parse(jsonMatch[1].trim());
@ -248,7 +251,7 @@ function parseTableData(body) {
} }
// 2. 尝试 CSV 解析(代码块内或纯文本) // 2. 尝试 CSV 解析(代码块内或纯文本)
const csvMatch = body.match(/```(?:csv)?\s*\n([\s\S]*?)\n```/); const csvMatch = body.match(/```(?:csv)?\s*\n([\s\S]*?)\n?```/);
const csvContent = csvMatch ? csvMatch[1].trim() : null; const csvContent = csvMatch ? csvMatch[1].trim() : null;
if (csvContent) { if (csvContent) {
@ -261,21 +264,59 @@ function parseTableData(body) {
return parseMarkdownTable(mdTableMatch[1]); return parseMarkdownTable(mdTableMatch[1]);
} }
// 4. 检查整个 body 是否为 CSV 格式(包含逗号分隔的多行) // 4. Check if body looks like CSV (consistent comma-separated columns across lines)
const lines = trimmed.split('\n').filter(l => l.trim()); const lines = trimmed.split('\n').filter(l => l.trim());
if (lines.length >= 2 && lines.every(l => l.includes(','))) { if (lines.length >= 2 && lines.every(l => l.includes(','))) {
return parseCSV(trimmed); const colCounts = lines.map(l => parseCSVLine(l).length);
const firstCount = colCounts[0];
if (firstCount >= 2 && colCounts.every(c => c === firstCount)) {
return parseCSV(trimmed);
}
} }
// 5. 降级:整个 body 作为单格数据 // 5. 降级:整个 body 作为单格数据
return [[trimmed]]; return [[trimmed]];
} }
/**
* Parse a single CSV line, handling quoted values containing commas.
*/
function parseCSVLine(line) {
const cells = [];
let current = '';
let inQuotes = false;
for (let i = 0; i < line.length; i++) {
const ch = line[i];
if (inQuotes) {
if (ch === '"' && line[i + 1] === '"') {
current += '"';
i++; // skip escaped quote
} else if (ch === '"') {
inQuotes = false;
} else {
current += ch;
}
} else {
if (ch === '"') {
inQuotes = true;
} else if (ch === ',') {
cells.push(current.trim());
current = '';
} else {
current += ch;
}
}
}
cells.push(current.trim());
return cells;
}
function parseCSV(text) { function parseCSV(text) {
return text return text
.split('\n') .split('\n')
.filter(line => line.trim()) .filter(line => line.trim())
.map(line => line.split(',').map(cell => cell.trim())); .map(line => parseCSVLine(line));
} }
function parseMarkdownTable(text) { function parseMarkdownTable(text) {
@ -383,13 +424,17 @@ function postIssueComment(token, repo, issueNumber, body) {
}; };
const req = https.request(options, (res) => { const req = https.request(options, (res) => {
let body = ''; let responseBody = '';
res.on('data', chunk => body += chunk); res.on('data', chunk => responseBody += chunk);
res.on('end', () => { res.on('end', () => {
if (res.statusCode >= 200 && res.statusCode < 300) { if (res.statusCode >= 200 && res.statusCode < 300) {
resolve(JSON.parse(body)); try {
resolve(JSON.parse(responseBody));
} catch (e) {
resolve({ raw: responseBody });
}
} else { } else {
reject(new Error(`GitHub API ${res.statusCode}: ${body}`)); reject(new Error(`GitHub API ${res.statusCode}: ${responseBody}`));
} }
}); });
}); });