feat: replace basic frontmatter display with structured accent card UI featuring badges, tags, and boolean flags

This commit is contained in:
2026-03-24 19:29:09 -04:00
parent d020264ba3
commit dc2fdbe109
3 changed files with 597 additions and 44 deletions
+182 -12
View File
@@ -2183,20 +2183,10 @@
window.open(popoutUrl, `popout_${data.vault}_${data.path.replace(/[^a-zA-Z0-9]/g, '_')}`, 'width=1000,height=700,menubar=no,toolbar=no,location=no,status=no,resizable=yes,scrollbars=no');
});
// Frontmatter
// Frontmatter — Accent Card
let fmSection = null;
if (data.frontmatter && Object.keys(data.frontmatter).length > 0) {
const fmToggle = el("div", { class: "frontmatter-toggle" }, [
document.createTextNode("▶ Frontmatter"),
]);
const fmContent = el("div", { class: "frontmatter-content" }, [
document.createTextNode(JSON.stringify(data.frontmatter, null, 2)),
]);
fmToggle.addEventListener("click", () => {
fmContent.classList.toggle("open");
fmToggle.textContent = fmContent.classList.contains("open") ? "▼ Frontmatter" : "▶ Frontmatter";
});
fmSection = el("div", {}, [fmToggle, fmContent]);
fmSection = buildFrontmatterCard(data.frontmatter);
}
// Content container (rendered HTML)
@@ -3419,6 +3409,186 @@
});
}
// ---------------------------------------------------------------------------
// Frontmatter Accent Card Builder
// ---------------------------------------------------------------------------
function buildFrontmatterCard(frontmatter) {
// Helper: format date
function formatDate(iso) {
if (!iso) return '—';
const d = new Date(iso);
const date = d.toISOString().slice(0, 10);
const time = d.toTimeString().slice(0, 5);
return `${date} · ${time}`;
}
// Extract boolean flags
const booleanFlags = ['publish', 'favoris', 'template', 'task', 'archive', 'draft', 'private']
.map(key => ({ key, value: !!frontmatter[key] }));
// Toggle state
let isOpen = true;
// Build header with chevron
const chevron = el("span", { class: "fm-chevron open" });
chevron.innerHTML = '<i data-lucide="chevron-down" style="width:14px;height:14px"></i>';
const fmHeader = el("div", { class: "fm-header" }, [
chevron,
document.createTextNode("Frontmatter")
]);
// ZONE 1: Top strip
const topBadges = [];
// Title badge
const title = frontmatter.titre || frontmatter.title || '';
if (title) {
topBadges.push(el("span", { class: "ac-title" }, [document.createTextNode(`"${title}"`)]));
}
// Status badge
if (frontmatter.statut) {
const statusBadge = el("span", { class: "ac-badge green" }, [
el("span", { class: "ac-dot" }),
document.createTextNode(frontmatter.statut)
]);
topBadges.push(statusBadge);
}
// Category badge
if (frontmatter.catégorie || frontmatter.categorie) {
const cat = frontmatter.catégorie || frontmatter.categorie;
const catBadge = el("span", { class: "ac-badge blue" }, [
document.createTextNode(cat)
]);
topBadges.push(catBadge);
}
// Publish badge
if (frontmatter.publish) {
topBadges.push(el("span", { class: "ac-badge purple" }, [
document.createTextNode("publié")
]));
}
// Favoris badge
if (frontmatter.favoris) {
topBadges.push(el("span", { class: "ac-badge purple" }, [
document.createTextNode("favori")
]));
}
const acTop = el("div", { class: "ac-top" }, topBadges);
// ZONE 2: Body 2 columns
const leftCol = el("div", { class: "ac-col" }, [
el("div", { class: "ac-row" }, [
el("span", { class: "ac-k" }, [document.createTextNode("auteur")]),
el("span", { class: "ac-v" }, [document.createTextNode(frontmatter.auteur || '—')])
]),
el("div", { class: "ac-row" }, [
el("span", { class: "ac-k" }, [document.createTextNode("catégorie")]),
el("span", { class: "ac-v" }, [document.createTextNode(frontmatter.catégorie || frontmatter.categorie || '—')])
]),
el("div", { class: "ac-row" }, [
el("span", { class: "ac-k" }, [document.createTextNode("statut")]),
el("span", { class: "ac-v" }, [document.createTextNode(frontmatter.statut || '—')])
]),
el("div", { class: "ac-row" }, [
el("span", { class: "ac-k" }, [document.createTextNode("aliases")]),
el("span", { class: "ac-v muted" }, [
document.createTextNode(
frontmatter.aliases && frontmatter.aliases.length > 0
? frontmatter.aliases.join(', ')
: '[]'
)
])
])
]);
const rightCol = el("div", { class: "ac-col" }, [
el("div", { class: "ac-row" }, [
el("span", { class: "ac-k" }, [document.createTextNode("creation_date")]),
el("span", { class: "ac-v mono" }, [document.createTextNode(formatDate(frontmatter.creation_date))])
]),
el("div", { class: "ac-row" }, [
el("span", { class: "ac-k" }, [document.createTextNode("modification_date")]),
el("span", { class: "ac-v mono" }, [document.createTextNode(formatDate(frontmatter.modification_date))])
]),
el("div", { class: "ac-row" }, [
el("span", { class: "ac-k" }, [document.createTextNode("publish")]),
el("span", { class: "ac-v" }, [document.createTextNode(String(frontmatter.publish || false))])
]),
el("div", { class: "ac-row" }, [
el("span", { class: "ac-k" }, [document.createTextNode("favoris")]),
el("span", { class: "ac-v" }, [document.createTextNode(String(frontmatter.favoris || false))])
])
]);
const acBody = el("div", { class: "ac-body" }, [leftCol, rightCol]);
// ZONE 3: Tags row
const tagPills = [];
if (frontmatter.tags && frontmatter.tags.length > 0) {
frontmatter.tags.forEach(tag => {
tagPills.push(el("span", { class: "ac-tag" }, [document.createTextNode(tag)]));
});
}
const acTagsRow = el("div", { class: "ac-tags-row" }, [
el("span", { class: "ac-tags-k" }, [document.createTextNode("tags")]),
el("div", { class: "ac-tags-wrap" }, tagPills)
]);
// ZONE 4: Flags row
const flagChips = [];
booleanFlags.forEach(flag => {
const chipClass = flag.value ? "flag-chip on" : "flag-chip off";
flagChips.push(el("span", { class: chipClass }, [
el("span", { class: "flag-dot" }),
document.createTextNode(flag.key)
]));
});
const acFlagsRow = el("div", { class: "ac-flags-row" }, [
el("span", { class: "ac-flags-k" }, [document.createTextNode("flags")]),
...flagChips
]);
// Assemble the card
const acCard = el("div", { class: "ac-card" }, [
acTop,
acBody,
acTagsRow,
acFlagsRow
]);
// Toggle functionality
fmHeader.addEventListener("click", () => {
isOpen = !isOpen;
if (isOpen) {
acCard.style.display = "block";
chevron.classList.remove("closed");
chevron.classList.add("open");
} else {
acCard.style.display = "none";
chevron.classList.remove("open");
chevron.classList.add("closed");
}
safeCreateIcons();
});
// Wrap in section
const fmSection = el("div", { class: "fm-section" }, [
fmHeader,
acCard
]);
return fmSection;
}
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------