Overview

let current = dv.current();
let title = current.name || current.file.name;
 
// --- CONFIGURATION ---
// Set to your silhouette image path or filename (e.g., "npc-images/silhouette.webp" or "silhouette.webp").
// If the file doesn't exist or is set to "", it will gracefully display the text message below.
let fallbackImage = "npc-images/silhouette.webp"; 
// ---------------------
 
// 1. Gather all potential names (Title, quoted nicknames, and Obsidian Aliases)
let rawNames = [title];
 
// Extract quoted nickname if present in title (e.g., Wulfric "The Bear" -> The Bear)
let matchNick = title.match(/"([^"]+)"/);
if (matchNick && matchNick) {
    rawNames.push(matchNick);
}
 
// Safely pull aliases from Obsidian Frontmatter/Properties
let rawAliases = current.file?.aliases || current.aliases || [];
if (typeof rawAliases === "string") {
    rawNames.push(rawAliases);
} else if (rawAliases && typeof rawAliases[Symbol.iterator] === "function") {
    for (let a of rawAliases) {
        if (a && typeof a === "string") rawNames.push(a);
    }
}
 
// 2. Build sanitized search terms (ensures terms are >= 2 chars to avoid matching "_" or empty strings)
let searchTerms = new Set();
for (let name of rawNames) {
    if (!name || typeof name !== "string") continue;
    
    let lower = name.toLowerCase().trim().replace(/["']/g, "");
    let slug = lower.replace(/[\s-]+/g, "_").replace(/^_+|_+\$/g, "");
    
    if (lower.length >= 2) searchTerms.add(lower);
    if (slug.length >= 2) searchTerms.add(slug);
}
 
// 3. Search npc-images for matching character files
let matches = app.vault.getFiles().filter(f => {
    let pathLower = f.path.toLowerCase();
    if (!pathLower.includes("npc-images")) return false;
    
    // Exclude the fallback image from character search
    if (fallbackImage && pathLower.includes(fallbackImage.toLowerCase())) return false;
    
    let imgName = f.name.toLowerCase();
    return Array.from(searchTerms).some(term => term && imgName.includes(term));
});
 
// 4. Prioritize files with "avatar" in the name, otherwise take first match
let match = matches.find(f => f.name.toLowerCase().includes("avatar")) || (matches.length > 0 ? matches : null);
 
// 5. Render artwork, fallback image, or clean text message
if (match) {
    dv.paragraph(`![[${match.path}|cover]]`);
} else {
    // Flexible fallback image lookup (works with filename, full path, or partial match)
    let fallbackFile = null;
    if (fallbackImage && fallbackImage.trim() !== "") {
        let cleanFB = fallbackImage.toLowerCase().trim();
        fallbackFile = app.vault.getFiles().find(f => 
            f.path.toLowerCase() === cleanFB || 
            f.path.toLowerCase().includes(cleanFB) || 
            f.name.toLowerCase().includes(cleanFB)
        );
    }
    
    if (fallbackFile) {
        dv.paragraph(`![[${fallbackFile.path}|cover]]`);
    } else {
        dv.paragraph(`*No artwork generated yet for ${title}*`);
    }
}

// 5. Render artwork or fallback if (match) { dv.paragraph(![[${match.path}|cover]]); } else { let fallbackFile = fallbackImage ? app.vault.getAbstractFileByPath(fallbackImage) : null; if (fallbackFile) { dv.paragraph(![[${fallbackFile.path}|cover]]); } else { dv.paragraph(*No artwork generated yet for ${title}*); } }

### Character Bio
Tiem Rhurin is the custodian of [[Oadeguard]] and the [[Western Dominance]].

Appearance & Personality