diff --git a/app/src/components/HtmlEmbed.astro b/app/src/components/HtmlEmbed.astro index 7d53a9b5c4a3e1f5432f83aa7b3a639d45fa6481..a8f1667eb27e43eba9b2638057b6abe6eaea602a 100644 --- a/app/src/components/HtmlEmbed.astro +++ b/app/src/components/HtmlEmbed.astro @@ -6,13 +6,43 @@ const { src, title, desc, frameless = false, align = 'left' } = Astro.props as P const embeds = (import.meta as any).glob('../content/embeds/**/*.html', { query: '?raw', import: 'default', eager: true }) as Record; function resolveFragment(requested: string): string | null { - // Allow both "banner.html" and "embeds/banner.html" - const needle = requested.replace(/^\/*/, ''); - for (const [key, html] of Object.entries(embeds)) { - if (key.endsWith('/' + needle) || key.endsWith('/' + needle.replace(/^embeds\//, ''))) { - return html; + // Résolution tolérante: accepte avec/sans "embeds/", avec/sans ".html", insensible à la casse, et recherche par basename + const norm = (s: string) => String(s || '') + .trim() + .replace(/^\/*/, '') + .replace(/^\.\//, '') + .toLowerCase(); + const raw = norm(requested); + const withHtml = raw.endsWith('.html') ? raw : `${raw}.html`; + const stripEmbeds = (s: string) => s.replace(/^embeds\//, ''); + const v1 = raw; + const v2 = withHtml; + const v3 = stripEmbeds(v1); + const v4 = stripEmbeds(v2); + const needles = new Set([v1, v2, v3, v4]); + + // Construire table des chemins normalisés -> contenu + const entries = Object.entries(embeds).map(([key, html]) => { + const nk = norm(key); + const base = nk.split('/').pop() || nk; + return { nk, base, html }; + }); + + // 1) Correspondance par fin de chemin complète + for (const e of entries) { + for (const v of needles) { + if (e.nk.endsWith('/' + v) || e.nk === v) return e.html; + } + } + + // 2) Correspondance par basename + for (const e of entries) { + for (const v of needles) { + const vb = v.split('/').pop(); + if (e.base === vb) return e.html; } } + return null; } @@ -69,7 +99,7 @@ const mountId = `frag-${Math.random().toString(36).slice(2)}`; + +