Skip to content

Commit

Permalink
Render heading links on the server
Browse files Browse the repository at this point in the history
  • Loading branch information
timacdonald committed Aug 26, 2024
1 parent 627ca99 commit 622188e
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 25 deletions.
66 changes: 53 additions & 13 deletions app/Markdown/GithubFlavoredMarkdownConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,22 @@

namespace App\Markdown;

use Illuminate\Support\Str;
use Laravel\Unfenced\UnfencedExtension;
use League\CommonMark\Environment\Environment;
use League\CommonMark\Environment\EnvironmentInterface;
use League\CommonMark\Event\DocumentParsedEvent;
use League\CommonMark\Extension\Attributes\AttributesExtension;
use League\CommonMark\Extension\Autolink\AutolinkExtension;
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
use League\CommonMark\Extension\CommonMark\Node\Block\BlockQuote;
use League\CommonMark\Extension\CommonMark\Node\Block\Heading;
use League\CommonMark\Extension\CommonMark\Node\Inline\HtmlInline;
use League\CommonMark\Extension\Strikethrough\StrikethroughExtension;
use League\CommonMark\Extension\Table\TableExtension;
use League\CommonMark\Extension\TaskList\TaskListExtension;
use League\CommonMark\MarkdownConverter;
use League\CommonMark\Environment\Environment;
use App\Markdown\GithubFlavoredMarkdownExtension;
use Illuminate\Support\Facades\Vite;
use League\CommonMark\Node\Node;
use League\CommonMark\Renderer\ChildNodeRendererInterface;
use League\CommonMark\Util\HtmlElement;
use League\CommonMark\Node\Block\Paragraph;
use Torchlight\Commonmark\V2\TorchlightExtension;
use Laravel\Unfenced\UnfencedExtension;
use League\CommonMark\Environment\EnvironmentInterface;
use League\CommonMark\Extension\Attributes\AttributesExtension;
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
use League\CommonMark\Extension\CommonMark\Node\Block\BlockQuote;
use League\CommonMark\Renderer\NodeRendererInterface;

/**
* Converts GitHub Flavored Markdown to HTML.
Expand All @@ -46,6 +43,49 @@ public function __construct(array $config = [])

$environment->addRenderer(BlockQuote::class, new BlockQuoteRenderer());

$environment->addEventListener(DocumentParsedEvent::class, function (DocumentParsedEvent $event) {
$walker = $event->getDocument()->walker();

while ($event = $walker->next()) {
[
$paragraph,
$heading,
$linkOpener,
$linkCloser,
] = [
$event->getNode(),
$event->getNode()->next(),
$event->getNode()->firstChild(),
$event->getNode()->lastChild(),
];

if (
! $heading instanceof Heading ||
! $paragraph instanceof Paragraph ||
count($paragraph->children()) !== 2 ||
! $linkOpener instanceof HtmlInline ||
! $linkCloser instanceof HtmlInline ||
! str_starts_with($linkOpener->getLiteral(), '<a name="') ||
! str_ends_with($linkOpener->getLiteral(), '">') ||
substr_count($linkOpener->getLiteral(), '"') !== 2 ||
$paragraph->firstChild()->next() !== $paragraph->lastChild() ||
! str_starts_with($linkCloser->getLiteral(), '</a>')
) {
continue;
}

$link = str($linkOpener->getLiteral())->after('<a name="')->beforeLast('">')->toString();

$heading->data->set('attributes.id', $link);
$heading->prependChild(new HtmlInline('<a href="#'.$link.'">'));
$heading->appendChild(new HtmlInline('</a>'));

$walker->resumeAt($heading->next());

$paragraph->detach();
}
});

parent::__construct($environment);
}

Expand Down
12 changes: 0 additions & 12 deletions resources/js/docs.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import './clipboard';
import './theme'

document.addEventListener('DOMContentLoaded', () => {
wrapHeadingsInAnchors();
setupNavCurrentLinkHandling();
highlightSupportPolicyTable();

Expand All @@ -20,17 +19,6 @@ document.addEventListener('DOMContentLoaded', () => {
});
})

function wrapHeadingsInAnchors() {
[...document.querySelector('.docs_main').querySelectorAll('a[name]')].forEach(anchor => {
const heading = anchor.parentNode.nextElementSibling;
heading.id = anchor.name;
anchor.href = `#${anchor.name}`;
anchor.removeAttribute('name');
[...heading.childNodes].forEach(node => anchor.appendChild(node));
heading.appendChild(anchor);
});
}

function setupNavCurrentLinkHandling() {
[...document.querySelectorAll('.docs_sidebar h2')].forEach(el => {
el.addEventListener('click', (e) => {
Expand Down

0 comments on commit 622188e

Please sign in to comment.