Auto-link Story Bible mentions in the draft, with a hover card to the entry
Bare proper nouns in prose ("Bixby walked in") now resolve against the
Story Bible automatically, the same as the existing [[wiki-links]] and
@mentions markup — no manual linking required. Matching is case-sensitive
and requires a capitalized, 3+ character match to a sheet's name or alias,
which is what keeps a character named "Hope" or "Will" from lighting up
on every unrelated use of the word; the longest phrase wins an overlap
("Bixby Reynolds" over "Bixby"), and a bare match never overrides the
author's own explicit markup.
Hovering a highlighted mention shows a card with the item's name, type
(Person/Place/Thing) and a summary (from a new summary:/description:
frontmatter field), with a link that opens the entry in the Story Bible
editor. The card appears after a short delay and stays open while the
pointer crosses onto it to reach the link.
Along the way:
- StoryBibleReference now carries absolute byte offsets (start/end) and
the resolved item_id, replacing column/length, which were actually
per-line and were being used as whole-buffer offsets — every reference
past a file's first line highlighted and jumped-to in the wrong place.
find_references() also now walks the buffer one char at a time rather
than one byte, which could previously land mid-character and panic on
any manuscript with accented letters or an em dash.
- build_story_bible_index() had its own, separately hardcoded list of
Story Bible directory names that had drifted from
find_story_bible_directory()'s list and no longer included
03-Story-Bible, the bundled template's actual folder — so the index,
and everything built on it, was silently empty for every project made
from that template. It now reuses the one list.
- Story Bible Editor window: its tree and content ScrollAreas (and the
content TextEdit) had no id_salt, so egui treated them as the same
widget — fixed with explicit salts.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+18
-17
@@ -341,37 +341,38 @@ impl App {
|
||||
}
|
||||
|
||||
/// Build the Story Bible index from the Story Bible directory.
|
||||
///
|
||||
/// Uses [`Self::find_story_bible_directory`] for the primary lookup —
|
||||
/// this used to keep its own, separately-hardcoded list of directory
|
||||
/// names, which had drifted out of sync and no longer included
|
||||
/// `03-Story-Bible`, the bundled template's actual folder. That silently
|
||||
/// left the index empty (no highlighting, no hover cards, no hits in the
|
||||
/// Story Bible window) for every project made from the snowflake
|
||||
/// template, so there is now exactly one place that name is spelled.
|
||||
pub(super) fn build_story_bible_index(&mut self) {
|
||||
use std::path::Path;
|
||||
let ws = self.config.workspace.clone();
|
||||
// Look for Story Bible directory - common locations
|
||||
let story_bible_dirs = [
|
||||
"03-Characters",
|
||||
"02-Story Bible",
|
||||
"Story Bible",
|
||||
"Characters",
|
||||
];
|
||||
|
||||
for dir_name in story_bible_dirs.iter() {
|
||||
let dir_path = Path::new(&ws).join(dir_name);
|
||||
if dir_path.exists() && dir_path.is_dir() {
|
||||
self.story_bible_index = crate::story_bible::StoryBibleIndex::build(&dir_path);
|
||||
return;
|
||||
}
|
||||
if let Some(dir_path) = self.find_story_bible_directory() {
|
||||
self.story_bible_index = crate::story_bible::StoryBibleIndex::build(&dir_path);
|
||||
return;
|
||||
}
|
||||
// If no specific Story Bible directory found, try to find all character/location/lore dirs
|
||||
self.story_bible_index = crate::story_bible::StoryBibleIndex::default();
|
||||
// No single Story Bible directory found — fall back to merging
|
||||
// whatever scattered character/location/lore folders exist.
|
||||
let ws = self.config.workspace.clone();
|
||||
let possible_dirs = ["03-Characters", "04-Locations", "05-Lore", "Characters", "Locations", "Lore"];
|
||||
for dir_name in possible_dirs.iter() {
|
||||
let dir_path = Path::new(&ws).join(dir_name);
|
||||
if dir_path.exists() && dir_path.is_dir() {
|
||||
let index = crate::story_bible::StoryBibleIndex::build(&dir_path);
|
||||
// Merge with existing index
|
||||
for (id, item) in index.items_by_id {
|
||||
self.story_bible_index.items_by_id.insert(id, item.clone());
|
||||
}
|
||||
for (name, item) in index.items_by_name {
|
||||
self.story_bible_index.items_by_name.insert(name, item);
|
||||
}
|
||||
for (alias, item) in index.items_by_alias {
|
||||
self.story_bible_index.items_by_alias.insert(alias, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user