From 7357983428008c2f173717b0fdc31665bdc6a56f Mon Sep 17 00:00:00 2001 From: "lina.wolf" Date: Mon, 26 Feb 2024 08:09:52 +0100 Subject: [PATCH] [FEATURE] Introduce NavigationTitle --- .../config/guides-restructured-text.php | 4 + .../NavigationTitleFieldListItemRule.php | 34 ++++++ .../DocumentEntryRegistrationTransformer.php | 24 +++- .../GlobMenuEntryNodeTransformer.php | 9 +- .../InternalMenuEntryNodeTransformer.php | 13 ++- .../ModifyDocumentEntryAdditionalData.php | 53 +++++++++ .../Html/BreadCrumbNodeRenderer.php | 9 +- packages/guides/src/Nodes/DocumentNode.php | 12 ++ .../Nodes/DocumentTree/DocumentEntryNode.php | 13 +++ .../Nodes/Metadata/NavigationTitleNode.php | 26 +++++ .../expected/anotherPage.html | 106 ++++++++++++++++++ .../expected/index.html | 106 ++++++++++++++++++ .../expected/yetAnotherPage.html | 106 ++++++++++++++++++ .../input/anotherPage.rst | 7 ++ .../input/guides.xml | 8 ++ .../input/include.rst.txt | 6 + .../input/index.rst | 19 ++++ .../input/somePage.rst | 7 ++ .../input/yetAnotherPage.rst | 9 ++ 19 files changed, 567 insertions(+), 4 deletions(-) create mode 100644 packages/guides-restructured-text/src/RestructuredText/Parser/Productions/FieldList/NavigationTitleFieldListItemRule.php create mode 100644 packages/guides/src/Event/ModifyDocumentEntryAdditionalData.php create mode 100644 packages/guides/src/Nodes/Metadata/NavigationTitleNode.php create mode 100644 tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/expected/anotherPage.html create mode 100644 tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/expected/index.html create mode 100644 tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/expected/yetAnotherPage.html create mode 100644 tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/input/anotherPage.rst create mode 100644 tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/input/guides.xml create mode 100644 tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/input/include.rst.txt create mode 100644 tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/input/index.rst create mode 100644 tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/input/somePage.rst create mode 100644 tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/input/yetAnotherPage.rst diff --git a/packages/guides-restructured-text/resources/config/guides-restructured-text.php b/packages/guides-restructured-text/resources/config/guides-restructured-text.php index a88b41d97..d744f29dc 100644 --- a/packages/guides-restructured-text/resources/config/guides-restructured-text.php +++ b/packages/guides-restructured-text/resources/config/guides-restructured-text.php @@ -81,6 +81,7 @@ use phpDocumentor\Guides\RestructuredText\Parser\Productions\FieldList\DateFieldListItemRule; use phpDocumentor\Guides\RestructuredText\Parser\Productions\FieldList\DedicationFieldListItemRule; use phpDocumentor\Guides\RestructuredText\Parser\Productions\FieldList\FieldListItemRule; +use phpDocumentor\Guides\RestructuredText\Parser\Productions\FieldList\NavigationTitleFieldListItemRule; use phpDocumentor\Guides\RestructuredText\Parser\Productions\FieldList\NocommentsFieldListItemRule; use phpDocumentor\Guides\RestructuredText\Parser\Productions\FieldList\NosearchFieldListItemRule; use phpDocumentor\Guides\RestructuredText\Parser\Productions\FieldList\OrganizationFieldListItemRule; @@ -320,6 +321,9 @@ ->set(DedicationFieldListItemRule::class) ->tag('phpdoc.guides.parser.rst.fieldlist') + ->set(NavigationTitleFieldListItemRule::class) + ->tag('phpdoc.guides.parser.rst.fieldlist') + ->set(NocommentsFieldListItemRule::class) ->tag('phpdoc.guides.parser.rst.fieldlist') diff --git a/packages/guides-restructured-text/src/RestructuredText/Parser/Productions/FieldList/NavigationTitleFieldListItemRule.php b/packages/guides-restructured-text/src/RestructuredText/Parser/Productions/FieldList/NavigationTitleFieldListItemRule.php new file mode 100644 index 000000000..76070ec1e --- /dev/null +++ b/packages/guides-restructured-text/src/RestructuredText/Parser/Productions/FieldList/NavigationTitleFieldListItemRule.php @@ -0,0 +1,34 @@ +getTerm()) === 'navigation-title'; + } + + public function apply(FieldListItemNode $fieldListItemNode, BlockContext $blockContext): MetadataNode + { + return new NavigationTitleNode($fieldListItemNode->getPlaintextContent()); + } +} diff --git a/packages/guides/src/Compiler/NodeTransformers/DocumentEntryRegistrationTransformer.php b/packages/guides/src/Compiler/NodeTransformers/DocumentEntryRegistrationTransformer.php index 1a01611ec..7f97227e6 100644 --- a/packages/guides/src/Compiler/NodeTransformers/DocumentEntryRegistrationTransformer.php +++ b/packages/guides/src/Compiler/NodeTransformers/DocumentEntryRegistrationTransformer.php @@ -15,17 +15,23 @@ use phpDocumentor\Guides\Compiler\CompilerContext; use phpDocumentor\Guides\Compiler\NodeTransformer; +use phpDocumentor\Guides\Event\ModifyDocumentEntryAdditionalData; use phpDocumentor\Guides\Nodes\DocumentNode; use phpDocumentor\Guides\Nodes\DocumentTree\DocumentEntryNode; use phpDocumentor\Guides\Nodes\Node; use phpDocumentor\Guides\Nodes\TitleNode; +use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; +use function assert; +use function is_string; + /** @implements NodeTransformer */ final class DocumentEntryRegistrationTransformer implements NodeTransformer { public function __construct( private readonly LoggerInterface $logger, + private readonly EventDispatcherInterface|null $eventDispatcher = null, ) { } @@ -44,7 +50,23 @@ public function leaveNode(Node $node, CompilerContext $compilerContext): Node|nu $this->logger->warning('Document has no title', $compilerContext->getLoggerInformation()); } - $entry = new DocumentEntryNode($node->getFilePath(), $node->getTitle() ?? TitleNode::emptyNode(), $node->isRoot()); + $additionalData = []; + if (is_string($node->getNavigationTitle())) { + $additionalData['navigationTitle'] = TitleNode::fromString($node->getNavigationTitle()); + } + + if ($this->eventDispatcher !== null) { + $event = $this->eventDispatcher->dispatch(new ModifyDocumentEntryAdditionalData($additionalData, $node, $compilerContext)); + assert($event instanceof ModifyDocumentEntryAdditionalData); + $additionalData = $event->getAdditionalData(); + } + + $entry = new DocumentEntryNode( + $node->getFilePath(), + $node->getTitle() ?? TitleNode::emptyNode(), + $node->isRoot(), + $additionalData, + ); $compilerContext->getProjectNode()->addDocumentEntry($entry); return $node->setDocumentEntry($entry); diff --git a/packages/guides/src/Compiler/NodeTransformers/MenuNodeTransformers/GlobMenuEntryNodeTransformer.php b/packages/guides/src/Compiler/NodeTransformers/MenuNodeTransformers/GlobMenuEntryNodeTransformer.php index b9c4e4045..db35b3899 100644 --- a/packages/guides/src/Compiler/NodeTransformers/MenuNodeTransformers/GlobMenuEntryNodeTransformer.php +++ b/packages/guides/src/Compiler/NodeTransformers/MenuNodeTransformers/GlobMenuEntryNodeTransformer.php @@ -20,6 +20,7 @@ use phpDocumentor\Guides\Nodes\Menu\MenuNode; use phpDocumentor\Guides\Nodes\Menu\TocNode; use phpDocumentor\Guides\Nodes\Node; +use phpDocumentor\Guides\Nodes\TitleNode; use function array_pop; use function assert; @@ -65,10 +66,16 @@ protected function handleMenuEntry(MenuNode $currentMenu, MenuEntryNode $entryNo } } + $titleNode = $documentEntry->getTitle(); + $navigationTitle = $documentEntry->getAdditionalData('navigationTitle'); + if ($navigationTitle instanceof TitleNode) { + $titleNode = $navigationTitle; + } + $documentEntriesInTree[] = $documentEntry; $newEntryNode = new InternalMenuEntryNode( $documentEntry->getFile(), - $documentEntry->getTitle(), + $titleNode, [], false, 1, diff --git a/packages/guides/src/Compiler/NodeTransformers/MenuNodeTransformers/InternalMenuEntryNodeTransformer.php b/packages/guides/src/Compiler/NodeTransformers/MenuNodeTransformers/InternalMenuEntryNodeTransformer.php index 82245cc99..1e5dd6a63 100644 --- a/packages/guides/src/Compiler/NodeTransformers/MenuNodeTransformers/InternalMenuEntryNodeTransformer.php +++ b/packages/guides/src/Compiler/NodeTransformers/MenuNodeTransformers/InternalMenuEntryNodeTransformer.php @@ -19,6 +19,7 @@ use phpDocumentor\Guides\Nodes\Menu\MenuNode; use phpDocumentor\Guides\Nodes\Menu\TocNode; use phpDocumentor\Guides\Nodes\Node; +use phpDocumentor\Guides\Nodes\TitleNode; use phpDocumentor\Guides\ReferenceResolvers\DocumentNameResolverInterface; use Psr\Log\LoggerInterface; @@ -63,10 +64,20 @@ protected function handleMenuEntry(MenuNode $currentMenu, MenuEntryNode $entryNo continue; } + $titleNode = $documentEntry->getTitle(); + $navigationTitle = $documentEntry->getAdditionalData('navigationTitle'); + if ($navigationTitle instanceof TitleNode) { + $titleNode = $navigationTitle; + } + + if ($entryNode->getValue() instanceof TitleNode) { + $titleNode = $entryNode->getValue(); + } + $documentEntriesInTree[] = $documentEntry; $newEntryNode = new InternalMenuEntryNode( $documentEntry->getFile(), - $entryNode->getValue() ?? $documentEntry->getTitle(), + $titleNode, [], false, 1, diff --git a/packages/guides/src/Event/ModifyDocumentEntryAdditionalData.php b/packages/guides/src/Event/ModifyDocumentEntryAdditionalData.php new file mode 100644 index 000000000..d0e3a25f8 --- /dev/null +++ b/packages/guides/src/Event/ModifyDocumentEntryAdditionalData.php @@ -0,0 +1,53 @@ + $additionalData */ + public function __construct( + private array $additionalData, + private readonly DocumentNode $documentNode, + private readonly CompilerContext $compilerContext, + ) { + } + + /** @return array */ + public function getAdditionalData(): array + { + return $this->additionalData; + } + + /** @param array $additionalData */ + public function setAdditionalData(array $additionalData): ModifyDocumentEntryAdditionalData + { + $this->additionalData = $additionalData; + + return $this; + } + + public function getDocumentNode(): DocumentNode + { + return $this->documentNode; + } + + public function getCompilerContext(): CompilerContext + { + return $this->compilerContext; + } +} diff --git a/packages/guides/src/NodeRenderers/Html/BreadCrumbNodeRenderer.php b/packages/guides/src/NodeRenderers/Html/BreadCrumbNodeRenderer.php index 8c4d28da1..24c07e382 100644 --- a/packages/guides/src/NodeRenderers/Html/BreadCrumbNodeRenderer.php +++ b/packages/guides/src/NodeRenderers/Html/BreadCrumbNodeRenderer.php @@ -19,6 +19,7 @@ use phpDocumentor\Guides\Nodes\Menu\InternalMenuEntryNode; use phpDocumentor\Guides\Nodes\Menu\MenuEntryNode; use phpDocumentor\Guides\Nodes\Node; +use phpDocumentor\Guides\Nodes\TitleNode; use phpDocumentor\Guides\RenderContext; use phpDocumentor\Guides\TemplateRenderer; @@ -107,9 +108,15 @@ private function buildBreadcrumb( int $level, bool $isCurrent, ): array { + $title = $documentEntry->getTitle(); + $navigationTitle = $documentEntry->getAdditionalData('navigationTitle'); + if ($navigationTitle instanceof TitleNode) { + $title = $navigationTitle; + } + $entry = new InternalMenuEntryNode( $documentEntry->getFile(), - $documentEntry->getTitle(), + $title, [], false, $level, diff --git a/packages/guides/src/Nodes/DocumentNode.php b/packages/guides/src/Nodes/DocumentNode.php index 1acead6b5..05f89745d 100644 --- a/packages/guides/src/Nodes/DocumentNode.php +++ b/packages/guides/src/Nodes/DocumentNode.php @@ -19,6 +19,7 @@ use phpDocumentor\Guides\Nodes\DocumentTree\SectionEntryNode; use phpDocumentor\Guides\Nodes\Menu\TocNode; use phpDocumentor\Guides\Nodes\Metadata\MetadataNode; +use phpDocumentor\Guides\Nodes\Metadata\NavigationTitleNode; use function array_filter; use function max; @@ -52,6 +53,8 @@ final class DocumentNode extends CompoundNode private int $maxFootnoteNumber = 0; private int $lastReturnedAnonymousFootnoteNumber = -1; + private string|null $navigationTitle = null; + /** * Variables are replacements in a document or project. * @@ -97,6 +100,11 @@ public function getNodes(string $nodeType = Node::class): array return array_filter($this->value, static fn ($node): bool => $node instanceof $nodeType); } + public function getNavigationTitle(): string|null + { + return $this->navigationTitle; + } + public function getPageTitle(): string|null { if ($this->metaTitle !== null) { @@ -132,6 +140,10 @@ public function setMetaTitle(string $metaTitle): void public function addHeaderNode(MetadataNode $node): void { + if ($node instanceof NavigationTitleNode) { + $this->navigationTitle = $node->getValue(); + } + $this->headerNodes[] = $node; } diff --git a/packages/guides/src/Nodes/DocumentTree/DocumentEntryNode.php b/packages/guides/src/Nodes/DocumentTree/DocumentEntryNode.php index 0d1b1882e..6dfac5ad5 100644 --- a/packages/guides/src/Nodes/DocumentTree/DocumentEntryNode.php +++ b/packages/guides/src/Nodes/DocumentTree/DocumentEntryNode.php @@ -13,6 +13,7 @@ namespace phpDocumentor\Guides\Nodes\DocumentTree; +use phpDocumentor\Guides\Nodes\Node; use phpDocumentor\Guides\Nodes\SectionNode; use phpDocumentor\Guides\Nodes\TitleNode; @@ -27,10 +28,12 @@ final class DocumentEntryNode extends EntryNode /** @var SectionEntryNode[] */ private array $sections = []; + /** @param array $additionalData */ public function __construct( private readonly string $file, private readonly TitleNode $titleNode, private readonly bool $isRoot = false, + private array $additionalData = [], ) { } @@ -100,4 +103,14 @@ public function findSectionEntry(SectionNode $sectionNode): SectionEntryNode|nul return null; } + + public function getAdditionalData(string $key): Node|null + { + return $this->additionalData[$key] ?? null; + } + + public function addAdditionalData(string $key, Node $value): void + { + $this->additionalData[$key] = $value; + } } diff --git a/packages/guides/src/Nodes/Metadata/NavigationTitleNode.php b/packages/guides/src/Nodes/Metadata/NavigationTitleNode.php new file mode 100644 index 000000000..95cb0b656 --- /dev/null +++ b/packages/guides/src/Nodes/Metadata/NavigationTitleNode.php @@ -0,0 +1,26 @@ + + + + Another Page - Bootstrap Theme + + + + + + + +
+ + +
+
+
+
+
+
+ + +
+
+ + + + +
+

Another Page

+ +

Lorem Ipsum Dolor.

+ +
+ +
+
+
+
+
+ + + + + + + + + + + \ No newline at end of file diff --git a/tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/expected/index.html b/tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/expected/index.html new file mode 100644 index 000000000..c9a1d1a91 --- /dev/null +++ b/tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/expected/index.html @@ -0,0 +1,106 @@ + + + + Document Title - Bootstrap Theme + + + + + + + +
+ + +
+
+
+
+
+
+ + +
+
+ + + + +
+

Document Title

+ +

Lorem Ipsum Dolor.

+ + +
+ +
+
+
+
+
+ + + + + + + + + + + \ No newline at end of file diff --git a/tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/expected/yetAnotherPage.html b/tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/expected/yetAnotherPage.html new file mode 100644 index 000000000..629055ca6 --- /dev/null +++ b/tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/expected/yetAnotherPage.html @@ -0,0 +1,106 @@ + + + + Yet Another Page - Bootstrap Theme + + + + Title in Menu + + + +
+ + +
+
+
+
+
+
+ + +
+
+ + + + +
+

Yet Another Page

+ +

Lorem Ipsum Dolor.

+ +
+ +
+
+
+
+
+ + + + + + + + + + + \ No newline at end of file diff --git a/tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/input/anotherPage.rst b/tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/input/anotherPage.rst new file mode 100644 index 000000000..5e259c9eb --- /dev/null +++ b/tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/input/anotherPage.rst @@ -0,0 +1,7 @@ +.. include:: /include.rst.txt + +============ +Another Page +============ + +Lorem Ipsum Dolor. diff --git a/tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/input/guides.xml b/tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/input/guides.xml new file mode 100644 index 000000000..4889c7b2e --- /dev/null +++ b/tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/input/guides.xml @@ -0,0 +1,8 @@ + + + + diff --git a/tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/input/include.rst.txt b/tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/input/include.rst.txt new file mode 100644 index 000000000..c234e39bb --- /dev/null +++ b/tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/input/include.rst.txt @@ -0,0 +1,6 @@ +.. documentblock:: + :identifier: footer + + Generated by `phpDocumentor `__. + +.. role:: custom diff --git a/tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/input/index.rst b/tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/input/index.rst new file mode 100644 index 000000000..2f0e5082d --- /dev/null +++ b/tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/input/index.rst @@ -0,0 +1,19 @@ +.. include:: /include.rst.txt + +:project: + Bootstrap Theme +:version: + 1.0 + +============== +Document Title +============== + +Lorem Ipsum Dolor. + +.. toctree:: + :hidden: + :glob: + :titlesonly: + + * diff --git a/tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/input/somePage.rst b/tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/input/somePage.rst new file mode 100644 index 000000000..dfdf1d25d --- /dev/null +++ b/tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/input/somePage.rst @@ -0,0 +1,7 @@ +.. include:: /include.rst.txt + +========= +Some Page +========= + +Lorem Ipsum :custom:`Dolor`. diff --git a/tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/input/yetAnotherPage.rst b/tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/input/yetAnotherPage.rst new file mode 100644 index 000000000..df7bb789d --- /dev/null +++ b/tests/Integration/tests-full/bootstrap/bootstrap-navigation-title/input/yetAnotherPage.rst @@ -0,0 +1,9 @@ +:navigation-title: Title in Menu + +.. include:: /include.rst.txt + +================ +Yet Another Page +================ + +Lorem Ipsum Dolor.