ed3d967526
- New entities (note/npc/quest/calendar): schemas, Dexie v4 tables, repos, hooks; campaign cascade-delete now covers them all - Dashboard hub: campaign stats, navigation cards, party overview, recent rolls; opening a campaign lands here - Notes/Wiki: tags, [[wiki-links]] with click-to-open/create, backlinks panel, full-text search, autosave - NPC manager (role/location/faction/status) and Quest tracker (status + objectives checklist + reward) - In-world Calendar: integer day counter + events (no real Date -> no timezone bug) - Fix: calendarRepo.get is read-only (creating-on-read crashed inside liveQuery) 8 new unit tests (wikilinks + extended cascade), worldbuilding e2e. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
24 lines
877 B
TypeScript
24 lines
877 B
TypeScript
/** Extract the distinct titles referenced as [[Wiki Links]] in a body of text. */
|
|
export function extractWikiLinks(text: string): string[] {
|
|
const set = new Set<string>();
|
|
for (const m of text.matchAll(/\[\[([^\]]+)\]\]/g)) {
|
|
const title = m[1]?.trim();
|
|
if (title) set.add(title);
|
|
}
|
|
return [...set];
|
|
}
|
|
|
|
/** Split text into plain segments and [[link]] segments for rendering. */
|
|
export function splitWikiLinks(text: string): { text: string; link?: string }[] {
|
|
const parts: { text: string; link?: string }[] = [];
|
|
let last = 0;
|
|
for (const m of text.matchAll(/\[\[([^\]]+)\]\]/g)) {
|
|
const idx = m.index ?? 0;
|
|
if (idx > last) parts.push({ text: text.slice(last, idx) });
|
|
parts.push({ text: m[1]!.trim(), link: m[1]!.trim() });
|
|
last = idx + m[0].length;
|
|
}
|
|
if (last < text.length) parts.push({ text: text.slice(last) });
|
|
return parts;
|
|
}
|