diff --git a/guides.xml b/guides.xml index 88ebdd74d..1ef75405a 100644 --- a/guides.xml +++ b/guides.xml @@ -11,6 +11,8 @@ log-path="php://stder" > + phpdoc + php diff --git a/packages/guides-cli/resources/schema/guides.xsd b/packages/guides-cli/resources/schema/guides.xsd index b154e554c..bd326a1b8 100644 --- a/packages/guides-cli/resources/schema/guides.xsd +++ b/packages/guides-cli/resources/schema/guides.xsd @@ -14,6 +14,7 @@ + diff --git a/packages/guides-restructured-text/resources/config/guides-restructured-text.php b/packages/guides-restructured-text/resources/config/guides-restructured-text.php index 19b496047..fd1d61f83 100644 --- a/packages/guides-restructured-text/resources/config/guides-restructured-text.php +++ b/packages/guides-restructured-text/resources/config/guides-restructured-text.php @@ -116,6 +116,7 @@ use phpDocumentor\Guides\RestructuredText\TextRoles\TextRoleFactory; use phpDocumentor\Guides\RestructuredText\Toc\GlobSearcher; use phpDocumentor\Guides\RestructuredText\Toc\ToctreeBuilder; +use phpDocumentor\Guides\Settings\SettingsManager; use Psr\Log\LoggerInterface; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; @@ -234,9 +235,11 @@ ->set(WarningDirective::class) ->set(YoutubeDirective::class) - + ->set(GenericTextRole::class, GenericTextRole::class) + ->arg('$settingsManager', inline_service(SettingsManager::class)) ->set(DefaultTextRoleFactory::class, DefaultTextRoleFactory::class) - ->arg('$genericTextRole', inline_service(GenericTextRole::class)) + ->arg('$genericTextRole', service(GenericTextRole::class)) + ->arg('$defaultTextRole', inline_service(LiteralTextRole::class)) ->arg('$textRoles', tagged_iterator('phpdoc.guides.parser.rst.text_role')) ->alias(TextRoleFactory::class, DefaultTextRoleFactory::class) diff --git a/packages/guides-restructured-text/src/RestructuredText/Directives/GeneralDirective.php b/packages/guides-restructured-text/src/RestructuredText/Directives/GeneralDirective.php index 46a5637c9..23dbba73f 100644 --- a/packages/guides-restructured-text/src/RestructuredText/Directives/GeneralDirective.php +++ b/packages/guides-restructured-text/src/RestructuredText/Directives/GeneralDirective.php @@ -19,12 +19,26 @@ use phpDocumentor\Guides\RestructuredText\Nodes\GeneralDirectiveNode; use phpDocumentor\Guides\RestructuredText\Parser\BlockContext; use phpDocumentor\Guides\RestructuredText\Parser\Directive; +use phpDocumentor\Guides\RestructuredText\Parser\Productions\Rule; +use phpDocumentor\Guides\Settings\SettingsManager; + +use function explode; +use function in_array; +use function str_contains; /** * A catch-all directive, the content is treated as content, the options passed on */ final class GeneralDirective extends SubDirective { + /** @param Rule $startingRule */ + public function __construct( + Rule $startingRule, + private readonly SettingsManager $settingsManager, + ) { + parent::__construct($startingRule); + } + public function getName(): string { return ''; @@ -39,6 +53,13 @@ protected function processSub( CollectionNode $collectionNode, Directive $directive, ): Node|null { + if (str_contains($directive->getName(), ':')) { + [$domainName, $directiveName] = explode(':', $directive->getName()); + if (in_array($domainName, $this->settingsManager->getProjectSettings()->getIgnoredDomains(), true)) { + return $collectionNode; + } + } + return new GeneralDirectiveNode( $directive->getName(), $directive->getData(), diff --git a/packages/guides-restructured-text/src/RestructuredText/TextRoles/GenericTextRole.php b/packages/guides-restructured-text/src/RestructuredText/TextRoles/GenericTextRole.php index f2ad3ca84..0d52e319c 100644 --- a/packages/guides-restructured-text/src/RestructuredText/TextRoles/GenericTextRole.php +++ b/packages/guides-restructured-text/src/RestructuredText/TextRoles/GenericTextRole.php @@ -14,19 +14,38 @@ namespace phpDocumentor\Guides\RestructuredText\TextRoles; use phpDocumentor\Guides\Nodes\Inline\GenericTextRoleInlineNode; +use phpDocumentor\Guides\Nodes\Inline\InlineNode; +use phpDocumentor\Guides\Nodes\Inline\PlainTextInlineNode; use phpDocumentor\Guides\RestructuredText\Parser\DocumentParserContext; +use phpDocumentor\Guides\Settings\SettingsManager; + +use function explode; +use function in_array; +use function str_contains; final class GenericTextRole extends BaseTextRole { protected string $name = 'default'; protected string|null $baseRole = null; + public function __construct( + private readonly SettingsManager $settingsManager, + ) { + } + public function processNode( DocumentParserContext $documentParserContext, string $role, string $content, string $rawContent, - ): GenericTextRoleInlineNode { + ): InlineNode { + if (str_contains($role, ':')) { + [$domainName, $directiveName] = explode(':', $role); + if (in_array($domainName, $this->settingsManager->getProjectSettings()->getIgnoredDomains(), true)) { + return new PlainTextInlineNode($content); + } + } + return new GenericTextRoleInlineNode($this->baseRole ?? $role, $content, $this->getClass()); } diff --git a/packages/guides-restructured-text/tests/unit/NodeRenderers/Html/GeneralDirectiveNodeRendererTest.php b/packages/guides-restructured-text/tests/unit/NodeRenderers/Html/GeneralDirectiveNodeRendererTest.php index f5d042d10..36560ab23 100644 --- a/packages/guides-restructured-text/tests/unit/NodeRenderers/Html/GeneralDirectiveNodeRendererTest.php +++ b/packages/guides-restructured-text/tests/unit/NodeRenderers/Html/GeneralDirectiveNodeRendererTest.php @@ -20,6 +20,7 @@ use phpDocumentor\Guides\RestructuredText\TextRoles\DefaultTextRoleFactory; use phpDocumentor\Guides\RestructuredText\TextRoles\GenericTextRole; use phpDocumentor\Guides\RestructuredText\TextRoles\LiteralTextRole; +use phpDocumentor\Guides\Settings\SettingsManager; use phpDocumentor\Guides\TemplateRenderer; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\MockObject\MockObject; @@ -40,7 +41,7 @@ public function setUp(): void new Logger('test'), ); $textRoleFactory = new DefaultTextRoleFactory( - new GenericTextRole(), + new GenericTextRole(self::createMock(SettingsManager::class)), new LiteralTextRole(), [], ); diff --git a/packages/guides-restructured-text/tests/unit/Parser/InlineTokenParserTest.php b/packages/guides-restructured-text/tests/unit/Parser/InlineTokenParserTest.php index dff5597b0..a686f4e87 100644 --- a/packages/guides-restructured-text/tests/unit/Parser/InlineTokenParserTest.php +++ b/packages/guides-restructured-text/tests/unit/Parser/InlineTokenParserTest.php @@ -47,6 +47,7 @@ use phpDocumentor\Guides\RestructuredText\TextRoles\GenericTextRole; use phpDocumentor\Guides\RestructuredText\TextRoles\LiteralTextRole; use phpDocumentor\Guides\RestructuredText\TextRoles\ReferenceTextRole; +use phpDocumentor\Guides\Settings\SettingsManager; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -59,7 +60,7 @@ final class InlineTokenParserTest extends TestCase public function setUp(): void { $this->textRoleFactory = new DefaultTextRoleFactory( - new GenericTextRole(), + new GenericTextRole(self::createMock(SettingsManager::class)), new LiteralTextRole(), [ new ReferenceTextRole(), diff --git a/packages/guides-restructured-text/tests/unit/Parser/Productions/DirectiveRuleTest.php b/packages/guides-restructured-text/tests/unit/Parser/Productions/DirectiveRuleTest.php index f9b14d30a..a591f6c51 100644 --- a/packages/guides-restructured-text/tests/unit/Parser/Productions/DirectiveRuleTest.php +++ b/packages/guides-restructured-text/tests/unit/Parser/Productions/DirectiveRuleTest.php @@ -21,6 +21,7 @@ use phpDocumentor\Guides\RestructuredText\Directives\OptionMapper\CodeNodeOptionMapper; use phpDocumentor\Guides\RestructuredText\Parser\DummyBaseDirective; use phpDocumentor\Guides\RestructuredText\Parser\DummyNode; +use phpDocumentor\Guides\Settings\SettingsManager; use PHPUnit\Framework\Attributes\DataProvider; use function array_values; @@ -36,7 +37,7 @@ public function setUp(): void $this->rule = new DirectiveRule( $this->givenInlineMarkupRule(), new Logger('test'), - new GeneralDirective(new DirectiveContentRule(new RuleContainer())), + new GeneralDirective(new DirectiveContentRule(new RuleContainer()), self::createMock(SettingsManager::class)), [$this->directiveHandler], ); } @@ -112,7 +113,7 @@ public function testCodeBlockValue(string $input, string $expectedValue): void $this->rule = new DirectiveRule( $this->givenInlineMarkupRule(), new Logger('test'), - new GeneralDirective(new DirectiveContentRule(new RuleContainer())), + new GeneralDirective(new DirectiveContentRule(new RuleContainer()), self::createMock(SettingsManager::class)), [$this->directiveHandler, new CodeBlockDirective($logger, $this->createMock(CodeNodeOptionMapper::class))], ); $context = $this->createContext($input); diff --git a/packages/guides-restructured-text/tests/unit/TextRoles/DefaultTextRoleFactoryTest.php b/packages/guides-restructured-text/tests/unit/TextRoles/DefaultTextRoleFactoryTest.php index 8e5d396bd..7e05219ba 100644 --- a/packages/guides-restructured-text/tests/unit/TextRoles/DefaultTextRoleFactoryTest.php +++ b/packages/guides-restructured-text/tests/unit/TextRoles/DefaultTextRoleFactoryTest.php @@ -14,6 +14,7 @@ namespace phpDocumentor\Guides\RestructuredText\TextRoles; use Monolog\Logger; +use phpDocumentor\Guides\Settings\SettingsManager; use PHPUnit\Framework\TestCase; final class DefaultTextRoleFactoryTest extends TestCase @@ -25,7 +26,7 @@ public function setUp(): void { $this->logger = new Logger('test'); $this->defaultTextRoleFactory = new DefaultTextRoleFactory( - new GenericTextRole(), + new GenericTextRole(self::createMock(SettingsManager::class)), new LiteralTextRole(), [], [], @@ -38,12 +39,6 @@ public function testUnknownTextRoleReturnsGenericTextRole(): void self::assertInstanceOf(GenericTextRole::class, $textRole); } - public function testUnknownDomainReturnsGenericTextRole(): void - { - $textRole = $this->defaultTextRoleFactory->getTextRole('unknown', 'unknown'); - self::assertInstanceOf(GenericTextRole::class, $textRole); - } - public function testRegisteredTextRoleIsReturned(): void { $this->defaultTextRoleFactory->registerTextRole(new AbbreviationTextRole($this->logger)); diff --git a/packages/guides-restructured-text/tests/unit/TextRoles/GenericTextRoleTest.php b/packages/guides-restructured-text/tests/unit/TextRoles/GenericTextRoleTest.php new file mode 100644 index 000000000..7b32ececd --- /dev/null +++ b/packages/guides-restructured-text/tests/unit/TextRoles/GenericTextRoleTest.php @@ -0,0 +1,53 @@ +projectSettings = new ProjectSettings(); + $this->settingsManager = new SettingsManager($this->projectSettings); + $this->documentParserContext = self::createMock(DocumentParserContext::class); + $this->subject = new GenericTextRole( + $this->settingsManager, + ); + } + + public function testIgnoredDomainReturnsPlainTextInlineNode(): void + { + $this->projectSettings->setIgnoredDomains(['ignored', 'alsoignored']); + $inline = $this->subject->processNode($this->documentParserContext, 'ignored:role', '', ''); + self::assertInstanceOf(PlainTextInlineNode::class, $inline); + } + + public function testUnknownDomainReturnsGenericTextRoleInlineNode(): void + { + $this->projectSettings->setIgnoredDomains(['ignored', 'alsoignored']); + $inline = $this->subject->processNode($this->documentParserContext, 'notignored:role', '', ''); + self::assertInstanceOf(GenericTextRoleInlineNode::class, $inline); + } +} diff --git a/packages/guides/src/DependencyInjection/GuidesExtension.php b/packages/guides/src/DependencyInjection/GuidesExtension.php index 3b23ca271..89904c0d4 100644 --- a/packages/guides/src/DependencyInjection/GuidesExtension.php +++ b/packages/guides/src/DependencyInjection/GuidesExtension.php @@ -104,6 +104,16 @@ static function ($value) { ->end() ->scalarPrototype()->end() ->end() + ->arrayNode('ignored_domain') + ->defaultValue([]) + ->beforeNormalization() + ->ifString() + ->then(static function ($value) { + return [$value]; + }) + ->end() + ->scalarPrototype()->end() + ->end() ->scalarNode('log_path')->end() ->scalarNode('fail_on_log')->end() ->scalarNode('fail_on_error')->end() @@ -217,6 +227,10 @@ public function load(array $configs, ContainerBuilder $container): void $projectSettings->setOutputFormats($config['output_format']); } + if (isset($config['ignored_domain']) && is_array($config['ignored_domain'])) { + $projectSettings->setIgnoredDomains($config['ignored_domain']); + } + if (isset($config['links_are_relative'])) { $projectSettings->setLinksRelative((bool) $config['links_are_relative']); } diff --git a/packages/guides/src/Settings/ProjectSettings.php b/packages/guides/src/Settings/ProjectSettings.php index 23e539bab..84b5272a5 100644 --- a/packages/guides/src/Settings/ProjectSettings.php +++ b/packages/guides/src/Settings/ProjectSettings.php @@ -35,6 +35,9 @@ final class ProjectSettings private string $defaultCodeLanguage = ''; private int $maxMenuDepth = 0; + /** @var string[] */ + private array $ignoredDomains = []; + public function getTitle(): string { return $this->title; @@ -215,4 +218,16 @@ public function setMaxMenuDepth(int $maxMenuDepth): ProjectSettings return $this; } + + /** @return string[] */ + public function getIgnoredDomains(): array + { + return $this->ignoredDomains; + } + + /** @param string[] $ignoredDomains */ + public function setIgnoredDomains(array $ignoredDomains): void + { + $this->ignoredDomains = $ignoredDomains; + } }