robot-learning-tutorial / app /src /components /HtmlFragment.astro
thibaud frere
update
98af9a5
raw
history blame
2.18 kB
---
interface Props { src: string }
const { src } = Astro.props as Props;
// Load all .html fragments under src/content/fragments/** as strings (dev & build)
const fragments = import.meta.glob('../content/fragments/**/*.html', { query: '?raw', import: 'default', eager: true }) as Record<string, string>;
function resolveFragment(requested: string): string | null {
// Allow both "banner.html" and "fragments/banner.html"
const needle = requested.replace(/^\/*/, '');
for (const [key, html] of Object.entries(fragments)) {
if (key.endsWith('/' + needle) || key.endsWith('/' + needle.replace(/^fragments\//, ''))) {
return html;
}
}
return null;
}
const html = resolveFragment(src);
const mountId = `frag-${Math.random().toString(36).slice(2)}`;
---
{ html ? (
<div id={mountId} set:html={html} />
) : (
<div><!-- Fragment not found: {src} --></div>
) }
<script>
// Re-execute <script> tags inside the injected fragment (innerHTML doesn't run scripts)
const scriptEl = document.currentScript;
const mount = scriptEl ? scriptEl.previousElementSibling : null;
const execute = () => {
if (!mount) return;
const scripts = mount.querySelectorAll('script');
scripts.forEach(old => {
// ignore non-executable types (e.g., application/json)
if (old.type && old.type !== 'text/javascript' && old.type !== 'module' && old.type !== '') return;
if (old.dataset.executed === 'true') return;
old.dataset.executed = 'true';
if (old.src) {
const s = document.createElement('script');
Array.from(old.attributes).forEach(({ name, value }) => s.setAttribute(name, value));
document.body.appendChild(s);
} else {
try {
// run inline
(0, eval)(old.text || '');
} catch (e) {
console.error('HtmlFragment inline script error:', e);
}
}
});
};
// Ensure execution when ready: run now if Plotly or D3 is present, or when document is ready; otherwise wait for 'load'
if (window.Plotly || window.d3 || document.readyState === 'complete') execute();
else window.addEventListener('load', execute, { once: true });
</script>