feat: Implement bidirectional Story Bible links with draft text

- Add story_bible.rs module with StoryBibleIndex, StoryBibleItem, and
  StoryBibleReference types for indexing Story Bible content
- Support wiki-style [[...]] and mention-style @... syntax for references
- Highlight Story Bible references in editor with purple background
- Add Story Bible window (View > Tools > Story Bible) to browse items
- Show references from current draft file in Story Bible window
- Allow clicking references to jump to their location in the editor
- Auto-index Story Bible items from common directories (03-Characters,
  02-Story Bible, Characters, etc.)
- Extract metadata from YAML frontmatter or filenames
- Add walkdir dependency for directory scanning
- Fix pre-existing format string errors in workspace.rs

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
landon
2026-09-16 08:56:28 -05:00
parent 511a7588fa
commit ca3e476a14
9 changed files with 631 additions and 156 deletions
+17
View File
@@ -27,6 +27,7 @@ mod outline;
mod project;
mod grammar;
mod spelling;
mod story_bible_ui;
mod style;
mod ui;
mod util;
@@ -372,6 +373,14 @@ pub struct App {
watcher_rx: Option<mpsc::Receiver<WatcherMsg>>,
/// The file watcher thread handle, so it can be stopped when the workspace closes.
watcher_thread: Option<thread::JoinHandle<()>>,
/// Index of Story Bible items for cross-referencing with draft text.
story_bible_index: crate::story_bible::StoryBibleIndex,
/// Whether the Story Bible window is open.
show_story_bible: bool,
/// Currently selected Story Bible item path.
selected_bible_item: Option<String>,
/// References found in the current draft file.
current_references: Vec<crate::story_bible::StoryBibleReference>,
}
impl App {
@@ -472,6 +481,10 @@ impl App {
show_project_settings: false,
watcher_rx: None,
watcher_thread: None,
story_bible_index: crate::story_bible::StoryBibleIndex::new(),
show_story_bible: false,
selected_bible_item: None,
current_references: Vec::new(),
};
app.load_spell_dict();
app.open_workspace();
@@ -594,6 +607,10 @@ impl eframe::App for App {
self.characters_window(ctx);
}
if self.show_story_bible {
self.story_bible_window(ctx);
}
if self.show_manuscript_settings {
self.manuscript_settings_window(ctx);
}