Skip to content

Commit

Permalink
Merge pull request #636 from phpDocumentor/feature/standard-domain
Browse files Browse the repository at this point in the history
[FEATURE] Introduce option directive
  • Loading branch information
linawolf authored Nov 2, 2023
2 parents 5aa985a + 38a4052 commit 4d6ebd2
Show file tree
Hide file tree
Showing 40 changed files with 517 additions and 65 deletions.
4 changes: 2 additions & 2 deletions packages/guides-cli/src/Command/Run.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
use phpDocumentor\Guides\Handlers\ParseDirectoryCommand;
use phpDocumentor\Guides\Handlers\ParseFileCommand;
use phpDocumentor\Guides\Handlers\RenderCommand;
use phpDocumentor\Guides\Intersphinx\InventoryRepository;
use phpDocumentor\Guides\Interlink\InventoryRepository;
use phpDocumentor\Guides\Nodes\ProjectNode;
use phpDocumentor\Guides\Settings\ProjectSettings;
use phpDocumentor\Guides\Settings\SettingsManager;
Expand Down Expand Up @@ -82,7 +82,7 @@ public function __construct(
'output-format',
null,
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'Format of the input can be html and or intersphinx',
'Format of the input can be html and or interlink',
);
$this->addOption(
'log-path',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
use phpDocumentor\Guides\RestructuredText\Directives\MenuDirective;
use phpDocumentor\Guides\RestructuredText\Directives\MetaDirective;
use phpDocumentor\Guides\RestructuredText\Directives\NoteDirective;
use phpDocumentor\Guides\RestructuredText\Directives\OptionDirective;
use phpDocumentor\Guides\RestructuredText\Directives\OptionMapper\CodeNodeOptionMapper;
use phpDocumentor\Guides\RestructuredText\Directives\PullQuoteDirective;
use phpDocumentor\Guides\RestructuredText\Directives\RawDirective;
Expand Down Expand Up @@ -98,6 +99,8 @@
use phpDocumentor\Guides\RestructuredText\TextRoles\AbbreviationTextRole;
use phpDocumentor\Guides\RestructuredText\TextRoles\DefaultTextRoleFactory;
use phpDocumentor\Guides\RestructuredText\TextRoles\DocReferenceTextRole;
use phpDocumentor\Guides\RestructuredText\TextRoles\GenericLinkProvider;
use phpDocumentor\Guides\RestructuredText\TextRoles\GenericReferenceTextRole;
use phpDocumentor\Guides\RestructuredText\TextRoles\GenericTextRole;
use phpDocumentor\Guides\RestructuredText\TextRoles\LiteralTextRole;
use phpDocumentor\Guides\RestructuredText\TextRoles\MathTextRole;
Expand Down Expand Up @@ -143,9 +146,11 @@
'%vendor_dir%/phpdocumentor/guides-restructured-text/src/RestructuredText/NodeRenderers/Html',
)

->set(GenericLinkProvider::class)

->set(DirectiveContentRule::class)
->set(DocReferenceTextRole::class)
->set(GenericReferenceTextRole::class)
->set(ReferenceTextRole::class)
->set(AbbreviationTextRole::class)
->set(MathTextRole::class)
Expand Down Expand Up @@ -193,6 +198,7 @@
])
->set(MetaDirective::class)
->set(NoteDirective::class)
->set(OptionDirective::class)
->set(PullQuoteDirective::class)
->set(RawDirective::class)
->set(ReplaceDirective::class)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{%- for id in node.additionalIds %}
<a id="{{ id }}"></a>
{% endfor -%}
<dl class="domain-default-option">
<dt class="domain-default-option-name" id="{{ node.id }}">{{ node.plainContent }}</dt>
<dd class="domain-default-option-description">
{{ renderNode(node.value) }}
</dd>
</dl>
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use phpDocumentor\Guides\NodeRenderers\TemplateNodeRenderer;
use phpDocumentor\Guides\RestructuredText\DependencyInjection\Compiler\TextRolePass;
use phpDocumentor\Guides\RestructuredText\Nodes\OptionNode;
use phpDocumentor\Guides\RestructuredText\Nodes\VersionChangeNode;
use phpDocumentor\Guides\TemplateRenderer;
use Symfony\Component\Config\FileLocator;
Expand All @@ -23,7 +24,10 @@

class ReStructuredTextExtension extends Extension implements PrependExtensionInterface, CompilerPassInterface
{
private const HTML = [VersionChangeNode::class => 'body/version-change.html.twig'];
private const HTML = [
VersionChangeNode::class => 'body/version-change.html.twig',
OptionNode::class => 'body/directive/option.html.twig',
];

/** @param mixed[] $configs */
public function load(array $configs, ContainerBuilder $container): void
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php

declare(strict_types=1);

namespace phpDocumentor\Guides\RestructuredText\Directives;

use phpDocumentor\Guides\Nodes\CollectionNode;
use phpDocumentor\Guides\Nodes\Node;
use phpDocumentor\Guides\ReferenceResolvers\AnchorReducer;
use phpDocumentor\Guides\RestructuredText\Nodes\OptionNode;
use phpDocumentor\Guides\RestructuredText\Parser\Directive;
use phpDocumentor\Guides\RestructuredText\Parser\Productions\Rule;
use phpDocumentor\Guides\RestructuredText\TextRoles\GenericLinkProvider;

use function array_map;
use function explode;
use function preg_replace;
use function str_contains;

/**
* Describes a command line argument or switch. Option argument names should be enclosed in angle brackets.
*
* https://www.sphinx-doc.org/en/master/usage/restructuredtext/domains.html#directive-option
*/
final class OptionDirective extends SubDirective
{
public const NAME = 'option';

/** @param Rule<CollectionNode> $startingRule */
public function __construct(
protected Rule $startingRule,
GenericLinkProvider $genericLinkProvider,
private readonly AnchorReducer $anchorReducer,
) {
parent::__construct($startingRule);

$genericLinkProvider->addGenericLink(self::NAME, OptionNode::LINK_TYPE);
}

public function getName(): string
{
return self::NAME;
}

/** {@inheritDoc}
*
* @param Directive $directive
*/
protected function processSub(
CollectionNode $collectionNode,
Directive $directive,
): Node|null {
$additionalIds = $this->getAdditionalIds($directive);

$id = $this->anchorReducer->reduceAnchor($directive->getData());

return new OptionNode($id, $directive->getData(), $additionalIds, $collectionNode->getChildren());
}

/** @return string[] */
private function getAdditionalIds(Directive $directive): array
{
$additionalIds = [];
if (str_contains($directive->getData(), ',')) {
$additionalIds = explode(',', $directive->getData());
$additionalIds = array_map('trim', $additionalIds);
$additionalIds = array_map(function ($item) {
// remove additional information in brackets like <module>
$pattern = '/<([^>]+)>/';
$item = preg_replace($pattern, '', $item);

// only keep allowed signs
return $this->anchorReducer->reduceAnchor($item ?? '');
}, $additionalIds);
}

return $additionalIds;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

declare(strict_types=1);

namespace phpDocumentor\Guides\RestructuredText\Nodes;

use phpDocumentor\Guides\Nodes\CompoundNode;
use phpDocumentor\Guides\Nodes\LinkTargetNode;
use phpDocumentor\Guides\Nodes\MultipleLinkTargetsNode;
use phpDocumentor\Guides\Nodes\Node;

/**
* Describes a command line argument or switch. Option argument names should be enclosed in angle brackets.
*
* https://www.sphinx-doc.org/en/master/usage/restructuredtext/domains.html#directive-option
*
* @extends CompoundNode<Node>
*/
class OptionNode extends CompoundNode implements LinkTargetNode, MultipleLinkTargetsNode
{
public const LINK_TYPE = 'std:option';

/**
* @param list<Node> $value
* @param string[] $additionalIds
*/
public function __construct(
private readonly string $id,
private readonly string $plainContent,
private readonly array $additionalIds,
array $value = [],
) {
parent::__construct($value);
}

public function getPlainContent(): string
{
return $this->plainContent;
}

public function getLinkType(): string
{
return self::LINK_TYPE;
}

public function getId(): string
{
return $this->id;
}

public function getLinkText(): string
{
return $this->plainContent;
}

/** @return string[] */
public function getAdditionalIds(): array
{
return $this->additionalIds;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ public function processNode(
$value = null;
}

return $this->createNode($referenceTarget, $value);
return $this->createNode($referenceTarget, $value, $role);
}

abstract protected function createNode(string $referenceTarget, string|null $referenceName): AbstractLinkInlineNode;
abstract protected function createNode(string $referenceTarget, string|null $referenceName, string $role): AbstractLinkInlineNode;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,18 @@

use phpDocumentor\Guides\Nodes\Inline\AbstractLinkInlineNode;
use phpDocumentor\Guides\Nodes\Inline\DocReferenceNode;
use Psr\Log\LoggerInterface;

use function preg_match;

class DocReferenceTextRole extends AbstractReferenceTextRole
{
public function __construct(
protected readonly LoggerInterface $logger,
) {
parent::__construct($this->logger);
}

final public const NAME = 'doc';

public function getName(): string
Expand All @@ -23,8 +32,17 @@ public function getAliases(): array
}

/** @return DocReferenceNode */
protected function createNode(string $referenceTarget, string|null $referenceName): AbstractLinkInlineNode
protected function createNode(string $referenceTarget, string|null $referenceName, string $role): AbstractLinkInlineNode
{
return new DocReferenceNode($referenceTarget, $referenceName ?? '');
$pattern = '/^([a-zA-Z0-9]+):(.*$)/';
if (preg_match($pattern, $referenceTarget, $matches)) {
$interlinkDomain = $matches[1];
$path = $matches[2];
} else {
$interlinkDomain = '';
$path = $referenceTarget;
}

return new DocReferenceNode($path, $referenceName ?? '', $interlinkDomain);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace phpDocumentor\Guides\RestructuredText\TextRoles;

use phpDocumentor\Guides\Nodes\SectionNode;

final class GenericLinkProvider
{
/** @var array<string, string> */
private array $textRoleLinkTypeMapping = [
'ref' => SectionNode::STD_LABEL,
];

public function addGenericLink(string $textRole, string $linkType): void
{
$this->textRoleLinkTypeMapping[$textRole] = $linkType;
}

/** @return string[] */
public function getTextRoleLinkTypeMapping(): array
{
return $this->textRoleLinkTypeMapping;
}

public function getLinkType(string $textRole): string
{
return $this->textRoleLinkTypeMapping[$textRole] ?? SectionNode::STD_LABEL;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

declare(strict_types=1);

namespace phpDocumentor\Guides\RestructuredText\TextRoles;

use phpDocumentor\Guides\Nodes\Inline\AbstractLinkInlineNode;
use phpDocumentor\Guides\Nodes\Inline\ReferenceNode;
use phpDocumentor\Guides\ReferenceResolvers\AnchorReducer;
use Psr\Log\LoggerInterface;

use function array_keys;
use function preg_match;

class GenericReferenceTextRole extends AbstractReferenceTextRole
{
public function __construct(
protected readonly LoggerInterface $logger,
private readonly GenericLinkProvider $genericLinkProvider,
private readonly AnchorReducer $anchorReducer,
) {
parent::__construct($this->logger);
}

public function getName(): string
{
return 'ref';
}

/** @inheritDoc */
public function getAliases(): array
{
return array_keys($this->genericLinkProvider->getTextRoleLinkTypeMapping());
}

/** @return ReferenceNode */
protected function createNode(string $referenceTarget, string|null $referenceName, string $role): AbstractLinkInlineNode
{
$linkType = $this->genericLinkProvider->getLinkType($role);
$pattern = '/^([a-zA-Z0-9]+):(.*$)/';
if (preg_match($pattern, $referenceTarget, $matches)) {
$interlinkDomain = $matches[1];
$id = $this->anchorReducer->reduceAnchor($matches[2]);
} else {
$interlinkDomain = '';
$id = $this->anchorReducer->reduceAnchor($referenceTarget);
}

return new ReferenceNode($id, $referenceName ?? '', $interlinkDomain, $linkType);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public function getAliases(): array
}

/** @return ReferenceNode */
protected function createNode(string $referenceTarget, string|null $referenceName): AbstractLinkInlineNode
protected function createNode(string $referenceTarget, string|null $referenceName, string $role): AbstractLinkInlineNode
{
return new ReferenceNode($referenceTarget, $referenceName ?? '');
}
Expand Down
Loading

0 comments on commit 4d6ebd2

Please sign in to comment.