Add automatic word count and link validation to create_note, update_note,
and update_sections operations to provide immediate feedback on note content
quality and link integrity.
Features:
- Word counting excludes frontmatter and Obsidian comments, includes all
other content (code blocks, inline code, headings, lists, etc.)
- Link validation checks wikilinks, heading links, and embeds
- Results categorized as: valid links, broken notes (note doesn't exist),
and broken headings (note exists but heading missing)
- Detailed broken link info includes line number and context snippet
- Human-readable summary (e.g., "15 links: 12 valid, 2 broken notes, 1 broken heading")
- Opt-out capability via validateLinks parameter (default: true) for
performance-critical operations
Implementation:
- New ContentUtils.countWords() for word counting logic
- Enhanced LinkUtils.validateLinks() for comprehensive link validation
- Updated create_note, update_note, update_sections to return wordCount
and linkValidation fields
- Updated MCP tool descriptions to document new features and parameters
- update_note now returns structured JSON instead of simple success message
Response format changes:
- create_note: added wordCount and linkValidation fields
- update_note: changed to structured response with wordCount and linkValidation
- update_sections: added wordCount and linkValidation fields
Breaking changes:
- update_note response format changed from simple message to structured JSON
Implements Task 10 from the implementation plan:
1. Updated NoteTools constructor to accept IVaultAdapter and IFileManagerAdapter
2. Created note-tools-factory.ts with factory function
3. Migrated all CRUD methods to use adapters:
- readNote: uses vault.read()
- createNote: uses vault.create(), vault.delete()
- createParentFolders: uses vault.createFolder()
- updateNote: uses vault.read(), vault.modify()
- deleteNote: uses vault.trash(), vault.delete()
- renameFile: uses fileManager.renameFile()
- readExcalidraw: uses vault.read()
- updateFrontmatter: uses vault.read(), vault.modify()
- updateSections: uses vault.read(), vault.modify()
4. Extended IVaultAdapter interface with modify(), delete(), and trash() methods
5. Implemented new methods in VaultAdapter
6. Updated ToolRegistry to use factory function
7. Kept app parameter temporarily for PathUtils dependency
8. All methods now use adapters instead of direct Obsidian API calls
9. Code compiles successfully
This change enables 100% test coverage by allowing full mocking of vault operations.