From f728810ff34cb6a5b9f88552f5ca58b27d61e0dc Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Tue, 19 Apr 2022 22:56:59 +0200 Subject: [PATCH] Add the table of contents to the frontend --- resources/frontend/hyde.css | 170 +++++++++++++++++- resources/frontend/hyde.scss | 29 ++- .../views/components/docs/sidebar.blade.php | 6 +- src/Models/HasTableOfContents.php | 2 + src/Services/MarkdownConverterService.php | 14 +- 5 files changed, 216 insertions(+), 5 deletions(-) diff --git a/resources/frontend/hyde.css b/resources/frontend/hyde.css index bae1cc67..9c99729e 100644 --- a/resources/frontend/hyde.css +++ b/resources/frontend/hyde.css @@ -1 +1,169 @@ -.post-article{max-width:960px}.post-article #byline{margin-bottom:1em}.post-article #byline time,.post-article #byline address,.post-article #byline dl{display:inline}.post-article #byline time dt,.post-article #byline time dd,.post-article #byline address dt,.post-article #byline address dd,.post-article #byline dl dt,.post-article #byline dl dd{display:inline}.post-article h2:first-child{margin-top:0}#sidebar-navigation li.list-item-active a{border-left:4px solid #5956eb;padding-left:calc(1rem - 4px);margin-left:-1rem;padding-top:.25rem;padding-bottom:.25rem;color:#5956eb}.dark #sidebar-navigation li.list-item-active a{color:#fff}@media(max-width: 360px){#documentation-sidebar{width:100%}}#documentation-content{max-width:100vw}@media(min-width: 768px){#documentation-content{max-width:calc(100vw - 20rem)}}#documentation-content code{max-width:80vw;overflow-x:auto;display:inline-block;vertical-align:top}#documentation-content pre code{display:block;max-width:unset}#sidebar-backdrop{width:100vw;height:100vh;background:rgba(128,128,128,.5);position:fixed;top:0;left:0;cursor:pointer}.sidebar-button-wrapper.open button.close{display:none}.sidebar-button-wrapper.closed button.open{display:none}.torchlight-enabled pre{border-radius:.25rem;margin-top:1rem;margin-bottom:1rem;overflow-x:auto;padding:0}.torchlight-enabled pre code.torchlight{display:block;min-width:-webkit-max-content;min-width:-moz-max-content;min-width:max-content;padding-top:1rem;padding-bottom:1rem}.torchlight-enabled pre code.torchlight .line{padding-left:1rem;padding-right:1rem}.torchlight-enabled pre code.torchlight .line-number,.torchlight-enabled pre code.torchlight .summary-caret{margin-right:1rem}#skip-to-content{left:-999px;position:absolute;top:auto;width:1px;height:1px;overflow:hidden;z-index:-999}#skip-to-content:focus,#skip-to-content:active{color:#fff;background-color:#000;left:auto;top:auto;width:30%;height:auto;overflow:auto;margin:10px 35%;padding:5px;border-radius:15px;border:4px solid #ff0;text-align:center;font-size:1.2em;z-index:999}.text-indigo-500,.hover\:text-indigo-500:hover{color:#5956eb} +/** + * Core Stylesheet for the HydePHP Frontend + * + * @package HydePHP - HydeFront + * @version 0.4.0 (HydeFront) + * @author Caen De Silva + * + * @see app.css where TailwindCSS is included, + * to declare your own styles. + */ +/* Base styles for compatibility */ +.post-article { + max-width: 960px; +} +.post-article #byline { + margin-bottom: 1em; +} +.post-article #byline time, .post-article #byline address, .post-article #byline dl { + display: inline; +} +.post-article #byline time dt, .post-article #byline time dd, .post-article #byline address dt, .post-article #byline address dd, .post-article #byline dl dt, .post-article #byline dl dd { + display: inline; +} +.post-article h2:first-child { + margin-top: 0; +} + +#sidebar-navigation li.list-item-active a.link-active { + border-left: 4px solid #5956eb; + padding-left: calc(1rem - 4px); + margin-left: -1rem; + padding-top: 0.25rem; + padding-bottom: 0.25rem; + color: #5956eb; + font-weight: 500; + background: rgba(0, 0, 0, 0.1); + display: inline-block; + width: 100%; +} +#sidebar-navigation .table-of-contents { + margin-top: 0.25rem; + font-size: 90%; +} +#sidebar-navigation .table-of-contents ul { + margin-top: 0.25rem; + margin-bottom: 0.25rem; +} +#sidebar-navigation .table-of-contents li { + margin-top: 0.25rem; + margin-bottom: 0.25rem; + margin-left: 1.5ch; +} +#sidebar-navigation .table-of-contents li a { + opacity: 0.9; +} +#sidebar-navigation .table-of-contents li a:hover { + opacity: 1; +} + +.dark #sidebar-navigation li.list-item-active a.link-active { + color: #fff; + font-weight: 400; +} + +@media (max-width: 360px) { + #documentation-sidebar { + width: 100%; + } +} + +#documentation-content { + max-width: 100vw; +} +@media (min-width: 768px) { + #documentation-content { + max-width: calc(100vw - 20rem); + } +} +#documentation-content code { + max-width: 80vw; + overflow-x: auto; + display: inline-block; + vertical-align: top; +} +#documentation-content pre code { + display: block; + max-width: unset; +} + +#sidebar-backdrop { + width: 100vw; + height: 100vh; + background: rgba(128, 128, 128, 0.5); + position: fixed; + top: 0; + left: 0; + cursor: pointer; +} + +.sidebar-button-wrapper.open button.close { + display: none; +} +.sidebar-button-wrapper.closed button.open { + display: none; +} + +/** + * Styles for Torchlight + * + * Uses the styles from https://torchlight.dev/docs/css + */ +.torchlight-enabled pre { + border-radius: 0.25rem; + margin-top: 1rem; + margin-bottom: 1rem; + overflow-x: auto; + padding: 0; +} +.torchlight-enabled pre code.torchlight { + display: block; + min-width: -webkit-max-content; + min-width: -moz-max-content; + min-width: max-content; + padding-top: 1rem; + padding-bottom: 1rem; +} +.torchlight-enabled pre code.torchlight .line { + padding-left: 1rem; + padding-right: 1rem; +} +.torchlight-enabled pre code.torchlight .line-number, +.torchlight-enabled pre code.torchlight .summary-caret { + margin-right: 1rem; +} + +/** +* Styles for Accessibility +*/ +#skip-to-content { + left: -999px; + position: absolute; + top: auto; + width: 1px; + height: 1px; + overflow: hidden; + z-index: -999; +} +#skip-to-content:focus, #skip-to-content:active { + color: #fff; + background-color: #000; + left: auto; + top: auto; + width: 30%; + height: auto; + overflow: auto; + margin: 10px 35%; + padding: 5px; + border-radius: 15px; + border: 4px solid yellow; + text-align: center; + font-size: 1.2em; + z-index: 999; +} + +.text-indigo-500, .hover\:text-indigo-500:hover { + color: #5956eb; +} + +/*# sourceMappingURL=hyde.css.map */ diff --git a/resources/frontend/hyde.scss b/resources/frontend/hyde.scss index 125e27fc..a277cff6 100644 --- a/resources/frontend/hyde.scss +++ b/resources/frontend/hyde.scss @@ -29,20 +29,45 @@ #sidebar-navigation { li.list-item-active { - a { + a.link-active { border-left: 4px solid #5956eb; padding-left: calc(1rem - 4px); margin-left: -1rem; padding-top: 0.25rem; padding-bottom: 0.25rem; color: #5956eb; + font-weight: 500; + background: rgba(0, 0, 0, 0.1); + display: inline-block; + width: 100%; + } + } + + .table-of-contents { + margin-top: 0.25rem; + font-size: 90%; + ul { + margin-top: 0.25rem; + margin-bottom: 0.25rem; + } + li { + margin-top: 0.25rem; + margin-bottom: 0.25rem; + margin-left: 1.5ch; + a { + opacity: 0.9; + &:hover { + opacity: 1; + } + } } } } .dark { - #sidebar-navigation li.list-item-active a { + #sidebar-navigation li.list-item-active a.link-active { color: #fff; + font-weight: 400; } } diff --git a/resources/views/components/docs/sidebar.blade.php b/resources/views/components/docs/sidebar.blade.php index f13ecb39..240d05ea 100644 --- a/resources/views/components/docs/sidebar.blade.php +++ b/resources/views/components/docs/sidebar.blade.php @@ -8,7 +8,11 @@ 'list-item-active' => $item['active'] ])> @if($item['active']) - {{ $item['title'] }} + {{ $item['title'] }} + + @if($docs->tableOfContents) + {!! ($docs->tableOfContents) !!} + @endif @else {{ $item['title'] }} @endif diff --git a/src/Models/HasTableOfContents.php b/src/Models/HasTableOfContents.php index 7c2bc3da..986b1e5d 100644 --- a/src/Models/HasTableOfContents.php +++ b/src/Models/HasTableOfContents.php @@ -15,6 +15,8 @@ trait HasTableOfContents public function constructTableOfContents(): void { + // @todo add feature to disable table of contents + // if Features::withTableOfContents $this->tableOfContents = (new GeneratesTableOfContents($this->body))->execute(); } } \ No newline at end of file diff --git a/src/Services/MarkdownConverterService.php b/src/Services/MarkdownConverterService.php index 2ee4f10d..3d654613 100644 --- a/src/Services/MarkdownConverterService.php +++ b/src/Services/MarkdownConverterService.php @@ -5,6 +5,7 @@ use Hyde\Framework\Features; use League\CommonMark\CommonMarkConverter; use League\CommonMark\Extension\GithubFlavoredMarkdownExtension; +use League\CommonMark\Extension\HeadingPermalink\HeadingPermalinkExtension; use Torchlight\Commonmark\V2\TorchlightExtension; class MarkdownConverterService @@ -22,9 +23,20 @@ public function __construct(string $markdown, ?bool $useTorchlight = null, ?bool { $this->markdown = $markdown; - $this->converter = new CommonMarkConverter(); + $config = [ + 'heading_permalink' => [ + 'id_prefix' => '', + 'fragment_prefix' => '', + 'symbol' => '', + ], + ]; + + $this->converter = new CommonMarkConverter($config); $this->converter->getEnvironment()->addExtension(new GithubFlavoredMarkdownExtension()); + // If TOC is enabled, add heading permalinks + $this->converter->getEnvironment()->addExtension(new HeadingPermalinkExtension()); + $this->useTorchlight = $useTorchlight ?? $this->determineIfTorchlightShouldBeEnabled(); }