Skip to content

Commit 496624f

Browse files
committed
Add TOC in sidebar for PSRs & PERs
1 parent 554dcde commit 496624f

File tree

5 files changed

+116
-31
lines changed

5 files changed

+116
-31
lines changed

app/config/sculpin_kernel.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,24 @@ services:
4040
tags:
4141
- { name: twig.extension }
4242

43+
fig.website.markdown_toc_extension:
44+
class: Fig\Website\TwigMarkdownTOCExtension
45+
arguments:
46+
$environment: '@League\CommonMark\EnvironmentInterface'
47+
tags:
48+
- { name: twig.extension }
49+
4350
aptoma.twig.markdown_extension:
4451
class: Aptoma\Twig\Extension\MarkdownExtension
4552
arguments:
4653
$markdownEngine: '@Aptoma\Twig\Extension\MarkdownEngineInterface'
4754
tags:
4855
- { name: twig.extension }
4956

57+
League\CommonMark\EnvironmentInterface:
58+
factory: ['Fig\Website\CommonMarkEnvironmentFactory', 'create']
59+
5060
Aptoma\Twig\Extension\MarkdownEngineInterface:
5161
factory: ['Fig\Website\CommonMarkEngineFactory', 'create']
62+
arguments:
63+
$environment: '@League\CommonMark\EnvironmentInterface'

app/lib/CommonMarkEngineFactory.php

Lines changed: 4 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,41 +4,14 @@
44

55
use Aptoma\Twig\Extension\MarkdownEngine\PHPLeagueCommonMarkEngine;
66
use Aptoma\Twig\Extension\MarkdownEngineInterface;
7-
use League\CommonMark\Block\Element\FencedCode;
8-
use League\CommonMark\Block\Element\IndentedCode;
9-
use League\CommonMark\Environment;
10-
use League\CommonMark\Extension\HeadingPermalink\HeadingPermalinkExtension;
11-
use League\CommonMark\Extension\Table\TableExtension;
7+
use League\CommonMark\EnvironmentInterface;
128
use League\CommonMark\GithubFlavoredMarkdownConverter;
13-
use Spatie\CommonMarkHighlighter\FencedCodeRenderer;
14-
use Spatie\CommonMarkHighlighter\IndentedCodeRenderer;
159

1610
class CommonMarkEngineFactory
1711
{
18-
public static function create(): MarkdownEngineInterface
19-
{
20-
$supportedLanguages = [
21-
'php',
22-
'http', # inside PSR-7
23-
];
24-
25-
$config = [
26-
'heading_permalink' => [
27-
'id_prefix' => '',
28-
'fragment_prefix' => '',
29-
'insert' => 'after',
30-
],
31-
];
32-
33-
$environment = Environment::createCommonMarkEnvironment();
34-
$environment->mergeConfig($config);
35-
$environment
36-
->addExtension(new TableExtension())
37-
->addExtension(new HeadingPermalinkExtension())
38-
->addBlockRenderer(FencedCode::class, new FencedCodeRenderer($supportedLanguages))
39-
->addBlockRenderer(IndentedCode::class, new IndentedCodeRenderer($supportedLanguages))
40-
;
41-
12+
public static function create(
13+
EnvironmentInterface $environment,
14+
): MarkdownEngineInterface {
4215
return new NullSafeCommonMarkEngine(
4316
new PHPLeagueCommonMarkEngine(
4417
new GithubFlavoredMarkdownConverter([], $environment)
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
namespace Fig\Website;
4+
5+
use League\CommonMark\Block\Element\FencedCode;
6+
use League\CommonMark\Block\Element\IndentedCode;
7+
use League\CommonMark\Environment;
8+
use League\CommonMark\EnvironmentInterface;
9+
use League\CommonMark\Extension\HeadingPermalink\HeadingPermalinkExtension;
10+
use League\CommonMark\Extension\Table\TableExtension;
11+
use Spatie\CommonMarkHighlighter\FencedCodeRenderer;
12+
use Spatie\CommonMarkHighlighter\IndentedCodeRenderer;
13+
14+
class CommonMarkEnvironmentFactory
15+
{
16+
public static function create(): EnvironmentInterface
17+
{
18+
$supportedLanguages = [
19+
'php',
20+
'http', # inside PSR-7
21+
];
22+
23+
$config = [
24+
'heading_permalink' => [
25+
'id_prefix' => '',
26+
'fragment_prefix' => '',
27+
'insert' => 'after',
28+
],
29+
];
30+
31+
$environment = Environment::createCommonMarkEnvironment();
32+
$environment->mergeConfig($config);
33+
$environment
34+
->addExtension(new TableExtension())
35+
->addExtension(new HeadingPermalinkExtension())
36+
->addBlockRenderer(FencedCode::class, new FencedCodeRenderer($supportedLanguages))
37+
->addBlockRenderer(IndentedCode::class, new IndentedCodeRenderer($supportedLanguages))
38+
;
39+
40+
return $environment;
41+
}
42+
}

app/lib/TwigMarkdownTOCExtension.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
namespace Fig\Website;
4+
5+
use League\CommonMark\DocParser;
6+
use League\CommonMark\DocParserInterface;
7+
use League\CommonMark\ElementRendererInterface;
8+
use League\CommonMark\EnvironmentInterface;
9+
use League\CommonMark\Extension\TableOfContents\TableOfContentsGenerator;
10+
use League\CommonMark\HtmlRenderer;
11+
use Twig\Extension\AbstractExtension;
12+
use Twig\TwigFilter;
13+
14+
class TwigMarkdownTOCExtension extends AbstractExtension
15+
{
16+
private readonly DocParserInterface $docParser;
17+
private readonly ElementRendererInterface $htmlRenderer;
18+
19+
public function __construct(
20+
EnvironmentInterface $environment,
21+
) {
22+
$this->docParser = new DocParser($environment);
23+
$this->htmlRenderer = new HtmlRenderer($environment);
24+
}
25+
26+
public function getFilters()
27+
{
28+
return [
29+
new TwigFilter('markdown_toc', function(string $markdown): string {
30+
return $this->renderTOC($markdown);
31+
}),
32+
];
33+
}
34+
35+
private function renderTOC(string $markdown): string
36+
{
37+
$generator = new TableOfContentsGenerator(
38+
TableOfContentsGenerator::STYLE_ORDERED,
39+
TableOfContentsGenerator::NORMALIZE_RELATIVE,
40+
minHeadingLevel: 2,
41+
maxHeadingLevel: 3,
42+
);
43+
44+
$toc = $generator->generate($this->docParser->parse($markdown));
45+
46+
return $toc === null
47+
? ''
48+
: $this->htmlRenderer->renderBlock($toc, inTightList: true);
49+
}
50+
}

source/_layouts/psr.twig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@
2424
</ul>
2525
</nav>
2626
</div>
27+
28+
<div class="columns__column columns__column--4 columns__column--padding_left">
29+
<nav class="sidebar">
30+
<h2 class="sidebar__title">Table of contents:</h2>
31+
{% set content = include(page.markdown_source) %}
32+
{{ content | markdown_toc | raw }}
33+
</nav>
34+
</div>
2735
{% endif %}
2836
</div>
2937
{% endblock %}

0 commit comments

Comments
 (0)