/** * Document Viewer Component * Displays framework documentation with TOC and navigation */ class DocumentViewer { constructor(containerId = 'document-viewer') { this.container = document.getElementById(containerId); this.currentDocument = null; } /** * Render document */ async render(documentSlug) { if (!this.container) { console.error('Document viewer container not found'); return; } try { // Show loading state this.showLoading(); // Fetch document const response = await API.Documents.get(documentSlug); if (!response.success) { throw new Error('Document not found'); } this.currentDocument = response.document; this.showDocument(); } catch (error) { this.showError(error.message); } } /** * Show loading state */ showLoading() { this.container.innerHTML = `

Loading document...

`; } /** * Show document content */ showDocument() { const doc = this.currentDocument; this.container.innerHTML = `
${doc.quadrant ? ` ${doc.quadrant} ` : ''}

${this.escapeHtml(doc.title)}

${doc.metadata?.version ? `

Version ${doc.metadata.version}

` : ''}
${doc.toc && doc.toc.length > 0 ? this.renderTOC(doc.toc) : ''}
${doc.content_html}
${doc.created_at ? `

Created: ${new Date(doc.created_at).toLocaleDateString()}

` : ''} ${doc.updated_at ? `

Updated: ${new Date(doc.updated_at).toLocaleDateString()}

` : ''}
`; // Add smooth scroll to TOC links this.initializeTOCLinks(); } /** * Render table of contents */ renderTOC(toc) { return `

Table of Contents

`; } /** * Initialize TOC links for smooth scrolling */ initializeTOCLinks() { this.container.querySelectorAll('a[href^="#"]').forEach(link => { link.addEventListener('click', (e) => { e.preventDefault(); const id = link.getAttribute('href').slice(1); const target = document.getElementById(id); if (target) { target.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }); }); } /** * Show error state */ showError(message) { this.container.innerHTML = `

Document Not Found

${this.escapeHtml(message)}

← Browse all documents
`; } /** * Escape HTML to prevent XSS */ escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } } // Export as global window.DocumentViewer = DocumentViewer;