| … | … | @@ -245,29 +245,37 @@ export class NoteManager { |
| 245 | 245 | * Lists all notes (excluding README) alphabetically with slug links. |
| 246 | 246 | */ |
| 247 | 247 | async regenerateToc (notebook) { |
| 248 | | const meta = await this.getNotebook(notebook) |
| 249 | | if (!meta || !meta.readmeId) return |
| 248 | try { |
| 249 | const meta = await this.getNotebook(notebook) |
| 250 | if (!meta || !meta.readmeId) return |
| 250 | 251 | |
| 251 | | const readme = await this.getNote(notebook, meta.readmeId) |
| 252 | | if (!readme) return |
| 252 | const readme = await this.getNote(notebook, meta.readmeId) |
| 253 | if (!readme) { |
| 254 | console.error(`[TOC] README note ${meta.readmeId} not found for ${notebook}`) |
| 255 | return |
| 256 | } |
| 253 | 257 | |
| 254 | | const content = readme.content || '' |
| 255 | | const startIdx = content.indexOf(TOC_START) |
| 256 | | const endIdx = content.indexOf(TOC_END) |
| 257 | | if (startIdx < 0 || endIdx < 0 || endIdx <= startIdx) return // Markers removed — no-op |
| 258 | const content = readme.content || '' |
| 259 | const startIdx = content.indexOf(TOC_START) |
| 260 | const endIdx = content.indexOf(TOC_END) |
| 261 | if (startIdx < 0 || endIdx < 0 || endIdx <= startIdx) return |
| 258 | 262 | |
| 259 | | // Build TOC entries from all notes except README |
| 260 | | const notes = await this.listNotes(notebook) |
| 261 | | const entries = notes |
| 262 | | .filter(n => n.id !== meta.readmeId) |
| 263 | | .sort((a, b) => (a.title || '').localeCompare(b.title || '')) |
| 264 | | .map(n => `- [${n.title || 'Untitled'}](${n.slug || n.id})`) |
| 263 | // Build TOC entries from all notes except README |
| 264 | const notes = await this.listNotes(notebook) |
| 265 | const nonReadme = notes.filter(n => n.id !== meta.readmeId) |
| 266 | const entries = nonReadme |
| 267 | .sort((a, b) => (a.title || '').localeCompare(b.title || '')) |
| 268 | .map(n => `- [${n.title || 'Untitled'}](${n.slug || n.id})`) |
| 265 | 269 | |
| 266 | | const tocContent = entries.length > 0 ? '\n' + entries.join('\n') + '\n' : '\n' |
| 267 | | const newContent = content.substring(0, startIdx + TOC_START.length) + tocContent + content.substring(endIdx) |
| 270 | const tocContent = entries.length > 0 ? '\n' + entries.join('\n') + '\n' : '\n' |
| 271 | const newContent = content.substring(0, startIdx + TOC_START.length) + tocContent + content.substring(endIdx) |
| 268 | 272 | |
| 269 | | if (newContent !== content) { |
| 270 | | await this.updateNote(notebook, meta.readmeId, { content: newContent }) |
| 273 | if (newContent !== content) { |
| 274 | await this.updateNote(notebook, meta.readmeId, { content: newContent }) |
| 275 | console.log(`[TOC] Updated ${notebook} README: ${entries.length} entries`) |
| 276 | } |
| 277 | } catch (err) { |
| 278 | console.error(`[TOC] Failed to regenerate for ${notebook}: ${err.message}`) |
| 271 | 279 | } |
| 272 | 280 | } |
| 273 | 281 | |
| … | … | @@ -597,7 +605,7 @@ export class NoteManager { |
| 597 | 605 | updatedAt: Date.now() |
| 598 | 606 | } |
| 599 | 607 | // Regenerate TOC in background |
| 600 | | this.regenerateToc(notebook).catch(() => {}) |
| 608 | this.regenerateToc(notebook) |
| 601 | 609 | return result |
| 602 | 610 | } |
| 603 | 611 | |
| … | … | @@ -642,7 +650,7 @@ export class NoteManager { |
| 642 | 650 | } |
| 643 | 651 | |
| 644 | 652 | // Regenerate TOC in background |
| 645 | | this.regenerateToc(notebook).catch(() => {}) |
| 653 | this.regenerateToc(notebook) |
| 646 | 654 | |
| 647 | 655 | return note // Return plaintext to caller |
| 648 | 656 | } |
| … | … | @@ -840,7 +848,7 @@ export class NoteManager { |
| 840 | 848 | } |
| 841 | 849 | const result = { ...note, id: note.noteId, content } |
| 842 | 850 | // Regenerate TOC if title changed |
| 843 | | if (titleChanged) this.regenerateToc(notebook).catch(() => {}) |
| 851 | if (titleChanged) this.regenerateToc(notebook) |
| 844 | 852 | return result |
| 845 | 853 | } |
| 846 | 854 | |
| … | … | @@ -875,7 +883,7 @@ export class NoteManager { |
| 875 | 883 | } |
| 876 | 884 | |
| 877 | 885 | // Regenerate TOC if title changed |
| 878 | | if (titleChanged) this.regenerateToc(notebook).catch(() => {}) |
| 886 | if (titleChanged) this.regenerateToc(notebook) |
| 879 | 887 | |
| 880 | 888 | return note // Return plaintext |
| 881 | 889 | } |
| … | … | @@ -886,7 +894,7 @@ export class NoteManager { |
| 886 | 894 | if (snb) { |
| 887 | 895 | await snb.deleteNote(noteId, 'user') |
| 888 | 896 | // Regenerate TOC in background |
| 889 | | this.regenerateToc(notebook).catch(() => {}) |
| 897 | this.regenerateToc(notebook) |
| 890 | 898 | return { deleted: true, id: noteId } |
| 891 | 899 | } |
| 892 | 900 | |
| … | … | @@ -922,7 +930,7 @@ export class NoteManager { |
| 922 | 930 | |
| 923 | 931 | // Regenerate TOC in background (only if we didn't just delete the README) |
| 924 | 932 | if (!meta || meta.readmeId !== noteId) { |
| 925 | | this.regenerateToc(notebook).catch(() => {}) |
| 933 | this.regenerateToc(notebook) |
| 926 | 934 | } |
| 927 | 935 | |
| 928 | 936 | return { deleted: true, id: noteId } |