Is there a way to only return the TOC #718
Replies: 2 comments
-
The Table of Contents is stored within a $toc = (new Query())
->where(Query::type(TableOfContents::class))
->findOne($document);
if ($toc === null) {
// No TOC is present
} else {
// FOUND IT!
} Or without using the fancy function getTOC(Document $document): ?TableOfContents
{
foreach ($document->iterator() as $node) {
if ($node instanceof TableOfContents) {
return $node;
}
}
return null;
} There are two main ways you could use this: Manually parse and render the TOCWith this approach, you have to wire some of the parsing/rendering logic yourself, but it's not too bad: $environment = new Environment();
// TODO: add any/all extensions you want
$document = (new MarkdownParser($environment))->parse($markdown);
$toc = (new Query())
->where(Query::type(TableOfContents::class))
->findOne($document);
if ($toc === null) {
// No TOC is present; you might want to handle this somehow
}
$tocHtml = (new HtmlRenderer($environment))->renderNodes([$toc]); Use an event listener to remove everything except the TOCIf you'd like to avoid that wiring, you can create a custom event listener that removes everything from the final class RemoveEverythingExceptTOCListener
{
public function __invoke(DocumentParsedEvent $event): void
{
$document = $event->getDocument();
$toc = (new Query())
->where(Query::type(TableOfContents::class))
->findOne($document);
if ($toc === null) {
// No TOC is present; remove all children
$event->getDocument()->replaceChildren([]);
} else {
$event->getDocument()->replaceChildren([$toc]);
}
}
} You can then register that with the environment: $environment->addEventListener(DocumentParsedEvent::class, new RemoveEverythingExceptTOCListener(), -200); // I'm not 100% sure about the priority here Or bundle it into a custom extension that registers it. I have not tested any of this code but I'm confident that it should at least be very very close to what you need. Hope that helps! |
Beta Was this translation helpful? Give feedback.
-
Thanks, works like a charm! Personally I'm also detaching the toc from the document because I also need the rest of the document. I'm doing something like this $converter = new GithubFlavoredMarkdownConverter($options);
$environment = $converter->getEnvironment();
foreach ($extensions as $extension) {
$environment->addExtension($extension);
}
$converted = $converter->convert($page->content);
$document = $converted->getDocument();
$toc = (new Query())
->where(Query::type(TableOfContents::class))
->findOne($document);
$toc->detach();
$renderer = new HtmlRenderer($environment);
$content = $renderer->renderDocument($document);
$toc = $renderer->renderNodes([$toc]); And that way I have my content I can put in the main container and the toc I can put aside, with different css and html structure. |
Beta Was this translation helpful? Give feedback.
-
Hello ~
I've been struggling trying to figure out a way to get only the table of contents. I am using the Table of Contents extension and when return the markdown, the TOC is there. What I guess I'm wondering is if there's a way to passing the markdown and instead of returning everything along with the TOC is if it's possible to only return the TOC?
Thanks so much for the help!
Beta Was this translation helpful? Give feedback.
All reactions