Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace phpDocumentor\Guides\RestructuredText\Directives;

use phpDocumentor\Guides\Nodes\ContentMenuNode;
use phpDocumentor\Guides\Nodes\Menu\ContentMenuNode;
use phpDocumentor\Guides\Nodes\Node;
use phpDocumentor\Guides\RestructuredText\Parser\Directive;
use phpDocumentor\Guides\RestructuredText\Parser\DocumentParserContext;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?php

declare(strict_types=1);

namespace phpDocumentor\Guides\Compiler\NodeTransformers;

use phpDocumentor\Guides\Compiler\CompilerContext;
use phpDocumentor\Guides\Compiler\NodeTransformer;
use phpDocumentor\Guides\Nodes\DocumentTree\DocumentEntryNode;
use phpDocumentor\Guides\Nodes\DocumentTree\SectionEntryNode;
use phpDocumentor\Guides\Nodes\Menu\ContentMenuNode;
use phpDocumentor\Guides\Nodes\Menu\MenuEntryNode;
use phpDocumentor\Guides\Nodes\Menu\TocNode;
use phpDocumentor\Guides\Nodes\Node;

use function assert;

use const PHP_INT_MAX;

/** @implements NodeTransformer<TocNode> */
class ContentMenuNodeWithSectionEntryTransformer implements NodeTransformer
{
public function enterNode(Node $node, CompilerContext $compilerContext): Node
{
return $node;
}

public function leaveNode(Node $node, CompilerContext $compilerContext): Node|null
{
if (!$node instanceof ContentMenuNode) {
return $node;
}

$depth = (int) $node->getOption('depth', PHP_INT_MAX);
$documentEntry = $compilerContext->getDocumentNode()->getDocumentEntry();

$menuEntries = [];
foreach ($documentEntry->getSections() as $section) {
// We do not add the main section as it repeats the document title
foreach ($section->getChildren() as $subSectionEntryNode) {
assert($subSectionEntryNode instanceof SectionEntryNode);
$sectionMenuEntry = new MenuEntryNode(
$documentEntry->getFile(),
$subSectionEntryNode->getTitle(),
[],
false,
1,
$subSectionEntryNode->getId(),
);
$menuEntries[] = $sectionMenuEntry;
$this->addSubSections($sectionMenuEntry, $subSectionEntryNode, $documentEntry, 1, $depth);
}
}

$node = $node->withMenuEntries($menuEntries);

return $node;
}

private function addSubSections(
MenuEntryNode $sectionMenuEntry,
SectionEntryNode $sectionEntryNode,
DocumentEntryNode $documentEntry,
int $currentLevel,
int $maxLevel,
): void {
if ($currentLevel >= $maxLevel) {
return;
}

foreach ($sectionEntryNode->getChildren() as $subSectionEntryNode) {
$subSectionMenuEntry = new MenuEntryNode(
$documentEntry->getFile(),
$subSectionEntryNode->getTitle(),
[],
false,
$currentLevel,
$subSectionEntryNode->getId(),
);
$sectionMenuEntry->addSection($subSectionMenuEntry);
$this->addSubSections(
$subSectionMenuEntry,
$subSectionEntryNode,
$documentEntry,
$currentLevel + 1,
$maxLevel,
);
}
}

public function supports(Node $node): bool
{
return $node instanceof ContentMenuNode;
}

public function getPriority(): int
{
// After DocumentEntryTransformer
return 4500;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,8 @@ public function leaveNode(Node $node, CompilerContext $compilerContext): Node|nu

$entry = new DocumentEntryNode($node->getFilePath(), $node->getTitle() ?? TitleNode::emptyNode());
$compilerContext->getProjectNode()->addDocumentEntry($entry);
$node->setDocumentEntry($entry);

return $node;
return $node->setDocumentEntry($entry);
}

public function supports(Node $node): bool
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public function enterNode(Node $node, CompilerContext $compilerContext): Node

$sectionEntryNode = new SectionEntryNode($node->getTitle());
if (count($this->sectionStack) === 0) {
$compilerContext->getDocumentNode()->getDocumentEntry()?->addSection($sectionEntryNode);
$compilerContext->getDocumentNode()->getDocumentEntry()->addSection($sectionEntryNode);
} else {
$parentSection = end($this->sectionStack);
assert($parentSection instanceof SectionEntryNode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,14 @@ public function leaveNode(Node $node, CompilerContext $compilerContext): Node|nu
private function addSubSections(MenuEntryNode $sectionMenuEntry, SectionEntryNode $sectionEntryNode, DocumentEntryNode $documentEntry, int $currentLevel): void
{
foreach ($sectionEntryNode->getChildren() as $subSectionEntryNode) {
$sectionMenuEntry = new MenuEntryNode($documentEntry->getFile(), $subSectionEntryNode->getTitle(), [], false, $currentLevel, $subSectionEntryNode->getId());
$sectionMenuEntry->addSection($sectionMenuEntry);
$subSectionMenuEntry = new MenuEntryNode($documentEntry->getFile(), $subSectionEntryNode->getTitle(), [], false, $currentLevel + 1, $subSectionEntryNode->getId());
$sectionMenuEntry->addSection($subSectionMenuEntry);
}
}

public function supports(Node $node): bool
{
return $node instanceof MenuNode;
return $node instanceof TocNode;
}

public function getPriority(): int
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
namespace phpDocumentor\Guides\NodeRenderers\Html;

use phpDocumentor\Guides\NodeRenderers\NodeRenderer;
use phpDocumentor\Guides\Nodes\ContentMenuNode;
use phpDocumentor\Guides\Nodes\Menu\ContentMenuNode;
use phpDocumentor\Guides\Nodes\Menu\MenuNode;
use phpDocumentor\Guides\Nodes\Menu\TocNode;
use phpDocumentor\Guides\Nodes\Node;
Expand Down
11 changes: 9 additions & 2 deletions packages/guides/src/Nodes/DocumentNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

namespace phpDocumentor\Guides\Nodes;

use Exception;
use phpDocumentor\Guides\Meta\FootnoteTarget;
use phpDocumentor\Guides\Nodes\DocumentTree\DocumentEntryNode;
use phpDocumentor\Guides\Nodes\DocumentTree\SectionEntryNode;
Expand Down Expand Up @@ -245,14 +246,20 @@ public function getFootnoteTargetAnonymous(): FootnoteTarget|null
return null;
}

public function getDocumentEntry(): DocumentEntryNode|null
public function getDocumentEntry(): DocumentEntryNode
{
if ($this->documentEntry === null) {
throw new Exception('DocumentEntry may not be accessed before initialization');
}

return $this->documentEntry;
}

public function setDocumentEntry(DocumentEntryNode $documentEntry): void
public function setDocumentEntry(DocumentEntryNode $documentEntry): DocumentNode
{
$this->documentEntry = $documentEntry;

return $this;
}

public function getRootSectionEntry(): SectionEntryNode|null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@
* @link https://phpdoc.org
*/

namespace phpDocumentor\Guides\Nodes;

use phpDocumentor\Guides\Nodes\Menu\MenuNode;
namespace phpDocumentor\Guides\Nodes\Menu;

use function is_scalar;

Expand Down
50 changes: 50 additions & 0 deletions packages/guides/src/Nodes/Menu/MenuEntry.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace phpDocumentor\Guides\Nodes\Menu;

use phpDocumentor\Guides\Nodes\AbstractNode;
use phpDocumentor\Guides\Nodes\TitleNode;

/** @extends AbstractNode<TitleNode> */
final class MenuEntry extends AbstractNode
{
/** @param MenuEntry[] $children */
public function __construct(
private readonly string $url,
TitleNode $title,
private readonly array $children = [],
private readonly bool $isDocumentRoot = false,
private readonly int $level = 1,
) {
$this->value = $title;
}

public function getUrl(): string
{
return $this->url;
}

/** @return MenuEntry[] */
public function getChildren(): array
{
return $this->children;
}

/** @return MenuEntry[] */
public function getEntries(): array
{
return $this->children;
}

public function isDocumentRoot(): bool
{
return $this->isDocumentRoot;
}

public function getLevel(): int
{
return $this->level;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ private static function getCompilerContext(string $path): CompilerContext
{
$context = new CompilerContext(new ProjectNode());
$document = new DocumentNode('123', $path);
$document->setDocumentEntry(new DocumentEntryNode($path, TitleNode::emptyNode()));
$document = $document->setDocumentEntry(new DocumentEntryNode($path, TitleNode::emptyNode()));

return $context->withShadowTree($document);
}
Expand All @@ -42,7 +42,7 @@ public function testSectionGetsRegistered(): void
$transformer->enterNode($node2, $this->context);
$transformer->leaveNode($node2, $this->context);
$transformer->leaveNode($node, $this->context);
self::assertCount(1, $this->context->getDocumentNode()->getDocumentEntry()?->getSections() ?? []);
self::assertInstanceOf(SectionEntryNode::class, $this->context->getDocumentNode()->getDocumentEntry()?->getSections()[0]);
self::assertCount(1, $this->context->getDocumentNode()->getDocumentEntry()->getSections());
self::assertInstanceOf(SectionEntryNode::class, $this->context->getDocumentNode()->getDocumentEntry()->getSections()[0]);
}
}
1 change: 1 addition & 0 deletions tests/Integration/tests-bootstrap/index/input/skip
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
toctrees do not work currently
16 changes: 11 additions & 5 deletions tests/Integration/tests/contents/expected/contents-depth-1.html
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Title</title>
<title>Title</title>

</head>
<body>
<div class="section" id="title">
<h1>Title</h1>

<div class="contents"><ul class="phpdocumentor-list"><li class="toc-item"><a href="/contents-depth-1.html#title">Title</a></li></ul></div>
<div class="contents"><ul class="phpdocumentor-list"><li class="toc-item"><a href="/contents-depth-1.html#depth-level-1">Depth Level 1</a></li></ul></div>
<div class="section" id="depth-level-1">
<h2>Depth Level 1</h2>

<div class="section" id="depth-level-2">
<h2>Depth Level 2</h2>
<h3>Depth Level 2</h3>

<div class="section" id="depth-level-3">
<h3>Depth Level 3</h3>
<h4>Depth Level 3</h4>

<div class="section" id="depth-level-4">
<h4>Depth Level 4</h4>
<h5>Depth Level 4</h5>

</div>

</div>

Expand Down
16 changes: 11 additions & 5 deletions tests/Integration/tests/contents/expected/contents-depth-2.html
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Title</title>
<title>Title</title>

</head>
<body>
<div class="section" id="title">
<h1>Title</h1>

<div class="contents"><ul class="phpdocumentor-list"><li class="toc-item"><a href="/contents-depth-2.html#title">Title</a><ul class="phpdocumentor-list"><li class="toc-item"><a href="/contents-depth-2.html#depth-level-2">Depth Level 2</a></li></ul></li></ul></div>
<div class="contents"><ul class="phpdocumentor-list"><li class="toc-item"><a href="/contents-depth-2.html#depth-level-1">Depth Level 1</a><ul class="section-level-1"><li class="toc-item"><a href="/contents-depth-2.html#depth-level-2">Depth Level 2</a></li></ul></li></ul></div>
<div class="section" id="depth-level-1">
<h2>Depth Level 1</h2>

<div class="section" id="depth-level-2">
<h2>Depth Level 2</h2>
<h3>Depth Level 2</h3>

<div class="section" id="depth-level-3">
<h3>Depth Level 3</h3>
<h4>Depth Level 3</h4>

<div class="section" id="depth-level-4">
<h4>Depth Level 4</h4>
<h5>Depth Level 4</h5>

</div>

</div>

Expand Down
16 changes: 11 additions & 5 deletions tests/Integration/tests/contents/expected/contents-depth-3.html
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Title</title>
<title>Title</title>

</head>
<body>
<div class="section" id="title">
<h1>Title</h1>

<div class="contents"><ul class="phpdocumentor-list"><li class="toc-item"><a href="/contents-depth-3.html#title">Title</a><ul class="phpdocumentor-list"><li class="toc-item"><a href="/contents-depth-3.html#depth-level-2">Depth Level 2</a><ul class="phpdocumentor-list"><li class="toc-item"><a href="/contents-depth-3.html#depth-level-3">Depth Level 3</a></li></ul></li></ul></li></ul></div>
<div class="contents"><ul class="phpdocumentor-list"><li class="toc-item"><a href="/contents-depth-3.html#depth-level-1">Depth Level 1</a><ul class="section-level-1"><li class="toc-item"><a href="/contents-depth-3.html#depth-level-2">Depth Level 2</a><ul class="section-level-1"><li class="toc-item"><a href="/contents-depth-3.html#depth-level-3">Depth Level 3</a></li></ul></li></ul></li></ul></div>
<div class="section" id="depth-level-1">
<h2>Depth Level 1</h2>

<div class="section" id="depth-level-2">
<h2>Depth Level 2</h2>
<h3>Depth Level 2</h3>

<div class="section" id="depth-level-3">
<h3>Depth Level 3</h3>
<h4>Depth Level 3</h4>

<div class="section" id="depth-level-4">
<h4>Depth Level 4</h4>
<h5>Depth Level 4</h5>

</div>

</div>

Expand Down
Loading