diff --git a/src/Generator/JsonGenerator.php b/src/Generator/JsonGenerator.php index 988528a..6a087b6 100644 --- a/src/Generator/JsonGenerator.php +++ b/src/Generator/JsonGenerator.php @@ -20,6 +20,7 @@ use Symfony\Component\DomCrawler\Crawler; use Symfony\Component\Filesystem\Filesystem; use SymfonyDocsBuilder\BuildConfig; +use SymfonyDocsBuilder\Twig\TocExtension; use function Symfony\Component\String\u; class JsonGenerator @@ -73,7 +74,8 @@ public function generateJson(string $masterDocument = 'index'): array 'title' => $metaEntry->getTitle(), 'parents' => $this->determineParents($parserFilename, $tocTreeHierarchy) ?: [], 'current_page_name' => $parserFilename, - 'toc' => $this->generateToc($metaEntry, current($metaEntry->getTitles())[1]), + 'toc' => $toc = $this->generateToc($metaEntry, current($metaEntry->getTitles())[1]), + 'toc_options' => TocExtension::getOptions($toc), 'next' => $next, 'prev' => $prev, 'body' => $crawler->filter('body')->html(), @@ -98,7 +100,7 @@ public function setOutput(SymfonyStyle $output) $this->output = $output; } - private function generateToc(MetaEntry $metaEntry, ?array $titles): array + private function generateToc(MetaEntry $metaEntry, ?array $titles, int $level = 1): array { if (null === $titles) { return []; @@ -108,11 +110,12 @@ private function generateToc(MetaEntry $metaEntry, ?array $titles): array foreach ($titles as $title) { $tocTree[] = [ + 'level' => $level, 'url' => sprintf('%s#%s', $metaEntry->getUrl(), Environment::slugify($title[0])), 'page' => u($metaEntry->getUrl())->beforeLast('.html'), 'fragment' => Environment::slugify($title[0]), 'title' => $title[0], - 'children' => $this->generateToc($metaEntry, $title[1]), + 'children' => $this->generateToc($metaEntry, $title[1], $level + 1), ]; } diff --git a/src/KernelFactory.php b/src/KernelFactory.php index c878b6c..80230c0 100644 --- a/src/KernelFactory.php +++ b/src/KernelFactory.php @@ -17,6 +17,7 @@ use SymfonyDocsBuilder\Directive as SymfonyDirectives; use SymfonyDocsBuilder\Reference as SymfonyReferences; use SymfonyDocsBuilder\Twig\AssetsExtension; +use SymfonyDocsBuilder\Twig\TocExtension; use function Symfony\Component\String\u; /** @@ -55,6 +56,7 @@ static function (string $path) use ($parseSubPath): bool { $twig = $configuration->getTemplateEngine(); $twig->addExtension(new AssetsExtension()); + $twig->addExtension(new TocExtension()); return new DocsKernel( $buildConfig, diff --git a/src/Templates/default/html/toc.html.twig b/src/Templates/default/html/toc.html.twig index cad7ccd..55b8737 100644 --- a/src/Templates/default/html/toc.html.twig +++ b/src/Templates/default/html/toc.html.twig @@ -1,5 +1,6 @@ {% apply spaceless %} -
+ {% set toc_options = toc_options(tocItems) %} +
{% include "toc-level.html.twig" %}
{% endapply %} diff --git a/src/Twig/TocExtension.php b/src/Twig/TocExtension.php new file mode 100644 index 0000000..ebea8c8 --- /dev/null +++ b/src/Twig/TocExtension.php @@ -0,0 +1,66 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SymfonyDocsBuilder\Twig; + +use Twig\Extension\AbstractExtension; +use Twig\TwigFunction; + +class TocExtension extends AbstractExtension +{ + public function getFunctions(): array + { + return [ + new TwigFunction('toc_options', [$this, 'getOptions']), + ]; + } + + public static function getOptions(array $toc): array + { + $flattendToc = self::flattenToc($toc); + $maxDepth = 0; + $numVisibleItems = 0; + foreach ($flattendToc as $tocItem) { + $maxDepth = max($maxDepth, $tocItem['level']); + $numVisibleItems++; + } + + return [ + 'maxDepth' => $maxDepth, + 'numVisibleItems' => $numVisibleItems, + 'size' => self::getTocSize($numVisibleItems), + ]; + } + + private static function flattenToc(array $toc, array &$flattenedToc = []): array + { + foreach ($toc as $item) { + $flattenedToc[] = $item; + + if ([] !== $item['children']) { + self::flattenToc($item['children'], $flattenedToc); + } + } + + return $flattenedToc; + } + + private static function getTocSize(int $numVisibleItems): string + { + if ($numVisibleItems < 10) { + return 'md'; + } + + if ($numVisibleItems < 20) { + return 'lg'; + } + + return 'xl'; + } +} diff --git a/tests/JsonIntegrationTest.php b/tests/JsonIntegrationTest.php index 0ef094d..7d3d07b 100644 --- a/tests/JsonIntegrationTest.php +++ b/tests/JsonIntegrationTest.php @@ -74,7 +74,12 @@ public function getJsonTests() 'link' => 'crud.html', ], 'title' => 'Design', - ] + 'toc_options' => [ + 'maxDepth' => 2, + 'numVisibleItems' => 3, + 'size' => 'md' + ], + ], ]; yield 'crud' => [ diff --git a/tests/fixtures/expected/build-pdf/book.html b/tests/fixtures/expected/build-pdf/book.html index deb53f8..a214463 100644 --- a/tests/fixtures/expected/build-pdf/book.html +++ b/tests/fixtures/expected/build-pdf/book.html @@ -6,7 +6,7 @@

Book

Here is a link to the main index

-
+