Spaces:
Runtime error
Runtime error
| /** | |
| * Incremental re-sync of idea files: append new comments only, | |
| * update frontmatter snapshot. | |
| */ | |
| import { parseFrontmatter, serializeFrontmatter, stripFrontmatter } from "./frontmatter.mjs"; | |
| import { isBot } from "./classify.mjs"; | |
| function countThumbs(reactionGroups) { | |
| if (!Array.isArray(reactionGroups)) return 0; | |
| const g = reactionGroups.find((rg) => rg.content === "THUMBS_UP"); | |
| return g?.users?.totalCount ?? 0; | |
| } | |
| function uniqueCommenters(comments, authorLogin) { | |
| const seen = new Set(); | |
| for (const c of comments ?? []) { | |
| const u = c.author; | |
| if (!u || !u.login) continue; | |
| if (u.login === authorLogin) continue; | |
| if (isBot(u)) continue; | |
| seen.add(u.login); | |
| } | |
| return seen.size; | |
| } | |
| function renderComments(comments) { | |
| return comments | |
| .map( | |
| (c) => | |
| `- **@${c.author?.login ?? "unknown"}** (${c.createdAt}):\n > ${(c.body ?? "").split("\n").join("\n > ")}` | |
| ) | |
| .join("\n"); | |
| } | |
| function appendComments(body, newComments) { | |
| const heading = "## 💬 Community Discussion"; | |
| let idx = body.indexOf(heading); | |
| if (idx < 0) idx = body.indexOf("## Community Discussion"); | |
| if (idx < 0) { | |
| return body + `\n\n${heading}\n\n` + renderComments(newComments); | |
| } | |
| const after = body.slice(idx); | |
| const nextHeaderMatch = after.slice(heading.length).match(/^##\s+/m); | |
| const insertAt = nextHeaderMatch ? idx + heading.length + nextHeaderMatch.index : body.length; | |
| const insertBlock = "\n\n" + renderComments(newComments) + "\n"; | |
| return body.slice(0, insertAt) + insertBlock + body.slice(insertAt); | |
| } | |
| export function resyncIdeaFile(text, issue, now = new Date(), opts = {}) { | |
| const meta = parseFrontmatter(text); | |
| if (!meta) return { changed: false, text }; | |
| const lastSyncedId = Number(meta.last_synced_comment_id ?? 0); | |
| const allComments = issue.comments ?? []; | |
| const newComments = allComments.filter((c) => Number(c.databaseId) > lastSyncedId); | |
| if (newComments.length === 0) { | |
| return { changed: false, text }; | |
| } | |
| const body = stripFrontmatter(text); | |
| const newBody = appendComments(body, newComments); | |
| const newMeta = { | |
| ...meta, | |
| last_synced_at: now.toISOString(), | |
| last_synced_comment_id: Math.max(...newComments.map((c) => Number(c.databaseId))), | |
| snapshot: { | |
| ...(meta.snapshot ?? {}), | |
| thumbs: countThumbs(issue.reactionGroups), | |
| commenters: uniqueCommenters(allComments, issue.author?.login), | |
| labels: (issue.labels ?? []).map((l) => l.name).filter(Boolean), | |
| state: String(issue.state ?? "open").toLowerCase(), | |
| }, | |
| }; | |
| const out = serializeFrontmatter(newMeta, newBody); | |
| const needsReclassification = !!( | |
| opts.inNeedDetails && newComments.some((c) => c.author?.login === issue.author?.login) | |
| ); | |
| return { changed: true, text: out, needsReclassification }; | |
| } | |