/** * Episteme Presentation Renderer * * Reads JSON data and renders Reveal.js slides */ (async function () { // Load presentation data const dataUrl = window.PRESENTATION_DATA_URL || '../generated/agile-agent-team.json'; let data; try { const response = await fetch(dataUrl); data = await response.json(); } catch (error) { console.error('Failed to load presentation data:', error); document.getElementById('slides').innerHTML = `

Error Loading Presentation

Could not load ${dataUrl}

Run: npx ts-node scripts/generate.ts data/agile-agent-team.yaml

`; Reveal.initialize(); return; } const slidesContainer = document.getElementById('slides'); // Actor icon mapping (simple initials for now) function getActorInitials(actor) { return actor.label.split(' ').map(w => w[0]).join('').toUpperCase().slice(0, 2); } // Format JSON for display function formatData(data) { if (!data) return ''; return JSON.stringify(data, null, 2) .replace(/"([^"]+)":/g, '"$1":') .replace(/: "([^"]+)"/g, ': "$1"') .replace(/: (\d+\.?\d*)/g, ': $1') .replace(/: (true|false)/g, ': $1') .replace(/: (null)/g, ': $1'); } // Render slides function renderSlides(slides) { let sectionNumber = 0; for (const slide of slides) { const section = document.createElement('section'); switch (slide.type) { case 'title': section.classList.add('title-slide'); section.innerHTML = `

stemedb

`; break; case 'section-title': sectionNumber++; section.innerHTML = `
Section ${sectionNumber}

${slide.title}

${slide.subtitle}

${slide.description.trim()}

`; break; case 'sequence': section.setAttribute('data-auto-animate', ''); section.innerHTML = renderSequenceSlide(slide, data.actors); break; } slidesContainer.appendChild(section); } } // Render sequence slide function renderSequenceSlide(slide, allActors) { const actors = slide.actors; const steps = slide.steps; // Actor columns const actorHtml = Object.values(actors).map(actor => `
${getActorInitials(actor)}
${actor.label}
`).join(''); // Step cards as fragments const stepsHtml = steps.map((step, index) => { const statusClass = step.danger ? 'danger' : (step.success ? 'success' : (step.warning ? 'warning' : '')); const fromActor = step.fromActor || actors[step.from] || { label: step.from }; const toActor = step.toActor || actors[step.to] || { label: step.to }; return `
${index + 1}
${fromActor.label} ${toActor.label}
${step.action}
${step.label}
${step.note ? `
${step.note}
` : ''} ${step.data ? `
${formatData(step.data)}
` : ''} ${step.callout ? `
${step.callout}
` : ''}
`; }).join(''); return `

${slide.title}

${actorHtml}
${stepsHtml}
`; } // Render slides renderSlides(data.slides); // Initialize Reveal.js Reveal.initialize({ hash: true, history: true, controls: true, progress: true, center: true, transition: 'fade', transitionSpeed: 'fast', // Keyboard shortcuts keyboard: { // Arrow keys for fragments within slide 39: 'next', // right 37: 'prev', // left }, }); // Make step cards visible as fragments appear Reveal.on('fragmentshown', event => { event.fragment.classList.add('visible'); }); Reveal.on('fragmenthidden', event => { event.fragment.classList.remove('visible'); }); // Show all fragments on slide enter if coming from later slide Reveal.on('slidechanged', event => { const currentSlide = event.currentSlide; const fragments = currentSlide.querySelectorAll('.fragment'); // Reset visibility on slide change fragments.forEach(frag => { if (frag.classList.contains('visible')) { frag.classList.add('visible'); } }); }); })();