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:
parent
76c375db18
commit
3732dc5e00
|
|
@ -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}`));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue