feat: add backlinks display and wiki-link rendering (closes #62, #64)

Implements two key knowledge module features:

**#62 - Backlinks Display:**
- Added BacklinksList component to show entries that link to current entry
- Fetches backlinks from /api/knowledge/entries/:slug/backlinks
- Displays entry title, summary, and link context
- Clickable links to navigate to linking entries
- Loading, error, and empty states

**#64 - Wiki-Link Rendering:**
- Added WikiLinkRenderer component to parse and render wiki-links
- Supports [[slug]] and [[slug|display text]] syntax
- Converts wiki-links to clickable navigation links
- Distinct styling (blue color, dotted underline)
- XSS protection via HTML escaping
- Memoized HTML processing for performance

**Components:**
- BacklinksList.tsx - Backlinks display with empty/loading/error states
- WikiLinkRenderer.tsx - Wiki-link parser and renderer
- Updated EntryViewer.tsx to use WikiLinkRenderer
- Integrated BacklinksList into entry detail page

**API:**
- Added fetchBacklinks() function in knowledge.ts
- Added KnowledgeBacklink type to shared types

**Tests:**
- Comprehensive tests for BacklinksList (8 tests)
- Comprehensive tests for WikiLinkRenderer (14 tests)
- All tests passing with Vitest

**Type Safety:**
- Strict TypeScript compliance
- No 'any' types
- Proper error handling
This commit is contained in:
Jason Woltje
2026-01-30 00:06:48 -06:00
parent 806a518467
commit ee9663a1f6
10 changed files with 849 additions and 6 deletions

View File

@@ -211,6 +211,29 @@ export interface KnowledgeEntryVersionWithAuthor extends KnowledgeEntryVersion {
};
}
/**
* Knowledge entry backlink
* Represents an entry that links to another entry
*/
export interface KnowledgeBacklink {
readonly id: string;
sourceId: string;
targetId: string;
linkText: string;
displayText: string;
positionStart: number;
positionEnd: number;
resolved: boolean;
context: string | null;
readonly createdAt: Date;
source: {
id: string;
title: string;
slug: string;
summary?: string | null;
};
}
/**
* Domain entity
*/