Skip to content

Commit fd9d376

Browse files
jaapiowouterj
andcommitted
[FEATURE] add configuration block directive
Add the implementation of the configuration block directive. To make the implemtation more generic a configuration option is introduced. This will allow the users to configure their own labels. Co-authored-by: Wouter de Jong <[email protected]>
1 parent 5035642 commit fd9d376

File tree

3 files changed

+126
-1
lines changed

3 files changed

+126
-1
lines changed

resources/config/guides-restructured-text.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use phpDocumentor\Guides\RestructuredText\Directives\CautionDirective;
1212
use phpDocumentor\Guides\RestructuredText\Directives\ClassDirective;
1313
use phpDocumentor\Guides\RestructuredText\Directives\CodeBlockDirective;
14+
use phpDocumentor\Guides\RestructuredText\Directives\ConfigurationBlockDirective;
1415
use phpDocumentor\Guides\RestructuredText\Directives\ConfvalDirective;
1516
use phpDocumentor\Guides\RestructuredText\Directives\ContainerDirective;
1617
use phpDocumentor\Guides\RestructuredText\Directives\ContentsDirective;
@@ -115,6 +116,7 @@
115116
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
116117

117118
use function Symfony\Component\DependencyInjection\Loader\Configurator\inline_service;
119+
use function Symfony\Component\DependencyInjection\Loader\Configurator\param;
118120
use function Symfony\Component\DependencyInjection\Loader\Configurator\service;
119121
use function Symfony\Component\DependencyInjection\Loader\Configurator\tagged_iterator;
120122

@@ -175,6 +177,10 @@
175177
),
176178
])
177179
->set(ConfvalDirective::class)
180+
->set(ConfigurationBlockDirective::class)
181+
->args([
182+
'$languageLabels' => param('phpdoc.rst.code_language_labels'),
183+
])
178184
->set(ContainerDirective::class)
179185
->set(ContentsDirective::class)
180186
->arg('$documentNameResolver', service(DocumentNameResolverInterface::class))

src/RestructuredText/DependencyInjection/ReStructuredTextExtension.php

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,41 @@
88
use phpDocumentor\Guides\RestructuredText\Nodes\ConfvalNode;
99
use phpDocumentor\Guides\RestructuredText\Nodes\OptionNode;
1010
use phpDocumentor\Guides\RestructuredText\Nodes\VersionChangeNode;
11+
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
12+
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
13+
use Symfony\Component\Config\Definition\ConfigurationInterface;
1114
use Symfony\Component\Config\FileLocator;
1215
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
1316
use Symfony\Component\DependencyInjection\ContainerBuilder;
1417
use Symfony\Component\DependencyInjection\Extension\Extension;
1518
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
1619
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
1720

21+
use function assert;
1822
use function dirname;
1923
use function phpDocumentor\Guides\DependencyInjection\template;
2024

21-
class ReStructuredTextExtension extends Extension implements PrependExtensionInterface, CompilerPassInterface
25+
final class ReStructuredTextExtension extends Extension implements
26+
PrependExtensionInterface,
27+
CompilerPassInterface,
28+
ConfigurationInterface
2229
{
2330
/** @param mixed[] $configs */
2431
public function load(array $configs, ContainerBuilder $container): void
2532
{
33+
$configuration = $this->getConfiguration($configs, $container);
34+
$config = $this->processConfiguration($configuration, $configs);
2635
$loader = new PhpFileLoader(
2736
$container,
2837
new FileLocator(dirname(__DIR__, 3) . '/resources/config'),
2938
);
3039

40+
$normalizedLanguageLabels = [];
41+
foreach ($config['code_language_labels'] ?? [] as $item) {
42+
$normalizedLanguageLabels[$item['language']] = $item['label'];
43+
}
44+
45+
$container->setParameter('phpdoc.rst.code_language_labels', $normalizedLanguageLabels);
3146
$loader->load('guides-restructured-text.php');
3247
}
3348

@@ -55,4 +70,36 @@ public function process(ContainerBuilder $container): void
5570
{
5671
(new TextRolePass())->process($container);
5772
}
73+
74+
public function getConfigTreeBuilder(): TreeBuilder
75+
{
76+
$treeBuilder = new TreeBuilder('rst');
77+
$rootNode = $treeBuilder->getRootNode();
78+
assert($rootNode instanceof ArrayNodeDefinition);
79+
80+
$rootNode
81+
->fixXmlConfig('code_language_label', 'code_language_labels')
82+
->children()
83+
->arrayNode('code_language_labels')
84+
->arrayPrototype()
85+
->children()
86+
->scalarNode('language')
87+
->isRequired()
88+
->end()
89+
->scalarNode('label')
90+
->isRequired()
91+
->end()
92+
->end()
93+
->end()
94+
->end()
95+
->end();
96+
97+
return $treeBuilder;
98+
}
99+
100+
/** @param mixed[] $config */
101+
public function getConfiguration(array $config, ContainerBuilder $container): static
102+
{
103+
return $this;
104+
}
58105
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace phpDocumentor\Guides\RestructuredText\Directives;
6+
7+
use phpDocumentor\Guides\Nodes\CodeNode;
8+
use phpDocumentor\Guides\Nodes\CollectionNode;
9+
use phpDocumentor\Guides\Nodes\Configuration\ConfigurationBlockNode;
10+
use phpDocumentor\Guides\Nodes\Configuration\ConfigurationTab;
11+
use phpDocumentor\Guides\Nodes\Node;
12+
use phpDocumentor\Guides\RestructuredText\Parser\BlockContext;
13+
use phpDocumentor\Guides\RestructuredText\Parser\Directive;
14+
use phpDocumentor\Guides\RestructuredText\Parser\Productions\Rule;
15+
use Psr\Log\LoggerInterface;
16+
use Symfony\Component\String\Slugger\AsciiSlugger;
17+
use Symfony\Component\String\Slugger\SluggerInterface;
18+
19+
use function assert;
20+
use function get_debug_type;
21+
22+
final class ConfigurationBlockDirective extends SubDirective
23+
{
24+
private SluggerInterface $slugger;
25+
26+
/**
27+
* @param Rule<CollectionNode> $startingRule
28+
* @param array<string, string> $languageLabels
29+
*/
30+
public function __construct(
31+
private LoggerInterface $logger,
32+
Rule $startingRule,
33+
private readonly array $languageLabels = [],
34+
) {
35+
parent::__construct($startingRule);
36+
37+
$this->slugger = new AsciiSlugger();
38+
}
39+
40+
public function getName(): string
41+
{
42+
return 'configuration-block';
43+
}
44+
45+
protected function processSub(
46+
BlockContext $blockContext,
47+
CollectionNode $collectionNode,
48+
Directive $directive,
49+
): Node|null {
50+
$tabs = [];
51+
foreach ($collectionNode->getValue() as $child) {
52+
if (!$child instanceof CodeNode) {
53+
$this->logger->warning('The ".. configuration-block::" directive only supports code blocks, "' . get_debug_type($child) . '" given.');
54+
55+
continue;
56+
}
57+
58+
$language = $child->getLanguage();
59+
assert($language !== null);
60+
61+
$label = $this->languageLabels[$language] ?? $this->slugger->slug($language, ' ')->title()->toString();
62+
63+
$tabs[] = new ConfigurationTab(
64+
$label,
65+
$this->slugger->slug($label)->lower()->toString(),
66+
$child,
67+
);
68+
}
69+
70+
return new ConfigurationBlockNode($tabs);
71+
}
72+
}

0 commit comments

Comments
 (0)