Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add automatic title and TOC to docs #71

Open
davidbyoung opened this issue Oct 22, 2024 · 0 comments
Open

Add automatic title and TOC to docs #71

davidbyoung opened this issue Oct 22, 2024 · 0 comments

Comments

@davidbyoung
Copy link
Collaborator

To make docs more dynamic, we should programmatically insert the title and table of contents to them. As an example, we could do something like the following (need to find how to grab the title from DocumentationBinder):

// Load the HTML content into a DOMDocument
$dom = new \DOMDocument();
\libxml_use_internal_errors(true);  // Suppress HTML warnings
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
\libxml_clear_errors();

// Get all <h2> and <h3> elements
$h2Elements = $dom->getElementsByTagName('h2');
$h3Elements = $dom->getElementsByTagName('h3');

// Initialize the table of contents as an ordered list
$toc = '<ol>';

// Loop through <h2> elements to create the TOC
foreach ($h2Elements as $h2) {
    $h2Id = $h2->getAttribute('id');
    $h2Text = $h2->textContent;

    // Add the <h2> to the ordered list with a link
    $toc .= '<li><a href="#' . \htmlspecialchars($h2Id) . '">' . \htmlspecialchars($h2Text) . '</a>';

    // Nested ordered list for <h3> elements under the current <h2>
    $nestedList = '';
    $foundH3 = false;

    // Find <h3> elements that follow this <h2> until the next <h2>
    foreach ($h3Elements as $h3) {
        $h3Parent = $h3->previousSibling;
        
        // Traverse backwards to skip over text nodes, comments, etc., until an element node is found
        while ($h3Parent && $h3Parent->nodeType !== XML_ELEMENT_NODE) {
            $h3Parent = $h3Parent->previousSibling;
        }

        // Ensure $h3Parent is exactly the corresponding <h2> element
        if ($h3Parent instanceof DOMElement && $h3Parent->tagName === 'h2' && $h3Parent->getAttribute('id') === $h2Id) {
            if (!$foundH3) {
                $nestedList .= '<ol>';  // Start the nested list when the first <h3> is found
                $foundH3 = true;
            }

            $h3Id = $h3->getAttribute('id');
            $h3Text = $h3->textContent;

            // Add the <h3> to the nested ordered list with a link
            $nestedList .= '<li><a href="#' . \htmlspecialchars($h3Id) . '">' . \htmlspecialchars($h3Text) . '</a></li>';
        }
    }

    // Close the nested list if <h3> elements were found
    if ($foundH3) {
        $nestedList .= '</ol>';
    }

    $toc .= $nestedList . '</li>';
}

$toc .= '</ol>';

// Add the new elements (title and TOC) to the top of the document
$newHtml = <<<HTML
    <h1 id="doc-title">{$title}</h1>
    <nav class="toc-nav">
        <div class="toc-nav-contents">
            <h2 id="table-of-contents">Table of Contents</h2>
            {$toc}
        </div>
    </nav>
HTML;

// Convert the DOMDocument to a string and prepend the new HTML
$finalHtml = $newHtml . $dom->saveHTML();

// Output the final HTML
echo $finalHtml;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant