diff --git a/packages/guides/src/Compiler/NodeTransformers/SectionCreationTransformer.php b/packages/guides/src/Compiler/NodeTransformers/SectionCreationTransformer.php index 4bd481b16..4542f3cc9 100644 --- a/packages/guides/src/Compiler/NodeTransformers/SectionCreationTransformer.php +++ b/packages/guides/src/Compiler/NodeTransformers/SectionCreationTransformer.php @@ -31,10 +31,12 @@ final class SectionCreationTransformer implements NodeTransformer { /** @var SectionNode[] $sectionStack */ private array $sectionStack = []; + private int $firstLevel = 1; public function enterNode(Node $node, CompilerContextInterface $compilerContext): Node { if ($node instanceof DocumentNode) { + $this->firstLevel = 1; $this->sectionStack = []; } @@ -68,7 +70,7 @@ public function leaveNode(Node $node, CompilerContextInterface $compilerContext) if (count($this->sectionStack) > 0 && $compilerContext->getShadowTree()->isLastChildOfParent()) { $lastSection = end($this->sectionStack); - while ($lastSection?->getTitle()->getLevel() > 1) { + while ($lastSection?->getTitle()->getLevel() > $this->firstLevel) { $lastSection = array_pop($this->sectionStack); } @@ -92,9 +94,9 @@ public function leaveNode(Node $node, CompilerContextInterface $compilerContext) end($this->sectionStack)->addChildNode($newSection); } - $this->sectionStack[] = $newSection; + $this->pushNewSectionToStack($newSection); - return $lastSection?->getTitle()->getLevel() === 1 ? $lastSection : null; + return $lastSection?->getTitle()->getLevel() <= $this->firstLevel ? $lastSection : null; } $newSection = new SectionNode($node); @@ -102,7 +104,7 @@ public function leaveNode(Node $node, CompilerContextInterface $compilerContext) $lastSection->addChildNode($newSection); } - $this->sectionStack[] = $newSection; + $this->pushNewSectionToStack($newSection); return null; } @@ -117,4 +119,21 @@ public function getPriority(): int // Should run as first transformer return PHP_INT_MAX; } + + /** + * Pushes the new section to the stack. + * + * The stack is used to track the current level of nodes and adding child + * nodes to the section. As not all documentation formats are using the + * correct level of title nodes we need to track the level of the first + * title node to determine the correct level of the section. + */ + private function pushNewSectionToStack(SectionNode $newSection): void + { + if (count($this->sectionStack) === 0) { + $this->firstLevel = $newSection->getTitle()->getLevel(); + } + + $this->sectionStack[] = $newSection; + } } diff --git a/packages/guides/src/Nodes/DocumentNode.php b/packages/guides/src/Nodes/DocumentNode.php index 05f89745d..fad13d235 100644 --- a/packages/guides/src/Nodes/DocumentNode.php +++ b/packages/guides/src/Nodes/DocumentNode.php @@ -121,7 +121,7 @@ public function getPageTitle(): string|null public function getTitle(): TitleNode|null { foreach ($this->value as $node) { - if ($node instanceof SectionNode && $node->getTitle()->getLevel() === 1) { + if ($node instanceof SectionNode) { return $node->getTitle(); } diff --git a/tests/Integration/tests/markdown/sections-no-level-1-md/expected/index.html b/tests/Integration/tests/markdown/sections-no-level-1-md/expected/index.html new file mode 100644 index 000000000..c4de8e63d --- /dev/null +++ b/tests/Integration/tests/markdown/sections-no-level-1-md/expected/index.html @@ -0,0 +1,45 @@ + + +
This is a sample Markdown document demonstrating sections and subsections.
+ +This is the first section of the document.
+ +This is a subsection under Section 1.
+ +Another subsection under Section 1.
+ +Moving on to the second section of the document.
+ +A subsection under Section 2.
+ +In conclusion, this is a simple example of a Markdown document with various sections and subsections.
+ +