From c9bd606f4cd4c3a8e28847445977bf2f023aa2a3 Mon Sep 17 00:00:00 2001 From: "@gapmiss" Date: Mon, 13 Jul 2026 11:51:46 -0500 Subject: [PATCH] fix: unify comment counts across frontmatter, history sidebar, and comments file using recursive count --- src/comments.ts | 15 +++++++++++++++ src/history-view.ts | 19 +++++++++++++++++-- src/main.ts | 3 ++- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/comments.ts b/src/comments.ts index 6724f46..bf416b6 100644 --- a/src/comments.ts +++ b/src/comments.ts @@ -94,6 +94,21 @@ function renderComment( return md; } +function countNestedComments(comments: Comment[]): number { + let total = 0; + for (const c of comments) { + total += 1; + if (c.children) { + total += countNestedComments(c.children); + } + } + return total; +} + +export function countAllComments(data: CommentsResponse): number { + return countNestedComments(data.comments); +} + export function renderComments( data: CommentsResponse, slug: string, diff --git a/src/history-view.ts b/src/history-view.ts index 5b93156..9061485 100644 --- a/src/history-view.ts +++ b/src/history-view.ts @@ -1,7 +1,7 @@ import { ItemView, normalizePath, Notice, setIcon, TFile, type WorkspaceLeaf } from 'obsidian'; import type SubstackClipperPlugin from './main'; import type { HistoryEntry } from './types'; -import { fetchComments, renderComments } from './comments'; +import { countAllComments, fetchComments, renderComments } from './comments'; export const HISTORY_VIEW_TYPE = 'substack-clipper-history'; @@ -256,7 +256,22 @@ export class HistoryView extends ItemView { `${this.plugin.settings.saveDirectory}/${entry.username}/${entry.slug}-comments.md`, ); await this.plugin.writeFile(commentsPath, commentsMd); - entry.commentCount = commentsData.comments.length; + entry.commentCount = countAllComments(commentsData); + + const notePath = normalizePath( + `${this.plugin.settings.saveDirectory}/${entry.username}/${entry.slug}.md`, + ); + const noteFile = this.app.vault.getAbstractFileByPath(notePath); + if (noteFile instanceof TFile) { + const content = await this.app.vault.read(noteFile); + const updated = content.replace( + /^comment-count: \d+$/m, + `comment-count: ${String(entry.commentCount)}`, + ); + if (updated !== content) { + await this.app.vault.modify(noteFile, updated); + } + } } entry.lastUpdated = new Date().toISOString(); succeeded++; diff --git a/src/main.ts b/src/main.ts index 66f9400..39e2092 100644 --- a/src/main.ts +++ b/src/main.ts @@ -8,7 +8,7 @@ import { fetchHtml, extractPreloads, parsePost, parseUrl, extractImages, extract import { htmlToMarkdown } from './converter'; import { postprocessMarkdown } from './postprocess'; import { downloadAllMedia } from './downloader'; -import { fetchComments, renderComments } from './comments'; +import { countAllComments, fetchComments, renderComments } from './comments'; export default class SubstackClipperPlugin extends Plugin { settings: SubstackClipperSettings; @@ -115,6 +115,7 @@ export default class SubstackClipperPlugin extends Plugin { await this.writeFile(commentsJsonPath, JSON.stringify(commentsData, null, 2)); } + article.commentCount = countAllComments(commentsData); const commentsMd = renderComments(commentsData, slug, domain); const commentsPath = normalizePath(`${this.settings.saveDirectory}/${username}/${slug}-comments.md`); await this.writeFile(commentsPath, commentsMd);