@@ -81,6 +81,32 @@ def load_metadata(self, docs_dir: Path) -> Optional[Dict[str, Any]]:
8181 return None
8282
8383
84+ def load_all_markdown_files (self , docs_dir : Path ) -> Dict [str , str ]:
85+ """
86+ Load all markdown files from documentation directory.
87+
88+ Args:
89+ docs_dir: Documentation directory path
90+
91+ Returns:
92+ Dictionary mapping filename to markdown content
93+ """
94+ markdown_files = {}
95+
96+ if not docs_dir .exists ():
97+ return markdown_files
98+
99+ # Load all .md files in the directory
100+ for md_file in docs_dir .glob ("*.md" ):
101+ try :
102+ content = safe_read (md_file )
103+ markdown_files [md_file .name ] = content
104+ except Exception :
105+ # Skip files that can't be read
106+ pass
107+
108+ return markdown_files
109+
84110 def generate (
85111 self ,
86112 output_path : Path ,
@@ -112,6 +138,11 @@ def generate(
112138 if docs_dir and metadata is None :
113139 metadata = self .load_metadata (docs_dir )
114140
141+ # Load all markdown content
142+ markdown_content = {}
143+ if docs_dir :
144+ markdown_content = self .load_all_markdown_files (docs_dir )
145+
115146 # Default values
116147 if module_tree is None :
117148 module_tree = {}
@@ -126,7 +157,8 @@ def generate(
126157 repository_url = repository_url ,
127158 github_pages_url = github_pages_url ,
128159 metadata = metadata ,
129- config = config
160+ config = config ,
161+ markdown_content = markdown_content
130162 )
131163
132164 # Write to file
@@ -139,7 +171,8 @@ def _generate_html_template(
139171 repository_url : Optional [str ],
140172 github_pages_url : Optional [str ],
141173 metadata : Optional [Dict [str , Any ]],
142- config : Dict [str , Any ]
174+ config : Dict [str , Any ],
175+ markdown_content : Dict [str , str ] = None
143176 ) -> str :
144177 """
145178 Generate the complete HTML template with embedded styles and scripts.
@@ -151,13 +184,15 @@ def _generate_html_template(
151184 github_pages_url: GitHub Pages URL
152185 metadata: Metadata dictionary
153186 config: Additional configuration
187+ markdown_content: Dictionary of markdown file contents
154188
155189 Returns:
156190 Complete HTML string
157191 """
158192 # Escape and prepare JSON data for embedding
159193 module_tree_json = json .dumps (module_tree )
160194 metadata_json = json .dumps (metadata ) if metadata else "null"
195+ markdown_content_json = json .dumps (markdown_content ) if markdown_content else "{}"
161196
162197 html = f'''<!DOCTYPE html>
163198<html lang="en">
@@ -448,7 +483,7 @@ def _generate_html_template(
448483<body>
449484 <div class="container">
450485 <nav class="sidebar" id="sidebar">
451- <div class="logo" onclick="loadPage('overview.md')">📚 { self ._escape_html (title )} </div>
486+ <div class="logo" onclick="loadPage(\\ 'overview.md\\ ')">📚 { self ._escape_html (title )} </div>
452487
453488 <div id="metadata-container"></div>
454489 <div id="navigation-container"></div>
@@ -467,6 +502,7 @@ def _generate_html_template(
467502 const METADATA = { metadata_json } ;
468503 const REPO_URL = { json .dumps (repository_url ) if repository_url else "null" } ;
469504 const GITHUB_PAGES_URL = { json .dumps (github_pages_url ) if github_pages_url else "null" } ;
505+ const MARKDOWN_CONTENT = { markdown_content_json } ;
470506
471507 // Current state
472508 let currentPage = 'overview.md';
@@ -568,7 +604,7 @@ def _generate_html_template(
568604
569605 // Add overview link
570606 let html = '<div class="nav-section">';
571- html += '<div class="nav-item' + (currentPage === 'overview.md' ? ' active' : '') + '" onclick="loadPage(\' overview.md\' )">Overview</div>';
607+ html += '<div class="nav-item' + (currentPage === 'overview.md' ? ' active' : '') + '" onclick="loadPage(\\ 'overview.md\ \ ')">Overview</div>';
572608 html += '</div>';
573609
574610 // Render module tree
@@ -593,7 +629,7 @@ def _generate_html_template(
593629 // If has components, it's a clickable page
594630 if (data.components && data.components.length > 0) {{
595631 const classes = 'nav-item' + (isActive ? ' active' : '');
596- html += `<div class="${{classes}}" onclick="loadPage('${{filename}}')">${{escapeHtml(displayName)}}</div>`;
632+ html += `<div class="${{classes}}" onclick="loadPage(\\ '${{filename}}\\ ')">${{escapeHtml(displayName)}}</div>`;
597633 }} else {{
598634 // Otherwise it's just a header
599635 html += `<div class="nav-section-header">${{escapeHtml(displayName)}}</div>`;
@@ -616,25 +652,41 @@ def _generate_html_template(
616652
617653 // Load and render a markdown page
618654 async function loadPage(filename) {{
655+ console.log('[loadPage] Starting for:', filename);
619656 currentPage = filename;
620657 const contentEl = document.getElementById('content');
621658
622659 try {{
623660 // Show loading
624661 contentEl.innerHTML = '<div class="loading">Loading...</div>';
662+ console.log('[loadPage] Set loading message');
625663
626- // Fetch markdown file
627- const response = await fetch(filename);
664+ let markdown;
628665
629- if (!response.ok) {{
630- throw new Error(`Failed to load ${{filename}}: ${{response.statusText}}`);
666+ // Try to get content from embedded data first
667+ console.log('[loadPage] Checking MARKDOWN_CONTENT:', typeof MARKDOWN_CONTENT, Object.keys(MARKDOWN_CONTENT || {{}}).length);
668+ if (MARKDOWN_CONTENT && MARKDOWN_CONTENT[filename]) {{
669+ markdown = MARKDOWN_CONTENT[filename];
670+ console.log('[loadPage] Got embedded content, length:', markdown.length);
671+ }} else {{
672+ console.log('[loadPage] Embedded content not found, fetching...');
673+ // Fallback to fetching if not embedded (for backward compatibility)
674+ const response = await fetch(filename);
675+
676+ if (!response.ok) {{
677+ throw new Error(`Failed to load ${{filename}}: ${{response.statusText}}`);
678+ }}
679+
680+ markdown = await response.text();
681+ console.log('[loadPage] Fetched content, length:', markdown.length);
631682 }}
632683
633- const markdown = await response.text();
634-
635684 // Convert to HTML
685+ console.log('[loadPage] Converting markdown to HTML with marked.parse()');
636686 const html = marked.parse(markdown);
687+ console.log('[loadPage] Converted, HTML length:', html.length);
637688 contentEl.innerHTML = html;
689+ console.log('[loadPage] Set content innerHTML');
638690
639691 // Render mermaid diagrams
640692 await mermaid.run({{
@@ -652,13 +704,26 @@ def _generate_html_template(
652704
653705 }} catch (error) {{
654706 console.error('Error loading page:', error);
655- contentEl.innerHTML = `
707+
708+ let errorHtml = `
656709 <div class="error-message">
657710 <h3>Error Loading Page</h3>
658711 <p>Could not load <strong>${{escapeHtml(filename)}}</strong></p>
659- <p>${{escapeHtml(error.message)}}</p>
660- </div>
712+ <p><strong>Error:</strong> ${{escapeHtml(error.message)}}</p>
661713 `;
714+
715+ // Check if markdown content is missing
716+ if (!MARKDOWN_CONTENT || Object.keys(MARKDOWN_CONTENT).length === 0) {{
717+ errorHtml += `
718+ <p style="margin-top: 1rem; padding: 1rem; background: #fff3cd; border: 1px solid #ffc107; border-radius: 4px;">
719+ <strong>Note:</strong> This HTML file was generated without embedded markdown content.
720+ Regenerate the documentation with the latest version to embed all markdown files.
721+ </p>
722+ `;
723+ }}
724+
725+ errorHtml += '</div>';
726+ contentEl.innerHTML = errorHtml;
662727 }}
663728 }}
664729
@@ -672,24 +737,70 @@ def _generate_html_template(
672737
673738 // Initialize app
674739 async function init() {{
675- // Render metadata and navigation
676- renderMetadata();
677- renderNavigation();
740+ console.log('[init] Starting initialization');
741+ console.log('[init] marked:', typeof marked);
742+ console.log('[init] mermaid:', typeof mermaid);
743+ console.log('[init] MARKDOWN_CONTENT keys:', Object.keys(MARKDOWN_CONTENT || {{}}).slice(0, 5));
678744
679- // Load initial page from hash or default to overview
680- const hash = window.location.hash.substring(1);
681- const initialPage = hash && hash.endsWith('.md') ? hash : 'overview.md';
682- await loadPage(initialPage);
683-
684- // Listen for hash changes
685- window.addEventListener('hashchange', handleHashChange);
745+ try {{
746+ // Render metadata and navigation
747+ console.log('[init] Rendering metadata');
748+ renderMetadata();
749+ console.log('[init] Rendering navigation');
750+ renderNavigation();
751+
752+ // Load initial page from hash or default to overview
753+ const hash = window.location.hash.substring(1);
754+ const initialPage = hash && hash.endsWith('.md') ? hash : 'overview.md';
755+ console.log('[init] Initial page:', initialPage);
756+ await loadPage(initialPage);
757+ console.log('[init] Page loaded successfully');
758+
759+ // Listen for hash changes
760+ window.addEventListener('hashchange', handleHashChange);
761+ console.log('[init] Initialization complete');
762+ }} catch (error) {{
763+ console.error('[init] ERROR:', error);
764+ const contentEl = document.getElementById('content');
765+ contentEl.innerHTML = `
766+ <div class="error-message">
767+ <h3>Initialization Error</h3>
768+ <p><strong>Error:</strong> ${{error.message}}</p>
769+ <pre>${{error.stack}}</pre>
770+ </div>
771+ `;
772+ }}
773+ }}
774+
775+ // Check if external libraries loaded
776+ function checkLibraries() {{
777+ if (typeof marked === 'undefined' || typeof mermaid === 'undefined') {{
778+ const contentEl = document.getElementById('content');
779+ contentEl.innerHTML = `
780+ <div class="error-message">
781+ <h3>External Libraries Not Loaded</h3>
782+ <p>The required JavaScript libraries (marked.js and mermaid.js) failed to load.</p>
783+ <p><strong>This usually happens when opening the HTML file directly (file:// protocol).</strong></p>
784+ <h4>Solution:</h4>
785+ <p>Serve the documentation with a local web server:</p>
786+ <ol>
787+ <li><strong>Python:</strong> <code>python3 -m http.server 8000</code> then visit <code>http://localhost:8000</code></li>
788+ <li><strong>Or deploy to GitHub Pages</strong> (works perfectly there!)</li>
789+ </ol>
790+ </div>
791+ `;
792+ return false;
793+ }}
794+ return true;
686795 }}
687796
688797 // Start when DOM is ready
689798 if (document.readyState === 'loading') {{
690- document.addEventListener('DOMContentLoaded', init);
799+ document.addEventListener('DOMContentLoaded', () => {{
800+ if (checkLibraries()) init();
801+ }});
691802 }} else {{
692- init();
803+ if (checkLibraries()) init();
693804 }}
694805 </script>
695806</body>
0 commit comments