refactor: Cleanup git state - commit all staged changes
Major refactoring cleanup: - Add new controller architecture (class-controller-*.php) - Add new settings-v2 UI (views/settings-v2/) - Add new CSS architecture (agentic-sidebar.css, tokens) - Add esbuild build pipeline (scripts/build.js, package.json) - Add composer dependencies (vendor/) - Add frontend src directory (assets/js/src/index.jsx) - Add documentation files - Remove old/obsolete files (class-settings.php, old CSS) This commits all pending changes from previous refactoring efforts.
This commit is contained in:
59
vendor/phpdocumentor/guides/src/Compiler/Compiler.php
vendored
Normal file
59
vendor/phpdocumentor/guides/src/Compiler/Compiler.php
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\NodeTransformers\NodeTransformerFactory;
|
||||
use phpDocumentor\Guides\Compiler\NodeTransformers\TransformerPass;
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
use SplPriorityQueue;
|
||||
|
||||
final class Compiler
|
||||
{
|
||||
/** @var SplPriorityQueue<int, CompilerPass> */
|
||||
private readonly SplPriorityQueue $passes;
|
||||
|
||||
/** @param iterable<CompilerPass> $passes */
|
||||
public function __construct(
|
||||
iterable $passes,
|
||||
NodeTransformerFactory $nodeTransformerFactory,
|
||||
) {
|
||||
$this->passes = new SplPriorityQueue();
|
||||
foreach ($passes as $pass) {
|
||||
$this->passes->insert($pass, $pass->getPriority());
|
||||
}
|
||||
|
||||
$transformerPriorities = $nodeTransformerFactory->getPriorities();
|
||||
foreach ($transformerPriorities as $transformerPriority) {
|
||||
$this->passes->insert(
|
||||
new TransformerPass(new DocumentNodeTraverser($nodeTransformerFactory, $transformerPriority), $transformerPriority),
|
||||
$transformerPriority,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DocumentNode[] $documents
|
||||
*
|
||||
* @return DocumentNode[]
|
||||
*/
|
||||
public function run(array $documents, CompilerContext $compilerContext): array
|
||||
{
|
||||
$clonedPasses = clone$this->passes;
|
||||
foreach ($clonedPasses as $pass) {
|
||||
$documents = $pass->run($documents, $compilerContext);
|
||||
}
|
||||
|
||||
return $documents;
|
||||
}
|
||||
}
|
||||
103
vendor/phpdocumentor/guides/src/Compiler/CompilerContext.php
vendored
Normal file
103
vendor/phpdocumentor/guides/src/Compiler/CompilerContext.php
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler;
|
||||
|
||||
use Doctrine\Deprecations\Deprecation;
|
||||
use Exception;
|
||||
use phpDocumentor\Guides\Compiler\ShadowTree\TreeNode;
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use phpDocumentor\Guides\Nodes\ProjectNode;
|
||||
|
||||
/**
|
||||
* Context class used in compiler passes to store the state of the nodes.
|
||||
*
|
||||
* The {@see Compiler} is making changes to the nodes in a {@see DocumentNode} as the nodes are immutable cannot
|
||||
* do this directly. This class helps to modify the nodes in the {@see DocumentNode} by creating a shadow tree.
|
||||
*
|
||||
* The class is final and should not be extended, if you need to provide more information to the compiler pass
|
||||
* you can use the {@see CompilerContextInterface} and decorate this class.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class CompilerContext implements CompilerContextInterface
|
||||
{
|
||||
/** @var TreeNode<Node> */
|
||||
private TreeNode $shadowTree;
|
||||
|
||||
public function __construct(
|
||||
private readonly ProjectNode $projectNode,
|
||||
) {
|
||||
if (self::class === static::class) {
|
||||
return;
|
||||
}
|
||||
|
||||
Deprecation::trigger(
|
||||
'phpdocumentor/guides',
|
||||
'https://github.com/phpDocumentor/guides/issues/971',
|
||||
'Extending CompilerContext is deprecated, please use the CompilerContextInterface instead.',
|
||||
);
|
||||
}
|
||||
|
||||
public function getProjectNode(): ProjectNode
|
||||
{
|
||||
return $this->projectNode;
|
||||
}
|
||||
|
||||
public function getDocumentNode(): DocumentNode
|
||||
{
|
||||
if (!isset($this->shadowTree)) {
|
||||
throw new Exception('DocumentNode must be set in compiler context');
|
||||
}
|
||||
|
||||
return $this->shadowTree->getRoot()->getNode();
|
||||
}
|
||||
|
||||
public function withDocumentShadowTree(DocumentNode $documentNode): static
|
||||
{
|
||||
$that = clone $this;
|
||||
$that->shadowTree = TreeNode::createFromDocument($documentNode);
|
||||
|
||||
return $that;
|
||||
}
|
||||
|
||||
/** @param TreeNode<Node> $shadowTree */
|
||||
public function withShadowTree(TreeNode $shadowTree): static
|
||||
{
|
||||
$that = clone $this;
|
||||
$that->shadowTree = $shadowTree;
|
||||
|
||||
return $that;
|
||||
}
|
||||
|
||||
/** @return TreeNode<Node> */
|
||||
public function getShadowTree(): TreeNode
|
||||
{
|
||||
if (!isset($this->shadowTree)) {
|
||||
throw new Exception('DocumentNode must be set in compiler context');
|
||||
}
|
||||
|
||||
return $this->shadowTree;
|
||||
}
|
||||
|
||||
/** @return array<string, string> */
|
||||
public function getLoggerInformation(): array
|
||||
{
|
||||
if (!isset($this->shadowTree)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [...$this->getDocumentNode()->getLoggerInformation()];
|
||||
}
|
||||
}
|
||||
37
vendor/phpdocumentor/guides/src/Compiler/CompilerContextInterface.php
vendored
Normal file
37
vendor/phpdocumentor/guides/src/Compiler/CompilerContextInterface.php
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\ShadowTree\TreeNode;
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use phpDocumentor\Guides\Nodes\ProjectNode;
|
||||
|
||||
interface CompilerContextInterface
|
||||
{
|
||||
public function getProjectNode(): ProjectNode;
|
||||
|
||||
public function getDocumentNode(): DocumentNode;
|
||||
|
||||
public function withDocumentShadowTree(DocumentNode $documentNode): self;
|
||||
|
||||
/** @param TreeNode<Node> $shadowTree */
|
||||
public function withShadowTree(TreeNode $shadowTree): self;
|
||||
|
||||
/** @return TreeNode<Node> */
|
||||
public function getShadowTree(): TreeNode;
|
||||
|
||||
/** @return array<string, string> */
|
||||
public function getLoggerInformation(): array;
|
||||
}
|
||||
28
vendor/phpdocumentor/guides/src/Compiler/CompilerPass.php
vendored
Normal file
28
vendor/phpdocumentor/guides/src/Compiler/CompilerPass.php
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler;
|
||||
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
|
||||
interface CompilerPass
|
||||
{
|
||||
/**
|
||||
* @param DocumentNode[] $documents
|
||||
*
|
||||
* @return DocumentNode[]
|
||||
*/
|
||||
public function run(array $documents, CompilerContext $compilerContext): array;
|
||||
|
||||
public function getPriority(): int;
|
||||
}
|
||||
82
vendor/phpdocumentor/guides/src/Compiler/DocumentNodeTraverser.php
vendored
Normal file
82
vendor/phpdocumentor/guides/src/Compiler/DocumentNodeTraverser.php
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\NodeTransformers\NodeTransformerFactory;
|
||||
use phpDocumentor\Guides\Compiler\ShadowTree\TreeNode;
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
|
||||
final class DocumentNodeTraverser
|
||||
{
|
||||
public function __construct(
|
||||
private readonly NodeTransformerFactory $nodeTransformerFactory,
|
||||
private readonly int $priority,
|
||||
) {
|
||||
}
|
||||
|
||||
public function traverse(DocumentNode $node, CompilerContext $compilerContext): Node|null
|
||||
{
|
||||
foreach ($this->nodeTransformerFactory->getTransformers() as $transformer) {
|
||||
if ($transformer->getPriority() !== $this->priority) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->traverseForTransformer($transformer, $compilerContext->getShadowTree(), $compilerContext);
|
||||
}
|
||||
|
||||
return $compilerContext->getShadowTree()->getNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param NodeTransformer<Node> $transformer
|
||||
* @param TreeNode<Node>|TreeNode<DocumentNode> $shadowNode
|
||||
*
|
||||
* return TNode|null
|
||||
*/
|
||||
private function traverseForTransformer(
|
||||
NodeTransformer $transformer,
|
||||
TreeNode $shadowNode,
|
||||
CompilerContext $compilerContext,
|
||||
): void {
|
||||
$node = $shadowNode->getNode();
|
||||
$supports = $transformer->supports($node);
|
||||
|
||||
if ($supports) {
|
||||
$transformed = $transformer->enterNode($node, $compilerContext);
|
||||
if ($transformed !== $node) {
|
||||
$shadowNode->getParent()?->replaceChild($node, $transformed);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($shadowNode->getChildren() as $shadowChild) {
|
||||
$this->traverseForTransformer($transformer, $shadowChild, $compilerContext->withShadowTree($shadowChild));
|
||||
}
|
||||
|
||||
if (!$supports) {
|
||||
return;
|
||||
}
|
||||
|
||||
$transformed = $transformer->leaveNode($node, $compilerContext);
|
||||
if ($transformed !== null) {
|
||||
if ($transformed !== $node) {
|
||||
$shadowNode->getParent()?->replaceChild($node, $transformed);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$shadowNode->getParent()?->removeChild($node);
|
||||
}
|
||||
}
|
||||
42
vendor/phpdocumentor/guides/src/Compiler/NodeTransformer.php
vendored
Normal file
42
vendor/phpdocumentor/guides/src/Compiler/NodeTransformer.php
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler;
|
||||
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
|
||||
/** @template T of Node */
|
||||
interface NodeTransformer
|
||||
{
|
||||
/**
|
||||
* @param T $node
|
||||
*
|
||||
* @return T
|
||||
*/
|
||||
public function enterNode(Node $node, CompilerContext $compilerContext): Node;
|
||||
|
||||
/**
|
||||
* @param T $node
|
||||
*
|
||||
* @return T|null
|
||||
*/
|
||||
public function leaveNode(Node $node, CompilerContext $compilerContext): Node|null;
|
||||
|
||||
/** @psalm-assert-if-true T $node */
|
||||
public function supports(Node $node): bool;
|
||||
|
||||
/**
|
||||
* The higher the priority the earlier the NodeTransformer is executed.
|
||||
*/
|
||||
public function getPriority(): int;
|
||||
}
|
||||
49
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/CitationInlineNodeTransformer.php
vendored
Normal file
49
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/CitationInlineNodeTransformer.php
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContextInterface;
|
||||
use phpDocumentor\Guides\Compiler\NodeTransformer;
|
||||
use phpDocumentor\Guides\Nodes\Inline\CitationInlineNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
|
||||
/** @implements NodeTransformer<Node> */
|
||||
final class CitationInlineNodeTransformer implements NodeTransformer
|
||||
{
|
||||
public function enterNode(Node $node, CompilerContextInterface $compilerContext): Node
|
||||
{
|
||||
if ($node instanceof CitationInlineNode) {
|
||||
$internalTarget = $compilerContext->getProjectNode()->getCitationTarget($node->getName());
|
||||
$node->setInternalTarget($internalTarget);
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function leaveNode(Node $node, CompilerContextInterface $compilerContext): Node|null
|
||||
{
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function supports(Node $node): bool
|
||||
{
|
||||
return $node instanceof CitationInlineNode;
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
// After CitationTargetTransformer
|
||||
return 2000;
|
||||
}
|
||||
}
|
||||
54
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/CitationTargetTransformer.php
vendored
Normal file
54
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/CitationTargetTransformer.php
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContextInterface;
|
||||
use phpDocumentor\Guides\Compiler\NodeTransformer;
|
||||
use phpDocumentor\Guides\Meta\CitationTarget;
|
||||
use phpDocumentor\Guides\Nodes\CitationNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
|
||||
/** @implements NodeTransformer<Node> */
|
||||
final class CitationTargetTransformer implements NodeTransformer
|
||||
{
|
||||
public function enterNode(Node $node, CompilerContextInterface $compilerContext): Node
|
||||
{
|
||||
if ($node instanceof CitationNode) {
|
||||
$compilerContext->getProjectNode()->addCitationTarget(
|
||||
new CitationTarget(
|
||||
$compilerContext->getDocumentNode()->getFilePath(),
|
||||
$node->getAnchor(),
|
||||
$node->getName(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function leaveNode(Node $node, CompilerContextInterface $compilerContext): Node|null
|
||||
{
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function supports(Node $node): bool
|
||||
{
|
||||
return $node instanceof CitationNode;
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
return 20_000;
|
||||
}
|
||||
}
|
||||
75
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/ClassNodeTransformer.php
vendored
Normal file
75
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/ClassNodeTransformer.php
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContextInterface;
|
||||
use phpDocumentor\Guides\Compiler\NodeTransformer;
|
||||
use phpDocumentor\Guides\Nodes\ClassNode;
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
|
||||
use function array_merge;
|
||||
|
||||
/**
|
||||
* @implements NodeTransformer<Node>
|
||||
*
|
||||
* The "class" directive sets the "classes" attribute value on its content or on the first immediately following
|
||||
* non-comment element. https://docutils.sourceforge.io/docs/ref/rst/directives.html#class
|
||||
*/
|
||||
final class ClassNodeTransformer implements NodeTransformer
|
||||
{
|
||||
/** @var string[] */
|
||||
private array $classes = [];
|
||||
|
||||
public function enterNode(Node $node, CompilerContextInterface $compilerContext): Node
|
||||
{
|
||||
if ($node instanceof DocumentNode) {
|
||||
// unset classes when entering the next document
|
||||
$this->classes = [];
|
||||
}
|
||||
|
||||
if ($node instanceof ClassNode) {
|
||||
$this->classes = $node->getClasses();
|
||||
}
|
||||
|
||||
if ($this->classes !== [] && !$node instanceof ClassNode) {
|
||||
$node->setClasses(array_merge($node->getClasses(), $this->classes));
|
||||
// Unset the classes after applied to the first direct successor
|
||||
$this->classes = [];
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function leaveNode(Node $node, CompilerContextInterface $compilerContext): Node|null
|
||||
{
|
||||
if ($node instanceof ClassNode) {
|
||||
//Remove the class node from the tree.
|
||||
return null;
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function supports(Node $node): bool
|
||||
{
|
||||
// Every node can have a class attached to it, however the node renderer decides on if to render the class
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
return 40_000;
|
||||
}
|
||||
}
|
||||
203
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/CollectLinkTargetsTransformer.php
vendored
Normal file
203
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/CollectLinkTargetsTransformer.php
vendored
Normal file
@@ -0,0 +1,203 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContextInterface;
|
||||
use phpDocumentor\Guides\Compiler\NodeTransformer;
|
||||
use phpDocumentor\Guides\Exception\DuplicateLinkAnchorException;
|
||||
use phpDocumentor\Guides\Meta\InternalTarget;
|
||||
use phpDocumentor\Guides\Nodes\AnchorNode;
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
use phpDocumentor\Guides\Nodes\LinkTargetNode;
|
||||
use phpDocumentor\Guides\Nodes\MultipleLinkTargetsNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use phpDocumentor\Guides\Nodes\OptionalLinkTargetsNode;
|
||||
use phpDocumentor\Guides\Nodes\PrefixedLinkTargetNode;
|
||||
use phpDocumentor\Guides\Nodes\SectionNode;
|
||||
use phpDocumentor\Guides\ReferenceResolvers\AnchorNormalizer;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use SplStack;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
/** @implements NodeTransformer<DocumentNode|AnchorNode|SectionNode> */
|
||||
final class CollectLinkTargetsTransformer implements NodeTransformer
|
||||
{
|
||||
/** @var SplStack<DocumentNode> */
|
||||
private readonly SplStack $documentStack;
|
||||
|
||||
public function __construct(
|
||||
private readonly AnchorNormalizer $anchorReducer,
|
||||
private LoggerInterface|null $logger = null,
|
||||
) {
|
||||
/*
|
||||
* TODO: remove stack here, as we should not have sub documents in this way, sub documents are
|
||||
* now produced by the {@see \phpDocumentor\Guides\RestructuredText\MarkupLanguageParser::getSubParser}
|
||||
* as this works right now in isolation includes do not work as they should.
|
||||
*/
|
||||
$this->documentStack = new SplStack();
|
||||
}
|
||||
|
||||
public function enterNode(Node $node, CompilerContextInterface $compilerContext): Node
|
||||
{
|
||||
if ($node instanceof DocumentNode) {
|
||||
$this->documentStack->push($node);
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
if ($node instanceof AnchorNode) {
|
||||
$currentDocument = $compilerContext->getDocumentNode();
|
||||
$parentSection = $compilerContext->getShadowTree()->getParent()?->getNode();
|
||||
$title = null;
|
||||
if ($parentSection instanceof SectionNode) {
|
||||
$title = $parentSection->getTitle()->toString();
|
||||
}
|
||||
|
||||
$anchorName = $this->anchorReducer->reduceAnchor($node->toString());
|
||||
try {
|
||||
$compilerContext->getProjectNode()->addLinkTarget(
|
||||
$anchorName,
|
||||
new InternalTarget(
|
||||
$currentDocument->getFilePath(),
|
||||
$node->toString(),
|
||||
$title,
|
||||
),
|
||||
);
|
||||
} catch (DuplicateLinkAnchorException $exception) {
|
||||
$this->logger?->warning($exception->getMessage(), $compilerContext->getLoggerInformation());
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
if ($node instanceof SectionNode) {
|
||||
$currentDocument = $this->documentStack->top();
|
||||
Assert::notNull($currentDocument);
|
||||
$anchorName = $node->getId();
|
||||
foreach ($node->getChildren() as $childNode) {
|
||||
if ($childNode instanceof AnchorNode) {
|
||||
$anchorName = $childNode->getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$compilerContext->getProjectNode()->addLinkTarget(
|
||||
$node->getId(),
|
||||
new InternalTarget(
|
||||
$currentDocument->getFilePath(),
|
||||
$anchorName,
|
||||
$node->getLinkText(),
|
||||
SectionNode::STD_TITLE,
|
||||
),
|
||||
);
|
||||
} catch (DuplicateLinkAnchorException $exception) {
|
||||
$this->logger?->warning($exception->getMessage(), $compilerContext->getLoggerInformation());
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
if ($node instanceof LinkTargetNode) {
|
||||
if ($node instanceof OptionalLinkTargetsNode && $node->isNoindex()) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
$currentDocument = $this->documentStack->top();
|
||||
Assert::notNull($currentDocument);
|
||||
$anchor = $this->anchorReducer->reduceAnchor($node->getId());
|
||||
$prefix = '';
|
||||
if ($node instanceof PrefixedLinkTargetNode) {
|
||||
$prefix = $node->getPrefix();
|
||||
}
|
||||
|
||||
$this->addLinkTargetToProject(
|
||||
$compilerContext,
|
||||
new InternalTarget(
|
||||
$currentDocument->getFilePath(),
|
||||
$anchor,
|
||||
$node->getLinkText(),
|
||||
$node->getLinkType(),
|
||||
$prefix,
|
||||
),
|
||||
);
|
||||
if ($node instanceof MultipleLinkTargetsNode) {
|
||||
foreach ($node->getAdditionalIds() as $id) {
|
||||
$anchor = $this->anchorReducer->reduceAnchor($id);
|
||||
$this->addLinkTargetToProject(
|
||||
$compilerContext,
|
||||
new InternalTarget(
|
||||
$currentDocument->getFilePath(),
|
||||
$anchor,
|
||||
$node->getLinkText(),
|
||||
$node->getLinkType(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function leaveNode(Node $node, CompilerContextInterface $compilerContext): Node|null
|
||||
{
|
||||
if ($node instanceof DocumentNode) {
|
||||
$this->documentStack->pop();
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function supports(Node $node): bool
|
||||
{
|
||||
return $node instanceof DocumentNode || $node instanceof AnchorNode || $node instanceof LinkTargetNode;
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
// After MetasPass
|
||||
return 5000;
|
||||
}
|
||||
|
||||
private function addLinkTargetToProject(CompilerContextInterface $compilerContext, InternalTarget $internalTarget): void
|
||||
{
|
||||
if ($compilerContext->getProjectNode()->hasInternalTarget($internalTarget->getAnchor(), $internalTarget->getLinkType())) {
|
||||
$otherLink = $compilerContext->getProjectNode()->getInternalTarget($internalTarget->getAnchor(), $internalTarget->getLinkType());
|
||||
$this->logger?->warning(
|
||||
sprintf(
|
||||
'Duplicate anchor "%s" for link type "%s" in document "%s". The anchor is already used at "%s"',
|
||||
$internalTarget->getAnchor(),
|
||||
$internalTarget->getLinkType(),
|
||||
$compilerContext->getDocumentNode()->getFilePath(),
|
||||
$otherLink?->getDocumentPath(),
|
||||
),
|
||||
$compilerContext->getLoggerInformation(),
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$compilerContext->getProjectNode()->addLinkTarget(
|
||||
$internalTarget->getAnchor(),
|
||||
$internalTarget,
|
||||
);
|
||||
} catch (DuplicateLinkAnchorException $exception) {
|
||||
$this->logger?->warning($exception->getMessage(), $compilerContext->getLoggerInformation());
|
||||
}
|
||||
}
|
||||
}
|
||||
49
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/CustomNodeTransformerFactory.php
vendored
Normal file
49
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/CustomNodeTransformerFactory.php
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\NodeTransformer;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
|
||||
use function array_map;
|
||||
use function array_unique;
|
||||
use function sort;
|
||||
|
||||
final class CustomNodeTransformerFactory implements NodeTransformerFactory
|
||||
{
|
||||
/** @param iterable<NodeTransformer<Node>> $transformers */
|
||||
public function __construct(private readonly iterable $transformers)
|
||||
{
|
||||
}
|
||||
|
||||
/** @return iterable<NodeTransformer<Node>> */
|
||||
public function getTransformers(): iterable
|
||||
{
|
||||
return $this->transformers;
|
||||
}
|
||||
|
||||
/** @return int[] */
|
||||
public function getPriorities(): array
|
||||
{
|
||||
$transformers = [...$this->transformers];
|
||||
$priorites = array_map(
|
||||
static fn (NodeTransformer $transformer): int => $transformer->getPriority(),
|
||||
$transformers,
|
||||
);
|
||||
sort($priorites);
|
||||
$priorites = array_unique($priorites);
|
||||
|
||||
return $priorites;
|
||||
}
|
||||
}
|
||||
68
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/DocumentBlockNodeTransformer.php
vendored
Normal file
68
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/DocumentBlockNodeTransformer.php
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContextInterface;
|
||||
use phpDocumentor\Guides\Compiler\NodeTransformer;
|
||||
use phpDocumentor\Guides\Nodes\DocumentBlockNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\TocNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
|
||||
/**
|
||||
* @implements NodeTransformer<Node>
|
||||
*
|
||||
* The "class" directive sets the "classes" attribute value on its content or on the first immediately following
|
||||
* non-comment element. https://docutils.sourceforge.io/docs/ref/rst/directives.html#class
|
||||
*/
|
||||
final class DocumentBlockNodeTransformer implements NodeTransformer
|
||||
{
|
||||
public function enterNode(Node $node, CompilerContextInterface $compilerContext): Node
|
||||
{
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function leaveNode(Node $node, CompilerContextInterface $compilerContext): Node|null
|
||||
{
|
||||
if ($node instanceof DocumentBlockNode) {
|
||||
$children = [];
|
||||
foreach ($node->getValue() as $child) {
|
||||
if ($child instanceof TocNode) {
|
||||
$child = $child->withOptions([...$child->getOptions(), 'menu' => $node->getIdentifier()]);
|
||||
}
|
||||
|
||||
$child = $child->withOptions([...$child->getOptions(), 'documentBlock' => $node->getIdentifier()]);
|
||||
|
||||
$children[] = $child;
|
||||
}
|
||||
|
||||
$compilerContext->getDocumentNode()->addDocumentPart($node->getIdentifier(), $children);
|
||||
|
||||
// Remove the node as it should not be rendered in the defined place but
|
||||
// wherever the theme defines
|
||||
return null;
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function supports(Node $node): bool
|
||||
{
|
||||
return $node instanceof DocumentBlockNode;
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
return 3000;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContextInterface;
|
||||
use phpDocumentor\Guides\Compiler\NodeTransformer;
|
||||
use phpDocumentor\Guides\Event\ModifyDocumentEntryAdditionalData;
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
use phpDocumentor\Guides\Nodes\DocumentTree\DocumentEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use phpDocumentor\Guides\Nodes\TitleNode;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
use function assert;
|
||||
use function is_string;
|
||||
|
||||
/** @implements NodeTransformer<Node> */
|
||||
final class DocumentEntryRegistrationTransformer implements NodeTransformer
|
||||
{
|
||||
public function __construct(
|
||||
private readonly LoggerInterface $logger,
|
||||
private readonly EventDispatcherInterface|null $eventDispatcher = null,
|
||||
) {
|
||||
}
|
||||
|
||||
public function enterNode(Node $node, CompilerContextInterface $compilerContext): Node
|
||||
{
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function leaveNode(Node $node, CompilerContextInterface $compilerContext): Node|null
|
||||
{
|
||||
if (!$node instanceof DocumentNode) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
if ($node->getTitle() === null && !$node->isOrphan()) {
|
||||
$this->logger->warning('Document has no title', $compilerContext->getLoggerInformation());
|
||||
}
|
||||
|
||||
$additionalData = [];
|
||||
if (is_string($node->getNavigationTitle())) {
|
||||
$additionalData['navigationTitle'] = TitleNode::fromString($node->getNavigationTitle());
|
||||
}
|
||||
|
||||
if ($this->eventDispatcher !== null) {
|
||||
$event = $this->eventDispatcher->dispatch(new ModifyDocumentEntryAdditionalData($additionalData, $node, $compilerContext));
|
||||
assert($event instanceof ModifyDocumentEntryAdditionalData);
|
||||
$additionalData = $event->getAdditionalData();
|
||||
}
|
||||
|
||||
$entry = new DocumentEntryNode(
|
||||
$node->getFilePath(),
|
||||
$node->getTitle() ?? TitleNode::emptyNode(),
|
||||
$node->isRoot(),
|
||||
$additionalData,
|
||||
$node->isOrphan(),
|
||||
);
|
||||
$compilerContext->getProjectNode()->addDocumentEntry($entry);
|
||||
|
||||
return $node->setDocumentEntry($entry);
|
||||
}
|
||||
|
||||
public function supports(Node $node): bool
|
||||
{
|
||||
return $node instanceof DocumentNode;
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
// Before TocNodeWithDocumentEntryTransformer and SectionEntryRegistrationTransformer
|
||||
return 5000;
|
||||
}
|
||||
}
|
||||
55
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/FootNodeNamedTransformer.php
vendored
Normal file
55
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/FootNodeNamedTransformer.php
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContextInterface;
|
||||
use phpDocumentor\Guides\Compiler\NodeTransformer;
|
||||
use phpDocumentor\Guides\Meta\FootnoteTarget;
|
||||
use phpDocumentor\Guides\Nodes\FootnoteNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
|
||||
/** @implements NodeTransformer<Node> */
|
||||
final class FootNodeNamedTransformer implements NodeTransformer
|
||||
{
|
||||
public function enterNode(Node $node, CompilerContextInterface $compilerContext): Node
|
||||
{
|
||||
if ($node instanceof FootnoteNode && $this->supports($node)) {
|
||||
$number = $compilerContext->getDocumentNode()->addFootnoteTarget(new FootnoteTarget(
|
||||
$compilerContext->getDocumentNode()->getFilePath(),
|
||||
$node->getAnchor(),
|
||||
$node->getName(),
|
||||
0,
|
||||
));
|
||||
$node->setNumber($number);
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function leaveNode(Node $node, CompilerContextInterface $compilerContext): Node|null
|
||||
{
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function supports(Node $node): bool
|
||||
{
|
||||
return $node instanceof FootnoteNode && $node->getNumber() <= 0;
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
// must be run *after* FootNodeNumberedTransformer
|
||||
return 20_000;
|
||||
}
|
||||
}
|
||||
54
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/FootNodeNumberedTransformer.php
vendored
Normal file
54
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/FootNodeNumberedTransformer.php
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContextInterface;
|
||||
use phpDocumentor\Guides\Compiler\NodeTransformer;
|
||||
use phpDocumentor\Guides\Meta\FootnoteTarget;
|
||||
use phpDocumentor\Guides\Nodes\FootnoteNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
|
||||
/** @implements NodeTransformer<Node> */
|
||||
final class FootNodeNumberedTransformer implements NodeTransformer
|
||||
{
|
||||
public function enterNode(Node $node, CompilerContextInterface $compilerContext): Node
|
||||
{
|
||||
if ($node instanceof FootnoteNode && $this->supports($node)) {
|
||||
$compilerContext->getDocumentNode()->addFootnoteTarget(new FootnoteTarget(
|
||||
$compilerContext->getDocumentNode()->getFilePath(),
|
||||
$node->getAnchor(),
|
||||
'',
|
||||
$node->getNumber(),
|
||||
));
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function leaveNode(Node $node, CompilerContextInterface $compilerContext): Node|null
|
||||
{
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function supports(Node $node): bool
|
||||
{
|
||||
return $node instanceof FootnoteNode && $node->getNumber() > 0;
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
// must be run *before* FootNodeNamedTransformer
|
||||
return 30_000;
|
||||
}
|
||||
}
|
||||
56
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/FootnoteInlineNodeTransformer.php
vendored
Normal file
56
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/FootnoteInlineNodeTransformer.php
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContextInterface;
|
||||
use phpDocumentor\Guides\Compiler\NodeTransformer;
|
||||
use phpDocumentor\Guides\Nodes\Inline\FootnoteInlineNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
|
||||
/** @implements NodeTransformer<Node> */
|
||||
final class FootnoteInlineNodeTransformer implements NodeTransformer
|
||||
{
|
||||
public function enterNode(Node $node, CompilerContextInterface $compilerContext): Node
|
||||
{
|
||||
if ($node instanceof FootnoteInlineNode) {
|
||||
if ($node->getNumber() > 0) {
|
||||
$internalTarget = $compilerContext->getDocumentNode()->getFootnoteTarget($node->getNumber());
|
||||
} elseif ($node->getName() !== '') {
|
||||
$internalTarget = $compilerContext->getDocumentNode()->getFootnoteTargetByName($node->getName());
|
||||
} else {
|
||||
$internalTarget = $compilerContext->getDocumentNode()->getFootnoteTargetAnonymous();
|
||||
}
|
||||
|
||||
$node->setInternalTarget($internalTarget);
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function leaveNode(Node $node, CompilerContextInterface $compilerContext): Node|null
|
||||
{
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function supports(Node $node): bool
|
||||
{
|
||||
return $node instanceof FootnoteInlineNode;
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
// After FooternoteTargetTransformer
|
||||
return 2000;
|
||||
}
|
||||
}
|
||||
62
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/ListNodeTransformer.php
vendored
Normal file
62
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/ListNodeTransformer.php
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContextInterface;
|
||||
use phpDocumentor\Guides\Compiler\NodeTransformer;
|
||||
use phpDocumentor\Guides\Nodes\ListItemNode;
|
||||
use phpDocumentor\Guides\Nodes\ListNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
use function assert;
|
||||
|
||||
/** @implements NodeTransformer<ListNode> */
|
||||
final class ListNodeTransformer implements NodeTransformer
|
||||
{
|
||||
public function __construct(
|
||||
private readonly LoggerInterface $logger,
|
||||
) {
|
||||
}
|
||||
|
||||
public function enterNode(Node $node, CompilerContextInterface $compilerContext): Node
|
||||
{
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function leaveNode(Node $node, CompilerContextInterface $compilerContext): Node|null
|
||||
{
|
||||
assert($node instanceof ListNode);
|
||||
foreach ($node->getChildren() as $listItemNode) {
|
||||
assert($listItemNode instanceof ListItemNode);
|
||||
if (!empty($listItemNode->getChildren())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->logger->warning('List item without content', $compilerContext->getLoggerInformation());
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function supports(Node $node): bool
|
||||
{
|
||||
return $node instanceof ListNode;
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
return 1000;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers\MenuNodeTransformers;
|
||||
|
||||
use Exception;
|
||||
use phpDocumentor\Guides\Compiler\CompilerContextInterface;
|
||||
use phpDocumentor\Guides\Compiler\NodeTransformer;
|
||||
use phpDocumentor\Guides\Nodes\Menu\MenuEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\MenuNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
use function assert;
|
||||
use function count;
|
||||
|
||||
/** @implements NodeTransformer<MenuEntryNode> */
|
||||
abstract class AbstractMenuEntryNodeTransformer implements NodeTransformer
|
||||
{
|
||||
public function __construct(
|
||||
protected readonly LoggerInterface $logger,
|
||||
) {
|
||||
}
|
||||
|
||||
final public function enterNode(Node $node, CompilerContextInterface $compilerContext): MenuEntryNode
|
||||
{
|
||||
return $node;
|
||||
}
|
||||
|
||||
/** @param MenuEntryNode $node */
|
||||
final public function leaveNode(Node $node, CompilerContextInterface $compilerContext): MenuEntryNode|null
|
||||
{
|
||||
assert($node instanceof MenuEntryNode);
|
||||
$currentMenuShaddow = $compilerContext->getShadowTree()->getParent();
|
||||
while ($currentMenuShaddow !== null && !$currentMenuShaddow->getNode() instanceof MenuNode) {
|
||||
$currentMenuShaddow = $currentMenuShaddow->getParent();
|
||||
}
|
||||
|
||||
$currentMenu = $currentMenuShaddow?->getNode();
|
||||
|
||||
if (!$currentMenu instanceof MenuNode) {
|
||||
throw new Exception('A MenuEntryNode must be attached to a MenuNode');
|
||||
}
|
||||
|
||||
$menuEntries = $this->handleMenuEntry($currentMenu, $node, $compilerContext);
|
||||
|
||||
if (count($menuEntries) === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (count($menuEntries) === 1) {
|
||||
return $menuEntries[0];
|
||||
}
|
||||
|
||||
foreach ($menuEntries as $menuEntry) {
|
||||
$compilerContext->getShadowTree()->getParent()?->addChild($menuEntry);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @return list<MenuEntryNode> */
|
||||
abstract protected function handleMenuEntry(MenuNode $currentMenu, MenuEntryNode $entryNode, CompilerContextInterface $compilerContext): array;
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers\MenuNodeTransformers;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContextInterface;
|
||||
use phpDocumentor\Guides\Nodes\DocumentTree\SectionEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\ContentMenuNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\MenuEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\MenuNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\SectionMenuEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use phpDocumentor\Guides\Nodes\SectionNode;
|
||||
|
||||
use function assert;
|
||||
|
||||
use const PHP_INT_MAX;
|
||||
|
||||
final class ContentsMenuEntryNodeTransformer extends AbstractMenuEntryNodeTransformer
|
||||
{
|
||||
use SubSectionHierarchyHandler;
|
||||
|
||||
private const DEFAULT_MAX_LEVELS = PHP_INT_MAX;
|
||||
|
||||
public function supports(Node $node): bool
|
||||
{
|
||||
return $node instanceof SectionMenuEntryNode;
|
||||
}
|
||||
|
||||
/** @return list<MenuEntryNode> */
|
||||
protected function handleMenuEntry(MenuNode $currentMenu, MenuEntryNode $entryNode, CompilerContextInterface $compilerContext): array
|
||||
{
|
||||
if (!$currentMenu instanceof ContentMenuNode) {
|
||||
return [$entryNode];
|
||||
}
|
||||
|
||||
assert($entryNode instanceof SectionMenuEntryNode);
|
||||
$depth = (int) $currentMenu->getOption('depth', self::DEFAULT_MAX_LEVELS - 1) + 1;
|
||||
$documentEntry = $compilerContext->getDocumentNode()->getDocumentEntry();
|
||||
if ($currentMenu->isLocal()) {
|
||||
$sectionNode = $compilerContext->getShadowTree()->getParent()?->getParent()?->getNode();
|
||||
if (!$sectionNode instanceof SectionNode) {
|
||||
$this->logger->error('Section of contents directive not found. ', $compilerContext->getLoggerInformation());
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
$sectionEntry = $documentEntry->findSectionEntry($sectionNode);
|
||||
if (!$sectionEntry instanceof SectionEntryNode) {
|
||||
$this->logger->error('Section of contents directive not found. ', $compilerContext->getLoggerInformation());
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
$newEntryNode = new SectionMenuEntryNode(
|
||||
$documentEntry->getFile(),
|
||||
$entryNode->getValue() ?? $sectionEntry->getTitle(),
|
||||
1,
|
||||
$sectionEntry->getId(),
|
||||
);
|
||||
$this->addSubSections($newEntryNode, $sectionEntry, $documentEntry, 1, $depth);
|
||||
} else {
|
||||
$newEntryNode = new SectionMenuEntryNode(
|
||||
$documentEntry->getFile(),
|
||||
$entryNode->getValue() ?? $documentEntry->getTitle(),
|
||||
1,
|
||||
);
|
||||
$this->addSubSectionsToMenuEntries($documentEntry, $newEntryNode, $depth);
|
||||
}
|
||||
|
||||
return $newEntryNode->getSections();
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
// After DocumentEntryTransformer
|
||||
return 4500;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers\MenuNodeTransformers;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContextInterface;
|
||||
use phpDocumentor\Guides\Nodes\DocumentTree\ExternalEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\ExternalMenuEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\MenuEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\MenuNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\TocNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use phpDocumentor\Guides\Nodes\TitleNode;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
use function assert;
|
||||
|
||||
final class ExternalMenuEntryNodeTransformer extends AbstractMenuEntryNodeTransformer
|
||||
{
|
||||
use MenuEntryManagement;
|
||||
use SubSectionHierarchyHandler;
|
||||
|
||||
public function __construct(
|
||||
LoggerInterface $logger,
|
||||
) {
|
||||
parent::__construct($logger);
|
||||
}
|
||||
|
||||
public function supports(Node $node): bool
|
||||
{
|
||||
return $node instanceof ExternalMenuEntryNode;
|
||||
}
|
||||
|
||||
/** @return list<MenuEntryNode> */
|
||||
protected function handleMenuEntry(MenuNode $currentMenu, MenuEntryNode $entryNode, CompilerContextInterface $compilerContext): array
|
||||
{
|
||||
assert($entryNode instanceof ExternalMenuEntryNode);
|
||||
|
||||
$newEntryNode = new ExternalEntryNode(
|
||||
$entryNode->getUrl(),
|
||||
($entryNode->getValue() ?? TitleNode::emptyNode())->toString(),
|
||||
);
|
||||
|
||||
if ($currentMenu instanceof TocNode) {
|
||||
$this->attachDocumentEntriesToParents([$newEntryNode], $compilerContext, '');
|
||||
}
|
||||
|
||||
return [$entryNode];
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
// After DocumentEntryTransformer
|
||||
return 4500;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers\MenuNodeTransformers;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContextInterface;
|
||||
use phpDocumentor\Guides\Nodes\Menu\GlobMenuEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\InternalMenuEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\MenuEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\MenuNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\TocNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use phpDocumentor\Guides\Nodes\TitleNode;
|
||||
|
||||
use function array_pop;
|
||||
use function assert;
|
||||
use function explode;
|
||||
use function implode;
|
||||
use function in_array;
|
||||
use function is_string;
|
||||
use function preg_match;
|
||||
use function preg_replace;
|
||||
|
||||
final class GlobMenuEntryNodeTransformer extends AbstractMenuEntryNodeTransformer
|
||||
{
|
||||
use MenuEntryManagement;
|
||||
use SubSectionHierarchyHandler;
|
||||
|
||||
// Setting a default level prevents PHP errors in case of circular references
|
||||
private const DEFAULT_MAX_LEVELS = 10;
|
||||
|
||||
/** @return list<MenuEntryNode> */
|
||||
protected function handleMenuEntry(MenuNode $currentMenu, MenuEntryNode $entryNode, CompilerContextInterface $compilerContext): array
|
||||
{
|
||||
assert($entryNode instanceof GlobMenuEntryNode);
|
||||
$maxDepth = (int) $currentMenu->getOption('maxdepth', self::DEFAULT_MAX_LEVELS);
|
||||
$documentEntries = $compilerContext->getProjectNode()->getAllDocumentEntries();
|
||||
$currentPath = $compilerContext->getDocumentNode()->getFilePath();
|
||||
$globExclude = explode(',', $currentMenu->getOption('globExclude') . '');
|
||||
$menuEntries = [];
|
||||
foreach ($documentEntries as $documentEntry) {
|
||||
if ($documentEntry->isOrphan()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
!self::matches($documentEntry->getFile(), $entryNode, $currentPath, $globExclude)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($currentMenu instanceof TocNode && self::isCurrent($documentEntry, $currentPath)) {
|
||||
// TocNodes do not select the current page in glob mode. In a menu we might want to display it
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($currentMenu->getChildren() as $currentMenuEntry) {
|
||||
if ($currentMenuEntry instanceof InternalMenuEntryNode && $currentMenuEntry->getUrl() === $documentEntry->getFile()) {
|
||||
// avoid duplicates
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
|
||||
$titleNode = $documentEntry->getTitle();
|
||||
$navigationTitle = $documentEntry->getAdditionalData('navigationTitle');
|
||||
if ($navigationTitle instanceof TitleNode) {
|
||||
$titleNode = $navigationTitle;
|
||||
}
|
||||
|
||||
$documentEntriesInTree[] = $documentEntry;
|
||||
$newEntryNode = new InternalMenuEntryNode(
|
||||
$documentEntry->getFile(),
|
||||
$titleNode,
|
||||
[],
|
||||
false,
|
||||
1,
|
||||
'',
|
||||
self::isInRootline($documentEntry, $compilerContext->getDocumentNode()->getDocumentEntry()),
|
||||
self::isCurrent($documentEntry, $currentPath),
|
||||
);
|
||||
if (!$currentMenu->hasOption('titlesonly') && $maxDepth > 1) {
|
||||
$this->addSubSectionsToMenuEntries($documentEntry, $newEntryNode, $maxDepth - 1);
|
||||
}
|
||||
|
||||
if ($currentMenu instanceof TocNode) {
|
||||
$this->attachDocumentEntriesToParents($documentEntriesInTree, $compilerContext, $currentPath);
|
||||
}
|
||||
|
||||
$menuEntries[] = $newEntryNode;
|
||||
}
|
||||
|
||||
return $menuEntries;
|
||||
}
|
||||
|
||||
public function supports(Node $node): bool
|
||||
{
|
||||
return $node instanceof GlobMenuEntryNode;
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
// After GlobMenuEntryNodeTransformer
|
||||
// Before SubInternalMenuEntry
|
||||
return 4000;
|
||||
}
|
||||
|
||||
/** @param String[] $globExclude */
|
||||
private static function matches(string $actualFile, GlobMenuEntryNode $parsedMenuEntryNode, string $currentFile, array $globExclude): bool
|
||||
{
|
||||
$expectedFile = $parsedMenuEntryNode->getUrl();
|
||||
if (self::isAbsoluteFile($expectedFile)) {
|
||||
if ($expectedFile === '/' . $actualFile) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return self::isGlob($actualFile, $currentFile, $expectedFile, '/', $globExclude);
|
||||
}
|
||||
|
||||
$current = explode('/', $currentFile);
|
||||
array_pop($current);
|
||||
$current[] = $expectedFile;
|
||||
$absoluteExpectedFile = implode('/', $current);
|
||||
|
||||
if ($absoluteExpectedFile === $actualFile) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return self::isGlob($actualFile, $currentFile, $absoluteExpectedFile, '', $globExclude);
|
||||
}
|
||||
|
||||
/** @param String[] $globExclude */
|
||||
private static function isGlob(string $documentEntryFile, string $currentPath, string $file, string $prefix, array $globExclude): bool
|
||||
{
|
||||
if (!in_array($documentEntryFile, $globExclude, true)) {
|
||||
$file = preg_replace('/(?<!\*)\*(?!\*)/', '[^\/]*', $file);
|
||||
assert(is_string($file));
|
||||
$file = preg_replace('/\*{2}/', '.*', $file);
|
||||
$pattern = '`^' . $file . '$`';
|
||||
|
||||
return preg_match($pattern, $prefix . $documentEntryFile) > 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers\MenuNodeTransformers;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContextInterface;
|
||||
use phpDocumentor\Guides\Nodes\Menu\InternalMenuEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\MenuEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\MenuNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\TocNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use phpDocumentor\Guides\Nodes\TitleNode;
|
||||
use phpDocumentor\Guides\ReferenceResolvers\DocumentNameResolverInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
use function array_pop;
|
||||
use function assert;
|
||||
use function explode;
|
||||
use function implode;
|
||||
use function sprintf;
|
||||
|
||||
final class InternalMenuEntryNodeTransformer extends AbstractMenuEntryNodeTransformer
|
||||
{
|
||||
use MenuEntryManagement;
|
||||
use SubSectionHierarchyHandler;
|
||||
|
||||
// Setting a default level prevents PHP errors in case of circular references
|
||||
private const DEFAULT_MAX_LEVELS = 10;
|
||||
|
||||
public function __construct(
|
||||
LoggerInterface $logger,
|
||||
private readonly DocumentNameResolverInterface $documentNameResolver,
|
||||
) {
|
||||
parent::__construct($logger);
|
||||
}
|
||||
|
||||
public function supports(Node $node): bool
|
||||
{
|
||||
return $node instanceof InternalMenuEntryNode;
|
||||
}
|
||||
|
||||
/** @return list<MenuEntryNode> */
|
||||
protected function handleMenuEntry(MenuNode $currentMenu, MenuEntryNode $entryNode, CompilerContextInterface $compilerContext): array
|
||||
{
|
||||
assert($entryNode instanceof InternalMenuEntryNode);
|
||||
$documentEntries = $compilerContext->getProjectNode()->getAllDocumentEntries();
|
||||
$currentPath = $compilerContext->getDocumentNode()->getFilePath();
|
||||
$maxDepth = (int) $currentMenu->getOption('maxdepth', self::DEFAULT_MAX_LEVELS);
|
||||
|
||||
foreach ($documentEntries as $documentEntry) {
|
||||
if (
|
||||
!self::matches($documentEntry->getFile(), $entryNode, $currentPath)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$titleNode = $documentEntry->getTitle();
|
||||
$navigationTitle = $documentEntry->getAdditionalData('navigationTitle');
|
||||
if ($navigationTitle instanceof TitleNode) {
|
||||
$titleNode = $navigationTitle;
|
||||
}
|
||||
|
||||
if ($entryNode->getValue() instanceof TitleNode) {
|
||||
$titleNode = $entryNode->getValue();
|
||||
}
|
||||
|
||||
$documentEntriesInTree[] = $documentEntry;
|
||||
$newEntryNode = new InternalMenuEntryNode(
|
||||
$documentEntry->getFile(),
|
||||
$titleNode,
|
||||
[],
|
||||
false,
|
||||
1,
|
||||
'',
|
||||
self::isInRootline($documentEntry, $compilerContext->getDocumentNode()->getDocumentEntry()),
|
||||
self::isCurrent($documentEntry, $currentPath),
|
||||
);
|
||||
if (!$currentMenu->hasOption('titlesonly') && $maxDepth > 1) {
|
||||
$this->addSubSectionsToMenuEntries($documentEntry, $newEntryNode, $maxDepth);
|
||||
}
|
||||
|
||||
if ($currentMenu instanceof TocNode) {
|
||||
$this->attachDocumentEntriesToParents($documentEntriesInTree, $compilerContext, $currentPath);
|
||||
}
|
||||
|
||||
return [$newEntryNode];
|
||||
}
|
||||
|
||||
$this->logger->warning(sprintf('Menu entry "%s" was not found in the document tree. Ignoring it. ', $entryNode->getUrl()), $compilerContext->getLoggerInformation());
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
private function matches(string $actualFile, InternalMenuEntryNode $parsedMenuEntryNode, string $currentFile): bool
|
||||
{
|
||||
$expectedFile = $parsedMenuEntryNode->getUrl();
|
||||
if (self::isAbsoluteFile($expectedFile)) {
|
||||
return $expectedFile === '/' . $actualFile;
|
||||
}
|
||||
|
||||
$current = explode('/', $currentFile);
|
||||
array_pop($current);
|
||||
|
||||
|
||||
$absoluteExpectedFile = $this->documentNameResolver->canonicalUrl(implode('/', $current), $expectedFile);
|
||||
|
||||
return $absoluteExpectedFile === $actualFile;
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
// After DocumentEntryTransformer
|
||||
return 4500;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers\MenuNodeTransformers;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContextInterface;
|
||||
use phpDocumentor\Guides\Nodes\DocumentTree\DocumentEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\DocumentTree\ExternalEntryNode;
|
||||
|
||||
use function sprintf;
|
||||
use function str_starts_with;
|
||||
|
||||
trait MenuEntryManagement
|
||||
{
|
||||
/** @param array<DocumentEntryNode|ExternalEntryNode> $entryNodes */
|
||||
private function attachDocumentEntriesToParents(
|
||||
array $entryNodes,
|
||||
CompilerContextInterface $compilerContext,
|
||||
string $currentPath,
|
||||
): void {
|
||||
foreach ($entryNodes as $entryNode) {
|
||||
if ($entryNode instanceof DocumentEntryNode) {
|
||||
if (($entryNode->isRoot() || $currentPath === $entryNode->getFile())) {
|
||||
// The root page may not be attached to any other
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($entryNode->getParent() !== null && $entryNode->getParent() !== $compilerContext->getDocumentNode()->getDocumentEntry()) {
|
||||
$this->logger->warning(sprintf(
|
||||
'Document %s has been added to parents %s and %s. The `toctree` directive changes the '
|
||||
. 'position of documents in the document tree. Use the `menu` directive to only display a menu without changing the document tree.',
|
||||
$entryNode->getFile(),
|
||||
$entryNode->getParent()->getFile(),
|
||||
$compilerContext->getDocumentNode()->getDocumentEntry()->getFile(),
|
||||
), $compilerContext->getLoggerInformation());
|
||||
}
|
||||
|
||||
if ($entryNode->getParent() !== null) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$entryNode->setParent($compilerContext->getDocumentNode()->getDocumentEntry());
|
||||
$compilerContext->getDocumentNode()->getDocumentEntry()->addChild($entryNode);
|
||||
}
|
||||
}
|
||||
|
||||
private static function isInRootline(DocumentEntryNode $menuEntry, DocumentEntryNode $currentDoc): bool
|
||||
{
|
||||
return $menuEntry->getFile() === $currentDoc->getFile()
|
||||
|| ($currentDoc->getParent() !== null
|
||||
&& self::isInRootline($menuEntry, $currentDoc->getParent()));
|
||||
}
|
||||
|
||||
private static function isCurrent(DocumentEntryNode $menuEntry, string $currentPath): bool
|
||||
{
|
||||
return $menuEntry->getFile() === $currentPath;
|
||||
}
|
||||
|
||||
private static function isAbsoluteFile(string $expectedFile): bool
|
||||
{
|
||||
return str_starts_with($expectedFile, '/');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers\MenuNodeTransformers;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContextInterface;
|
||||
use phpDocumentor\Guides\Exception\DocumentEntryNotFound;
|
||||
use phpDocumentor\Guides\Nodes\DocumentTree\DocumentEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\DocumentTree\ExternalEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\ExternalMenuEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\InternalMenuEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\MenuEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\MenuNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use phpDocumentor\Guides\Nodes\TitleNode;
|
||||
|
||||
use function assert;
|
||||
use function sprintf;
|
||||
|
||||
final class SubInternalMenuEntryNodeTransformer extends AbstractMenuEntryNodeTransformer
|
||||
{
|
||||
use MenuEntryManagement;
|
||||
use SubSectionHierarchyHandler;
|
||||
|
||||
// Setting a default level prevents PHP errors in case of circular references
|
||||
private const DEFAULT_MAX_LEVELS = 10;
|
||||
|
||||
public function supports(Node $node): bool
|
||||
{
|
||||
return $node instanceof InternalMenuEntryNode;
|
||||
}
|
||||
|
||||
/** @return list<MenuEntryNode> */
|
||||
protected function handleMenuEntry(MenuNode $currentMenu, MenuEntryNode $entryNode, CompilerContextInterface $compilerContext): array
|
||||
{
|
||||
assert($entryNode instanceof InternalMenuEntryNode);
|
||||
$maxDepth = (int) $currentMenu->getOption('maxdepth', self::DEFAULT_MAX_LEVELS);
|
||||
try {
|
||||
$documentEntryOfMenuEntry = $compilerContext->getProjectNode()->getDocumentEntry($entryNode->getUrl());
|
||||
} catch (DocumentEntryNotFound) {
|
||||
$this->logger->warning(sprintf('Menu entry "%s" was not found in the document tree. Ignoring it. ', $entryNode->getUrl()), $compilerContext->getLoggerInformation());
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
$this->addSubEntries($currentMenu, $compilerContext, $entryNode, $documentEntryOfMenuEntry, $entryNode->getLevel() + 1, $maxDepth);
|
||||
|
||||
return [$entryNode];
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
// After MenuEntries are resolved
|
||||
return 3000;
|
||||
}
|
||||
|
||||
private function addSubEntries(
|
||||
MenuNode $currentMenu,
|
||||
CompilerContextInterface $compilerContext,
|
||||
InternalMenuEntryNode $sectionMenuEntry,
|
||||
DocumentEntryNode $documentEntry,
|
||||
int $currentLevel,
|
||||
int $maxDepth,
|
||||
): void {
|
||||
if ($maxDepth < $currentLevel) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($documentEntry->getMenuEntries() as $subEntryNode) {
|
||||
if ($subEntryNode instanceof DocumentEntryNode) {
|
||||
$titleNode = $subEntryNode->getTitle();
|
||||
$navigationTitle = $subEntryNode->getAdditionalData('navigationTitle');
|
||||
if ($navigationTitle instanceof TitleNode) {
|
||||
$titleNode = $navigationTitle;
|
||||
}
|
||||
|
||||
$subMenuEntry = new InternalMenuEntryNode(
|
||||
$subEntryNode->getFile(),
|
||||
$titleNode,
|
||||
[],
|
||||
false,
|
||||
$currentLevel,
|
||||
'',
|
||||
self::isInRootline($subEntryNode, $compilerContext->getDocumentNode()->getDocumentEntry()),
|
||||
self::isCurrent($subEntryNode, $compilerContext->getDocumentNode()->getFilePath()),
|
||||
);
|
||||
|
||||
if (!$currentMenu->hasOption('titlesonly') && $maxDepth - $currentLevel + 1 > 1) {
|
||||
$this->addSubSectionsToMenuEntries($subEntryNode, $subMenuEntry, $maxDepth - $currentLevel + 2);
|
||||
}
|
||||
|
||||
$sectionMenuEntry->addMenuEntry($subMenuEntry);
|
||||
$this->addSubEntries($currentMenu, $compilerContext, $subMenuEntry, $subEntryNode, $currentLevel + 1, $maxDepth);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!($subEntryNode instanceof ExternalEntryNode)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$subMenuEntry = new ExternalMenuEntryNode(
|
||||
$subEntryNode->getValue(),
|
||||
TitleNode::fromString($subEntryNode->getTitle()),
|
||||
$currentLevel,
|
||||
);
|
||||
$sectionMenuEntry->addMenuEntry($subMenuEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers\MenuNodeTransformers;
|
||||
|
||||
use phpDocumentor\Guides\Nodes\DocumentTree\DocumentEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\DocumentTree\SectionEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\InternalMenuEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\SectionMenuEntryNode;
|
||||
|
||||
use function assert;
|
||||
|
||||
trait SubSectionHierarchyHandler
|
||||
{
|
||||
private function addSubSectionsToMenuEntries(DocumentEntryNode $documentEntry, InternalMenuEntryNode|SectionMenuEntryNode $menuEntry, int $maxLevel): void
|
||||
{
|
||||
foreach ($documentEntry->getSections() as $section) {
|
||||
// We do not add the main section as it repeats the document title
|
||||
foreach ($section->getChildren() as $subSectionEntryNode) {
|
||||
assert($subSectionEntryNode instanceof SectionEntryNode);
|
||||
$currentLevel = $menuEntry->getLevel() + 1;
|
||||
$sectionMenuEntry = new SectionMenuEntryNode(
|
||||
$documentEntry->getFile(),
|
||||
$subSectionEntryNode->getTitle(),
|
||||
$currentLevel,
|
||||
$subSectionEntryNode->getId(),
|
||||
);
|
||||
$menuEntry->addSection($sectionMenuEntry);
|
||||
$this->addSubSections($sectionMenuEntry, $subSectionEntryNode, $documentEntry, $currentLevel, $maxLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function addSubSections(
|
||||
SectionMenuEntryNode $sectionMenuEntry,
|
||||
SectionEntryNode $sectionEntryNode,
|
||||
DocumentEntryNode $documentEntry,
|
||||
int $currentLevel,
|
||||
int $maxLevel,
|
||||
): void {
|
||||
if ($currentLevel >= $maxLevel) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($sectionEntryNode->getChildren() as $subSectionEntryNode) {
|
||||
$subSectionMenuEntry = new SectionMenuEntryNode(
|
||||
$documentEntry->getFile(),
|
||||
$subSectionEntryNode->getTitle(),
|
||||
$currentLevel,
|
||||
$subSectionEntryNode->getId(),
|
||||
);
|
||||
$sectionMenuEntry->addSection($subSectionMenuEntry);
|
||||
$this->addSubSections(
|
||||
$subSectionMenuEntry,
|
||||
$subSectionEntryNode,
|
||||
$documentEntry,
|
||||
$currentLevel + 1,
|
||||
$maxLevel,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers\MenuNodeTransformers;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContextInterface;
|
||||
use phpDocumentor\Guides\Compiler\NodeTransformer;
|
||||
use phpDocumentor\Guides\Nodes\Menu\MenuNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\NavMenuNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\TocNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use phpDocumentor\Guides\Settings\SettingsManager;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/** @implements NodeTransformer<MenuNode> */
|
||||
final class TocNodeReplacementTransformer implements NodeTransformer
|
||||
{
|
||||
public function __construct(
|
||||
private readonly LoggerInterface $logger,
|
||||
private readonly SettingsManager $settingsManager,
|
||||
) {
|
||||
}
|
||||
|
||||
public function enterNode(Node $node, CompilerContextInterface $compilerContext): Node
|
||||
{
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function leaveNode(Node $node, CompilerContextInterface $compilerContext): Node|null
|
||||
{
|
||||
if (!$node instanceof TocNode) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
if (!$this->settingsManager->getProjectSettings()->isAutomaticMenu()) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
if ($node->hasOption('hidden')) {
|
||||
$this->logger->warning('The `.. toctree::` directive with option `:hidden:` is not supported in automatic-menu mode. ', $compilerContext->getLoggerInformation());
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->logger->warning('The `.. toctree::` directive is not supported in automatic-menu mode. Use `.. menu::` instead. ', $compilerContext->getLoggerInformation());
|
||||
$menuNode = new NavMenuNode($node->getMenuEntries());
|
||||
$menuNode = $menuNode->withOptions($node->getOptions());
|
||||
$menuNode = $menuNode->withCaption($node->getCaption());
|
||||
|
||||
return $menuNode;
|
||||
}
|
||||
|
||||
public function supports(Node $node): bool
|
||||
{
|
||||
return $node instanceof TocNode;
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
return 20_000;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers\MenuNodeTransformers;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContextInterface;
|
||||
use phpDocumentor\Guides\Compiler\NodeTransformer;
|
||||
use phpDocumentor\Guides\Nodes\Menu\TocNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
|
||||
use function assert;
|
||||
|
||||
/** @implements NodeTransformer<TocNode> */
|
||||
final class TocNodeTransformer implements NodeTransformer
|
||||
{
|
||||
public function enterNode(Node $node, CompilerContextInterface $compilerContext): Node
|
||||
{
|
||||
assert($node instanceof TocNode);
|
||||
$compilerContext->getDocumentNode()->addTocNode($node);
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function leaveNode(Node $node, CompilerContextInterface $compilerContext): Node|null
|
||||
{
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function supports(Node $node): bool
|
||||
{
|
||||
return $node instanceof TocNode;
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
return 1000;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers\MenuNodeTransformers;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContext;
|
||||
use phpDocumentor\Guides\Compiler\NodeTransformer;
|
||||
use phpDocumentor\Guides\Nodes\Menu\TocNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
|
||||
use function array_reverse;
|
||||
use function is_array;
|
||||
|
||||
/** @implements NodeTransformer<TocNode> */
|
||||
final class ToctreeSortingTransformer implements NodeTransformer
|
||||
{
|
||||
public function getPriority(): int
|
||||
{
|
||||
return 3200;
|
||||
}
|
||||
|
||||
public function enterNode(Node $node, CompilerContext $compilerContext): Node
|
||||
{
|
||||
if (!$node instanceof TocNode) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
if (!$node->isReversed()) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
$entries = $node->getValue();
|
||||
$documentEntry = $compilerContext->getDocumentNode()->getDocumentEntry();
|
||||
$documentMenuEntries = $documentEntry->getMenuEntries();
|
||||
if (is_array($entries)) {
|
||||
$entries = array_reverse($entries);
|
||||
$documentMenuEntries = array_reverse($documentMenuEntries);
|
||||
}
|
||||
|
||||
$documentEntry->setMenuEntries($documentMenuEntries);
|
||||
$node->setValue($entries);
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function leaveNode(Node $node, CompilerContext $compilerContext): Node|null
|
||||
{
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function supports(Node $node): bool
|
||||
{
|
||||
return $node instanceof TocNode;
|
||||
}
|
||||
}
|
||||
118
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/MoveAnchorTransformer.php
vendored
Normal file
118
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/MoveAnchorTransformer.php
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers;
|
||||
|
||||
use ArrayIterator;
|
||||
use LogicException;
|
||||
use phpDocumentor\Guides\Compiler\CompilerContextInterface;
|
||||
use phpDocumentor\Guides\Compiler\NodeTransformer;
|
||||
use phpDocumentor\Guides\Compiler\ShadowTree\TreeNode;
|
||||
use phpDocumentor\Guides\Nodes\AnchorNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use phpDocumentor\Guides\Nodes\SectionNode;
|
||||
use WeakMap;
|
||||
|
||||
/** @implements NodeTransformer<AnchorNode> */
|
||||
final class MoveAnchorTransformer implements NodeTransformer
|
||||
{
|
||||
/** @var WeakMap<AnchorNode, true> */
|
||||
private WeakMap $seen;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->seen = new WeakMap();
|
||||
}
|
||||
|
||||
public function enterNode(Node $node, CompilerContextInterface $compilerContext): Node
|
||||
{
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function leaveNode(Node $node, CompilerContextInterface $compilerContext): Node|null
|
||||
{
|
||||
//When exists in seen, it means that the node has already been processed. Ignore it.
|
||||
if (isset($this->seen[$node])) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
$this->seen[$node] = true;
|
||||
$parent = $compilerContext->getShadowTree()->getParent();
|
||||
if ($parent === null) {
|
||||
throw new LogicException('Node not found in shadow tree');
|
||||
}
|
||||
|
||||
$position = $parent->findPosition($node);
|
||||
if ($position === null) {
|
||||
throw new LogicException('Node not found in shadow tree');
|
||||
}
|
||||
|
||||
return $this->attemptMoveToNeighbour($parent, $position, $node);
|
||||
}
|
||||
|
||||
public function supports(Node $node): bool
|
||||
{
|
||||
return $node instanceof AnchorNode;
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
return 30_000;
|
||||
}
|
||||
|
||||
/** @param TreeNode<Node> $parent */
|
||||
private function attemptMoveToNeighbour(TreeNode $parent, int $position, AnchorNode $node): AnchorNode|null
|
||||
{
|
||||
$current = $this->findNextSection($parent, $position);
|
||||
if ($current === null) {
|
||||
if ($parent->getParent() === null) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
$position = $parent->getParent()->findPosition($parent->getNode());
|
||||
if ($position === null) {
|
||||
throw new LogicException('Node not found in shadow tree');
|
||||
}
|
||||
|
||||
return $this->attemptMoveToNeighbour($parent->getParent(), $position, $node);
|
||||
}
|
||||
|
||||
if ($current->getNode() instanceof SectionNode) {
|
||||
$current->pushChild($node);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TreeNode<Node> $parent
|
||||
*
|
||||
* @return TreeNode<Node>|null
|
||||
*/
|
||||
private function findNextSection(TreeNode $parent, int $position): TreeNode|null
|
||||
{
|
||||
$children = new ArrayIterator($parent->getChildren());
|
||||
if ($children->count() <= $position + 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$children->seek($position + 1);
|
||||
while ($children->valid() && $children->current()->getNode() instanceof AnchorNode) {
|
||||
$children->next();
|
||||
}
|
||||
|
||||
return $children->current();
|
||||
}
|
||||
}
|
||||
26
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/NodeTransformerFactory.php
vendored
Normal file
26
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/NodeTransformerFactory.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\NodeTransformer;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
|
||||
interface NodeTransformerFactory
|
||||
{
|
||||
/** @return iterable<NodeTransformer<Node>> */
|
||||
public function getTransformers(): iterable;
|
||||
|
||||
/** @return int[] */
|
||||
public function getPriorities(): array;
|
||||
}
|
||||
72
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/RawNodeEscapeTransformer.php
vendored
Normal file
72
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/RawNodeEscapeTransformer.php
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContext;
|
||||
use phpDocumentor\Guides\Compiler\NodeTransformer;
|
||||
use phpDocumentor\Guides\Nodes\Inline\PlainTextInlineNode;
|
||||
use phpDocumentor\Guides\Nodes\InlineCompoundNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use phpDocumentor\Guides\Nodes\ParagraphNode;
|
||||
use phpDocumentor\Guides\Nodes\RawNode;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HtmlSanitizer\HtmlSanitizer;
|
||||
use Symfony\Component\HtmlSanitizer\HtmlSanitizerConfig;
|
||||
|
||||
use function assert;
|
||||
|
||||
/** @implements NodeTransformer<Node> */
|
||||
final class RawNodeEscapeTransformer implements NodeTransformer
|
||||
{
|
||||
private HtmlSanitizer $htmlSanitizer;
|
||||
|
||||
public function __construct(
|
||||
private readonly bool $escapeRawNodes,
|
||||
private readonly LoggerInterface $logger,
|
||||
HtmlSanitizerConfig $htmlSanitizerConfig,
|
||||
) {
|
||||
$this->htmlSanitizer = new HtmlSanitizer($htmlSanitizerConfig);
|
||||
}
|
||||
|
||||
public function enterNode(Node $node, CompilerContext $compilerContext): Node
|
||||
{
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function leaveNode(Node $node, CompilerContext $compilerContext): Node|null
|
||||
{
|
||||
assert($node instanceof RawNode);
|
||||
if ($this->escapeRawNodes) {
|
||||
$this->logger->warning('We do not support plain HTML for security reasons. Escaping all HTML ');
|
||||
|
||||
return new ParagraphNode([new InlineCompoundNode([new PlainTextInlineNode($node->getValue())])]);
|
||||
}
|
||||
|
||||
if ($node->getOption('format', 'html') === 'html') {
|
||||
return new RawNode($this->htmlSanitizer->sanitize($node->getValue()));
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function supports(Node $node): bool
|
||||
{
|
||||
return $node instanceof RawNode;
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
return 1000;
|
||||
}
|
||||
}
|
||||
139
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/SectionCreationTransformer.php
vendored
Normal file
139
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/SectionCreationTransformer.php
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContextInterface;
|
||||
use phpDocumentor\Guides\Compiler\NodeTransformer;
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use phpDocumentor\Guides\Nodes\SectionNode;
|
||||
use phpDocumentor\Guides\Nodes\TitleNode;
|
||||
|
||||
use function array_pop;
|
||||
use function count;
|
||||
use function end;
|
||||
|
||||
use const PHP_INT_MAX;
|
||||
|
||||
/** @implements NodeTransformer<Node> */
|
||||
final class SectionCreationTransformer implements NodeTransformer
|
||||
{
|
||||
/** @var SectionNode[] $sectionStack */
|
||||
private array $sectionStack = [];
|
||||
private int $firstLevel = 1;
|
||||
|
||||
public function enterNode(Node $node, CompilerContextInterface $compilerContext): Node
|
||||
{
|
||||
if ($node instanceof DocumentNode) {
|
||||
$this->firstLevel = 1;
|
||||
$this->sectionStack = [];
|
||||
}
|
||||
|
||||
if (!$compilerContext->getShadowTree()->getParent()?->getNode() instanceof DocumentNode) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
if (!$node instanceof TitleNode) {
|
||||
$lastSection = end($this->sectionStack);
|
||||
if ($lastSection instanceof SectionNode) {
|
||||
$lastSection->addChildNode($node);
|
||||
}
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function leaveNode(Node $node, CompilerContextInterface $compilerContext): Node|null
|
||||
{
|
||||
if (!$compilerContext->getShadowTree()->getParent()?->getNode() instanceof DocumentNode) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
if ($node instanceof SectionNode) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
if (count($this->sectionStack) === 0 && !$node instanceof TitleNode) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
if (count($this->sectionStack) > 0 && $compilerContext->getShadowTree()->isLastChildOfParent()) {
|
||||
$lastSection = end($this->sectionStack);
|
||||
while ($lastSection?->getTitle()->getLevel() > $this->firstLevel) {
|
||||
$lastSection = array_pop($this->sectionStack);
|
||||
}
|
||||
|
||||
return $lastSection;
|
||||
}
|
||||
|
||||
if (!$node instanceof TitleNode) {
|
||||
// Remove all nodes that will be attached to a section
|
||||
return null;
|
||||
}
|
||||
|
||||
$lastSection = end($this->sectionStack);
|
||||
if ($lastSection instanceof SectionNode && $node !== $lastSection->getTitle() && $node->getLevel() <= $lastSection->getTitle()->getLevel()) {
|
||||
while (end($this->sectionStack) instanceof SectionNode && $node !== end($this->sectionStack)->getTitle() && $node->getLevel() <= end($this->sectionStack)->getTitle()->getLevel()) {
|
||||
$lastSection = array_pop($this->sectionStack);
|
||||
}
|
||||
|
||||
$newSection = new SectionNode($node);
|
||||
// Attach the new section to the last one still on the stack if there still is one
|
||||
if (end($this->sectionStack) instanceof SectionNode) {
|
||||
end($this->sectionStack)->addChildNode($newSection);
|
||||
}
|
||||
|
||||
$this->pushNewSectionToStack($newSection);
|
||||
|
||||
return $lastSection?->getTitle()->getLevel() <= $this->firstLevel ? $lastSection : null;
|
||||
}
|
||||
|
||||
$newSection = new SectionNode($node);
|
||||
if ($lastSection instanceof SectionNode) {
|
||||
$lastSection->addChildNode($newSection);
|
||||
}
|
||||
|
||||
$this->pushNewSectionToStack($newSection);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function supports(Node $node): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
// Should run as first transformer
|
||||
return PHP_INT_MAX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes the new section to the stack.
|
||||
*
|
||||
* The stack is used to track the current level of nodes and adding child
|
||||
* nodes to the section. As not all documentation formats are using the
|
||||
* correct level of title nodes we need to track the level of the first
|
||||
* title node to determine the correct level of the section.
|
||||
*/
|
||||
private function pushNewSectionToStack(SectionNode $newSection): void
|
||||
{
|
||||
if (count($this->sectionStack) === 0) {
|
||||
$this->firstLevel = $newSection->getTitle()->getLevel();
|
||||
}
|
||||
|
||||
$this->sectionStack[] = $newSection;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContextInterface;
|
||||
use phpDocumentor\Guides\Compiler\NodeTransformer;
|
||||
use phpDocumentor\Guides\Nodes\DocumentTree\SectionEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use phpDocumentor\Guides\Nodes\SectionNode;
|
||||
|
||||
use function array_pop;
|
||||
use function assert;
|
||||
use function count;
|
||||
use function end;
|
||||
|
||||
/** @implements NodeTransformer<Node> */
|
||||
final class SectionEntryRegistrationTransformer implements NodeTransformer
|
||||
{
|
||||
/** @var SectionEntryNode[] $sectionStack */
|
||||
private array $sectionStack = [];
|
||||
|
||||
public function enterNode(Node $node, CompilerContextInterface $compilerContext): Node
|
||||
{
|
||||
if (!$node instanceof SectionNode) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
$sectionEntryNode = new SectionEntryNode($node->getTitle());
|
||||
if (count($this->sectionStack) === 0) {
|
||||
$compilerContext->getDocumentNode()->getDocumentEntry()->addSection($sectionEntryNode);
|
||||
} else {
|
||||
$parentSection = end($this->sectionStack);
|
||||
assert($parentSection instanceof SectionEntryNode);
|
||||
$parentSection->addChild($sectionEntryNode);
|
||||
}
|
||||
|
||||
$this->sectionStack[] = $sectionEntryNode;
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function leaveNode(Node $node, CompilerContextInterface $compilerContext): Node|null
|
||||
{
|
||||
if (!$node instanceof SectionNode) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
array_pop($this->sectionStack);
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function supports(Node $node): bool
|
||||
{
|
||||
return $node instanceof SectionNode;
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
// After DocumentEntryRegistrationTransformer
|
||||
return 4900;
|
||||
}
|
||||
}
|
||||
57
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/TransformerPass.php
vendored
Normal file
57
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/TransformerPass.php
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContext;
|
||||
use phpDocumentor\Guides\Compiler\CompilerPass;
|
||||
use phpDocumentor\Guides\Compiler\DocumentNodeTraverser;
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
|
||||
use function array_filter;
|
||||
|
||||
/**
|
||||
* The TransformerPass is a special kind of CompilerPass that traverses all documents and
|
||||
* Calls the DocumentNodeTraverser for each.
|
||||
*
|
||||
* The TransformerPass cannot be injected as there must be one for each available priority of
|
||||
* NodeTransformer.
|
||||
*/
|
||||
final class TransformerPass implements CompilerPass
|
||||
{
|
||||
public function __construct(
|
||||
private readonly DocumentNodeTraverser $documentNodeTraverser,
|
||||
private readonly int $priority,
|
||||
) {
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public function run(array $documents, CompilerContext $compilerContext): array
|
||||
{
|
||||
foreach ($documents as $key => $document) {
|
||||
if (!($document instanceof DocumentNode)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$compilerContext = $compilerContext->withDocumentShadowTree($document);
|
||||
$documents[$key] = $this->documentNodeTraverser->traverse($document, $compilerContext);
|
||||
}
|
||||
|
||||
return array_filter($documents, static fn ($document): bool => $document instanceof DocumentNode);
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
return $this->priority;
|
||||
}
|
||||
}
|
||||
73
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/VariableInlineNodeTransformer.php
vendored
Normal file
73
vendor/phpdocumentor/guides/src/Compiler/NodeTransformers/VariableInlineNodeTransformer.php
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\NodeTransformers;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContextInterface;
|
||||
use phpDocumentor\Guides\Compiler\NodeTransformer;
|
||||
use phpDocumentor\Guides\Nodes\Inline\PlainTextInlineNode;
|
||||
use phpDocumentor\Guides\Nodes\Inline\VariableInlineNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* @implements NodeTransformer<Node>
|
||||
*
|
||||
* The "class" directive sets the "classes" attribute value on its content or on the first immediately following
|
||||
* non-comment element. https://docutils.sourceforge.io/docs/ref/rst/directives.html#class
|
||||
*/
|
||||
final class VariableInlineNodeTransformer implements NodeTransformer
|
||||
{
|
||||
public function __construct(
|
||||
private readonly LoggerInterface $logger,
|
||||
) {
|
||||
}
|
||||
|
||||
public function enterNode(Node $node, CompilerContextInterface $compilerContext): Node
|
||||
{
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function leaveNode(Node $node, CompilerContextInterface $compilerContext): Node|null
|
||||
{
|
||||
if (!$node instanceof VariableInlineNode) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
$nodeReplacement = $compilerContext->getDocumentNode()->getVariable($node->getValue(), null);
|
||||
$nodeReplacement ??= $compilerContext->getProjectNode()->getVariable($node->getValue(), null);
|
||||
|
||||
if ($nodeReplacement instanceof Node) {
|
||||
$node->setChild($nodeReplacement);
|
||||
} else {
|
||||
$this->logger->warning(
|
||||
'No replacement was found for variable |' . $node->getValue() . '|',
|
||||
$compilerContext->getLoggerInformation(),
|
||||
);
|
||||
$node->setChild(new PlainTextInlineNode('|' . $node->getValue() . '|'));
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function supports(Node $node): bool
|
||||
{
|
||||
return $node instanceof VariableInlineNode;
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
// Late, other replacements should already have happened
|
||||
return 30_000;
|
||||
}
|
||||
}
|
||||
112
vendor/phpdocumentor/guides/src/Compiler/Passes/AutomaticMenuPass.php
vendored
Normal file
112
vendor/phpdocumentor/guides/src/Compiler/Passes/AutomaticMenuPass.php
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\Passes;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContextInterface;
|
||||
use phpDocumentor\Guides\Compiler\CompilerPass;
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
use phpDocumentor\Guides\Settings\SettingsManager;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
use function array_pop;
|
||||
use function count;
|
||||
use function explode;
|
||||
use function implode;
|
||||
use function in_array;
|
||||
use function sprintf;
|
||||
|
||||
final class AutomaticMenuPass implements CompilerPass
|
||||
{
|
||||
public function __construct(
|
||||
private readonly SettingsManager $settingsManager,
|
||||
private readonly LoggerInterface|null $logger = null,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
return 20; // must be run very late
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DocumentNode[] $documents
|
||||
*
|
||||
* @return DocumentNode[]
|
||||
*/
|
||||
public function run(array $documents, CompilerContextInterface $compilerContext): array
|
||||
{
|
||||
if (!$this->settingsManager->getProjectSettings()->isAutomaticMenu()) {
|
||||
return $documents;
|
||||
}
|
||||
|
||||
$projectNode = $compilerContext->getProjectNode();
|
||||
$rootDocumentEntry = $projectNode->getRootDocumentEntry();
|
||||
$indexNames = explode(',', $this->settingsManager->getProjectSettings()->getIndexName());
|
||||
foreach ($documents as $documentNode) {
|
||||
if ($documentNode->isOrphan()) {
|
||||
// Do not add orphans to the automatic menu
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($documentNode->isRoot()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$filePath = $documentNode->getFilePath();
|
||||
$pathParts = explode('/', $filePath);
|
||||
$documentEntry = $projectNode->getDocumentEntry($filePath);
|
||||
if (count($pathParts) === 1 || count($pathParts) === 2 && in_array($pathParts[1], $indexNames, true)) {
|
||||
$documentEntry->setParent($rootDocumentEntry);
|
||||
$rootDocumentEntry->addChild($documentEntry);
|
||||
continue;
|
||||
}
|
||||
|
||||
$fileName = array_pop($pathParts);
|
||||
$path = implode('/', $pathParts);
|
||||
if (in_array($fileName, $indexNames, true)) {
|
||||
array_pop($pathParts);
|
||||
$path = implode('/', $pathParts);
|
||||
}
|
||||
|
||||
$parentFound = false;
|
||||
foreach ($indexNames as $indexName) {
|
||||
$indexFile = $path . '/' . $indexName;
|
||||
$parentEntry = $projectNode->findDocumentEntry($indexFile);
|
||||
if ($parentEntry === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$documentEntry->setParent($parentEntry);
|
||||
$parentEntry->addChild($documentEntry);
|
||||
$parentFound = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if ($parentFound) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$parentEntry = $projectNode->findDocumentEntry($path);
|
||||
if ($parentEntry === null) {
|
||||
$this->logger?->warning(sprintf('No parent found for file "%s/%s" attaching it to the document root instead. ', $path, $fileName));
|
||||
continue;
|
||||
}
|
||||
|
||||
$documentEntry->setParent($parentEntry);
|
||||
$parentEntry->addChild($documentEntry);
|
||||
}
|
||||
|
||||
return $documents;
|
||||
}
|
||||
}
|
||||
212
vendor/phpdocumentor/guides/src/Compiler/Passes/GlobalMenuPass.php
vendored
Normal file
212
vendor/phpdocumentor/guides/src/Compiler/Passes/GlobalMenuPass.php
vendored
Normal file
@@ -0,0 +1,212 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\Passes;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContextInterface;
|
||||
use phpDocumentor\Guides\Compiler\CompilerPass;
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
use phpDocumentor\Guides\Nodes\DocumentTree\DocumentEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\DocumentTree\EntryNode;
|
||||
use phpDocumentor\Guides\Nodes\DocumentTree\ExternalEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\ExternalMenuEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\InternalMenuEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\MenuEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\NavMenuNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\TocNode;
|
||||
use phpDocumentor\Guides\Nodes\TitleNode;
|
||||
use phpDocumentor\Guides\Settings\SettingsManager;
|
||||
use Throwable;
|
||||
|
||||
use function array_map;
|
||||
use function assert;
|
||||
use function count;
|
||||
|
||||
use const PHP_INT_MAX;
|
||||
|
||||
final class GlobalMenuPass implements CompilerPass
|
||||
{
|
||||
public function __construct(
|
||||
private readonly SettingsManager $settingsManager,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
return 20; // must be run very late
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DocumentNode[] $documents
|
||||
*
|
||||
* @return DocumentNode[]
|
||||
*/
|
||||
public function run(array $documents, CompilerContextInterface $compilerContext): array
|
||||
{
|
||||
$projectNode = $compilerContext->getProjectNode();
|
||||
try {
|
||||
$rootDocumentEntry = $projectNode->getRootDocumentEntry();
|
||||
} catch (Throwable) {
|
||||
// Todo: Functional tests have no root document entry
|
||||
return $documents;
|
||||
}
|
||||
|
||||
$rootDocument = null;
|
||||
$rootFile = $rootDocumentEntry->getFile();
|
||||
foreach ($documents as $document) {
|
||||
if ($document->getDocumentEntry()->getFile() === $rootFile) {
|
||||
$rootDocument = $document;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($rootDocument === null) {
|
||||
return $documents;
|
||||
}
|
||||
|
||||
$menuNodes = [];
|
||||
foreach ($rootDocument->getTocNodes() as $tocNode) {
|
||||
$menuNode = $this->getNavMenuNodefromTocNode($compilerContext, $tocNode);
|
||||
$menuNodes[] = $menuNode->withCaption($tocNode->getCaption());
|
||||
}
|
||||
|
||||
if ($this->settingsManager->getProjectSettings()->isAutomaticMenu() && count($menuNodes) === 0) {
|
||||
$menuNodes[] = $this->getNavMenuNodeFromDocumentEntries($compilerContext);
|
||||
}
|
||||
|
||||
$projectNode->setGlobalMenues($menuNodes);
|
||||
|
||||
return $documents;
|
||||
}
|
||||
|
||||
private function getNavMenuNodeFromDocumentEntries(CompilerContextInterface $compilerContext): NavMenuNode
|
||||
{
|
||||
$rootDocumentEntry = $compilerContext->getProjectNode()->getRootDocumentEntry();
|
||||
$menuEntries = $this->getMenuEntriesFromDocumentEntries($rootDocumentEntry);
|
||||
|
||||
return new NavMenuNode($menuEntries);
|
||||
}
|
||||
|
||||
/** @return InternalMenuEntryNode[] */
|
||||
public function getMenuEntriesFromDocumentEntries(DocumentEntryNode $rootDocumentEntry): array
|
||||
{
|
||||
$menuEntries = [];
|
||||
foreach ($rootDocumentEntry->getChildren() as $documentEntryNode) {
|
||||
$children = $this->getMenuEntriesFromDocumentEntries($documentEntryNode);
|
||||
$newMenuEntry = new InternalMenuEntryNode($documentEntryNode->getFile(), $documentEntryNode->getTitle(), $children, false, 1);
|
||||
$menuEntries[] = $newMenuEntry;
|
||||
}
|
||||
|
||||
return $menuEntries;
|
||||
}
|
||||
|
||||
private function getNavMenuNodefromTocNode(CompilerContextInterface $compilerContext, TocNode $tocNode, string|null $menuType = null): NavMenuNode
|
||||
{
|
||||
$self = $this;
|
||||
$menuEntries = array_map(static function (MenuEntryNode $tocEntry) use ($compilerContext, $self) {
|
||||
return $self->getMenuEntryWithChildren($compilerContext, $tocEntry);
|
||||
}, $tocNode->getMenuEntries());
|
||||
$node = new NavMenuNode($menuEntries);
|
||||
$options = $tocNode->getOptions();
|
||||
unset($options['hidden']);
|
||||
unset($options['titlesonly']);
|
||||
unset($options['maxdepth']);
|
||||
if ($menuType !== null) {
|
||||
$options['menu'] = $menuType;
|
||||
}
|
||||
|
||||
$node = $node->withOptions($options);
|
||||
assert($node instanceof NavMenuNode);
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
private function getMenuEntryWithChildren(CompilerContextInterface $compilerContext, MenuEntryNode $menuEntry): MenuEntryNode
|
||||
{
|
||||
if (!$menuEntry instanceof InternalMenuEntryNode) {
|
||||
return $menuEntry;
|
||||
}
|
||||
|
||||
$newMenuEntry = new InternalMenuEntryNode($menuEntry->getUrl(), $menuEntry->getValue(), [], false, 1);
|
||||
$maxdepth = $this->settingsManager->getProjectSettings()->getMaxMenuDepth();
|
||||
$maxdepth = $maxdepth < 1 ? PHP_INT_MAX : $maxdepth + 1;
|
||||
$documentEntryOfMenuEntry = $compilerContext->getProjectNode()->getDocumentEntry($menuEntry->getUrl());
|
||||
$this->addSubEntries($compilerContext, $newMenuEntry, $documentEntryOfMenuEntry, 2, $maxdepth);
|
||||
|
||||
return $newMenuEntry;
|
||||
}
|
||||
|
||||
/** @param EntryNode<DocumentEntryNode|ExternalEntryNode>|ExternalEntryNode $entryNode */
|
||||
private function addSubEntries(
|
||||
CompilerContextInterface $compilerContext,
|
||||
MenuEntryNode $sectionMenuEntry,
|
||||
EntryNode $entryNode,
|
||||
int $currentLevel,
|
||||
int $maxDepth,
|
||||
): void {
|
||||
if ($maxDepth <= $currentLevel) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$sectionMenuEntry instanceof InternalMenuEntryNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$entryNode instanceof DocumentEntryNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($entryNode->getMenuEntries() as $subEntryNode) {
|
||||
$subMenuEntry = match ($subEntryNode::class) {
|
||||
DocumentEntryNode::class => $this->createInternalMenuEntry($subEntryNode, $currentLevel),
|
||||
ExternalEntryNode::class => $this->createExternalMenuEntry($subEntryNode, $currentLevel),
|
||||
};
|
||||
|
||||
$sectionMenuEntry->addMenuEntry($subMenuEntry);
|
||||
$this->addSubEntries(
|
||||
$compilerContext,
|
||||
$subMenuEntry,
|
||||
$subEntryNode,
|
||||
$currentLevel + 1,
|
||||
$maxDepth,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function createInternalMenuEntry(DocumentEntryNode $subEntryNode, int $currentLevel): InternalMenuEntryNode
|
||||
{
|
||||
$titleNode = $subEntryNode->getTitle();
|
||||
$navigationTitle = $subEntryNode->getAdditionalData('navigationTitle');
|
||||
if ($navigationTitle instanceof TitleNode) {
|
||||
$titleNode = $navigationTitle;
|
||||
}
|
||||
|
||||
return new InternalMenuEntryNode(
|
||||
$subEntryNode->getFile(),
|
||||
$titleNode,
|
||||
[],
|
||||
false,
|
||||
$currentLevel,
|
||||
'',
|
||||
);
|
||||
}
|
||||
|
||||
private function createExternalMenuEntry(ExternalEntryNode $subEntryNode, int $currentLevel): ExternalMenuEntryNode
|
||||
{
|
||||
return new ExternalMenuEntryNode(
|
||||
$subEntryNode->getValue(),
|
||||
TitleNode::fromString($subEntryNode->getTitle()),
|
||||
$currentLevel,
|
||||
);
|
||||
}
|
||||
}
|
||||
105
vendor/phpdocumentor/guides/src/Compiler/Passes/ImplicitHyperlinkTargetPass.php
vendored
Normal file
105
vendor/phpdocumentor/guides/src/Compiler/Passes/ImplicitHyperlinkTargetPass.php
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\Passes;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContextInterface;
|
||||
use phpDocumentor\Guides\Compiler\CompilerPass;
|
||||
use phpDocumentor\Guides\Nodes\AnchorNode;
|
||||
use phpDocumentor\Guides\Nodes\CompoundNode;
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use phpDocumentor\Guides\Nodes\SectionNode;
|
||||
|
||||
use function array_map;
|
||||
use function array_merge;
|
||||
use function current;
|
||||
use function in_array;
|
||||
use function next;
|
||||
|
||||
/**
|
||||
* Resolves the hyperlink target for each section in the document.
|
||||
*
|
||||
* This follows the reStructuredText rules as outlined in:
|
||||
* https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#implicit-hyperlink-targets
|
||||
*/
|
||||
final class ImplicitHyperlinkTargetPass implements CompilerPass
|
||||
{
|
||||
public function getPriority(): int
|
||||
{
|
||||
return 20_000; // must be run *before* MetasPass
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public function run(array $documents, CompilerContextInterface $compilerContext): array
|
||||
{
|
||||
return array_map(function (DocumentNode $document): DocumentNode {
|
||||
// implicit references must not conflict with explicit ones
|
||||
$knownReferences = $this->fetchExplicitReferences($document);
|
||||
|
||||
$nodes = $document->getNodes();
|
||||
$this->deduplicateSectionIds($nodes, $knownReferences);
|
||||
|
||||
return $document;
|
||||
}, $documents);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, Node> $nodes
|
||||
* @param list<string> $knownIds
|
||||
*
|
||||
* @return list<string>
|
||||
*/
|
||||
private function deduplicateSectionIds(array $nodes, array $knownIds): array
|
||||
{
|
||||
$node = current($nodes);
|
||||
do {
|
||||
if ($node instanceof SectionNode) {
|
||||
$realId = $sectionId = $node->getTitle()->getId();
|
||||
|
||||
// resolve conflicting references by appending an increasing number
|
||||
$i = 1;
|
||||
while (in_array($realId, $knownIds, true)) {
|
||||
$realId = $sectionId . '-' . ($i++);
|
||||
}
|
||||
|
||||
$node->getTitle()->setId($realId);
|
||||
$knownIds[] = $realId;
|
||||
}
|
||||
|
||||
if ($node instanceof CompoundNode) {
|
||||
$knownIds = $this->deduplicateSectionIds($node->getChildren(), $knownIds);
|
||||
}
|
||||
//phpcs:ignore SlevomatCodingStandard.ControlStructures.AssignmentInCondition.AssignmentInCondition
|
||||
} while ($node = next($nodes));
|
||||
|
||||
return $knownIds;
|
||||
}
|
||||
|
||||
/** @return string[] */
|
||||
private function fetchExplicitReferences(Node $node): array
|
||||
{
|
||||
if ($node instanceof AnchorNode) {
|
||||
return [$node->getValue()];
|
||||
}
|
||||
|
||||
$anchors = [];
|
||||
if ($node instanceof CompoundNode) {
|
||||
foreach ($node->getChildren() as $child) {
|
||||
$anchors[] = $this->fetchExplicitReferences($child);
|
||||
}
|
||||
}
|
||||
|
||||
return array_merge(...$anchors);
|
||||
}
|
||||
}
|
||||
74
vendor/phpdocumentor/guides/src/Compiler/Passes/ToctreeValidationPass.php
vendored
Normal file
74
vendor/phpdocumentor/guides/src/Compiler/Passes/ToctreeValidationPass.php
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\Passes;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContextInterface;
|
||||
use phpDocumentor\Guides\Compiler\CompilerPass;
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
use phpDocumentor\Guides\Nodes\DocumentTree\DocumentEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\ProjectNode;
|
||||
use phpDocumentor\Guides\Settings\ProjectSettings;
|
||||
use phpDocumentor\Guides\Settings\SettingsManager;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
final class ToctreeValidationPass implements CompilerPass
|
||||
{
|
||||
private SettingsManager $settingsManager;
|
||||
|
||||
public function __construct(
|
||||
private readonly LoggerInterface $logger,
|
||||
SettingsManager|null $settingsManager = null,
|
||||
) {
|
||||
// if for backward compatibility reasons no settings manager was passed, use the defaults
|
||||
$this->settingsManager = $settingsManager ?? new SettingsManager(new ProjectSettings());
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
return 20; // must be run very late
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DocumentNode[] $documents
|
||||
*
|
||||
* @return DocumentNode[]
|
||||
*/
|
||||
public function run(array $documents, CompilerContextInterface $compilerContext): array
|
||||
{
|
||||
if ($this->settingsManager->getProjectSettings()->isAutomaticMenu()) {
|
||||
return $documents;
|
||||
}
|
||||
|
||||
$projectNode = $compilerContext->getProjectNode();
|
||||
|
||||
foreach ($documents as $document) {
|
||||
if (!$this->isMissingInToctree($projectNode->getDocumentEntry($document->getFilePath()), $projectNode) || $document->isOrphan()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->logger->warning(
|
||||
'Document "' . $document->getFilePath() . '" isn\'t included in any toctree. Include it in a `.. toctree::` directive or add `:orphan:` in the first line of the rst document',
|
||||
$document->getLoggerInformation(),
|
||||
);
|
||||
}
|
||||
|
||||
return $documents;
|
||||
}
|
||||
|
||||
public function isMissingInToctree(DocumentEntryNode $documentEntry, ProjectNode $projectNode): bool
|
||||
{
|
||||
return $documentEntry->getParent() === null
|
||||
&& $documentEntry->getFile() !== $projectNode->getRootDocumentEntry()->getFile();
|
||||
}
|
||||
}
|
||||
211
vendor/phpdocumentor/guides/src/Compiler/ShadowTree/TreeNode.php
vendored
Normal file
211
vendor/phpdocumentor/guides/src/Compiler/ShadowTree/TreeNode.php
vendored
Normal file
@@ -0,0 +1,211 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Compiler\ShadowTree;
|
||||
|
||||
use LogicException;
|
||||
use phpDocumentor\Guides\Nodes\CompoundNode;
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
|
||||
use function array_unshift;
|
||||
use function array_values;
|
||||
use function count;
|
||||
|
||||
/** @template-covariant TNode of Node */
|
||||
final class TreeNode
|
||||
{
|
||||
/** @var TreeNode<DocumentNode> */
|
||||
private TreeNode $root;
|
||||
|
||||
/** @var self<Node>[] */
|
||||
private array $children = [];
|
||||
|
||||
private function __construct(
|
||||
/** @var TNode */
|
||||
private Node $node,
|
||||
/** @var self<Node>|self<DocumentNode>|null */
|
||||
private self|null $parent = null,
|
||||
) {
|
||||
}
|
||||
|
||||
/** @return TreeNode<DocumentNode> */
|
||||
public static function createFromDocument(DocumentNode $document): self
|
||||
{
|
||||
$node = new self($document);
|
||||
$node->setChildren(self::createFromCompoundNode($document, $node));
|
||||
$node->setRoot($node);
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CompoundNode<Node> $node
|
||||
* @param self<Node>|self<DocumentNode>|null $parent
|
||||
*
|
||||
* @return TreeNode<Node>[]
|
||||
*/
|
||||
private static function createFromCompoundNode(CompoundNode $node, self|null $parent): array
|
||||
{
|
||||
$children = [];
|
||||
foreach ($node->getChildren() as $child) {
|
||||
$children[] = self::createFromNode($child, $parent);
|
||||
}
|
||||
|
||||
return $children;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TValue $node
|
||||
* @param self<Node>|self<DocumentNode>|null $parent
|
||||
*
|
||||
* @return TreeNode<TValue>
|
||||
*
|
||||
* @template TValue of Node
|
||||
*/
|
||||
private static function createFromNode(Node $node, self|null $parent = null): self
|
||||
{
|
||||
$treeNode = new self($node, $parent);
|
||||
if ($node instanceof CompoundNode === false) {
|
||||
return $treeNode;
|
||||
}
|
||||
|
||||
$treeNode->setChildren(self::createFromCompoundNode($node, $treeNode));
|
||||
|
||||
return $treeNode;
|
||||
}
|
||||
|
||||
/** @param self<Node>[] $children */
|
||||
private function setChildren(array $children): void
|
||||
{
|
||||
foreach ($children as $child) {
|
||||
$child->parent = $this;
|
||||
}
|
||||
|
||||
$this->children = $children;
|
||||
}
|
||||
|
||||
/** @return self<DocumentNode> */
|
||||
public function getRoot(): self
|
||||
{
|
||||
return $this->root;
|
||||
}
|
||||
|
||||
/** @param self<DocumentNode> $root */
|
||||
private function setRoot(self $root): void
|
||||
{
|
||||
$this->root = $root;
|
||||
foreach ($this->children as $child) {
|
||||
$child->setRoot($root);
|
||||
}
|
||||
}
|
||||
|
||||
/** @return TNode */
|
||||
public function getNode(): Node
|
||||
{
|
||||
return $this->node;
|
||||
}
|
||||
|
||||
/** @return TreeNode<Node>[] */
|
||||
public function getChildren(): array
|
||||
{
|
||||
return $this->children;
|
||||
}
|
||||
|
||||
public function addChild(Node $child): void
|
||||
{
|
||||
if ($this->node instanceof CompoundNode === false) {
|
||||
throw new LogicException('Cannot add a child to a non-compound node');
|
||||
}
|
||||
|
||||
$shadowNode = self::createFromNode($child, $this);
|
||||
$shadowNode->setRoot($this->root);
|
||||
$this->children[] = $shadowNode;
|
||||
$this->node->addChildNode($child);
|
||||
}
|
||||
|
||||
public function pushChild(Node $child): void
|
||||
{
|
||||
if ($this->node instanceof CompoundNode === false) {
|
||||
throw new LogicException('Cannot add a child to a non-compound node');
|
||||
}
|
||||
|
||||
$shadowNode = self::createFromNode($child, $this);
|
||||
$shadowNode->setRoot($this->root);
|
||||
array_unshift($this->children, $shadowNode);
|
||||
$this->node->pushChildNode($child);
|
||||
}
|
||||
|
||||
/** @return self<Node>|self<DocumentNode>|null */
|
||||
public function getParent(): TreeNode|null
|
||||
{
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
public function removeChild(Node $node): void
|
||||
{
|
||||
if ($this->node instanceof CompoundNode === false) {
|
||||
throw new LogicException('Cannot remove a child from a non-compound node');
|
||||
}
|
||||
|
||||
foreach ($this->children as $key => $child) {
|
||||
if ($child->getNode() === $node) {
|
||||
unset($this->children[$key]);
|
||||
$child->parent = null;
|
||||
$newNode = $this->node->removeNode($key);
|
||||
$this->parent?->replaceChild($this->node, $newNode);
|
||||
$this->node = $newNode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->children = array_values($this->children);
|
||||
}
|
||||
|
||||
public function replaceChild(Node $oldChildNode, Node $newChildNode): void
|
||||
{
|
||||
if ($this->node instanceof CompoundNode === false) {
|
||||
throw new LogicException('Cannot remove a child from a non-compound node');
|
||||
}
|
||||
|
||||
foreach ($this->children as $key => $child) {
|
||||
if ($child->getNode() === $oldChildNode) {
|
||||
$child->node = $newChildNode;
|
||||
$newNode = $this->node->replaceNode($key, $newChildNode);
|
||||
$this->parent?->replaceChild($this->node, $newNode);
|
||||
$this->node = $newNode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function findPosition(Node $node): int|null
|
||||
{
|
||||
foreach ($this->children as $key => $child) {
|
||||
if ($child->getNode() === $node) {
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function isLastChildOfParent(): bool
|
||||
{
|
||||
if ($this->parent === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->parent->findPosition($this->node) === count($this->parent->getChildren()) - 1;
|
||||
}
|
||||
}
|
||||
47
vendor/phpdocumentor/guides/src/DependencyInjection/CommandLocator.php
vendored
Normal file
47
vendor/phpdocumentor/guides/src/DependencyInjection/CommandLocator.php
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\DependencyInjection;
|
||||
|
||||
use League\Tactician\Exception\MissingHandlerException;
|
||||
use League\Tactician\Handler\Locator\HandlerLocator;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
|
||||
use function assert;
|
||||
use function is_object;
|
||||
use function sprintf;
|
||||
|
||||
final class CommandLocator implements HandlerLocator
|
||||
{
|
||||
public function __construct(private readonly ContainerInterface $commands)
|
||||
{
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public function getHandlerForCommand($commandName): object
|
||||
{
|
||||
try {
|
||||
$command = $this->commands->get($commandName);
|
||||
assert(is_object($command));
|
||||
|
||||
return $command;
|
||||
} catch (NotFoundExceptionInterface $e) {
|
||||
throw new MissingHandlerException(
|
||||
sprintf('No handler found for command "%s"', $commandName),
|
||||
$e->getCode(),
|
||||
$e,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
51
vendor/phpdocumentor/guides/src/DependencyInjection/Compiler/NodeRendererPass.php
vendored
Normal file
51
vendor/phpdocumentor/guides/src/DependencyInjection/Compiler/NodeRendererPass.php
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\DependencyInjection\Compiler;
|
||||
|
||||
use phpDocumentor\Guides\NodeRenderers\TemplateNodeRenderer;
|
||||
use phpDocumentor\Guides\TemplateRenderer;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
use function is_array;
|
||||
use function sprintf;
|
||||
|
||||
final class NodeRendererPass implements CompilerPassInterface
|
||||
{
|
||||
public function process(ContainerBuilder $container): void
|
||||
{
|
||||
$definitions = [];
|
||||
if (is_array($container->getParameter('phpdoc.guides.node_templates')) === false) {
|
||||
throw new RuntimeException('phpdoc.guides.node_templates must be an array');
|
||||
}
|
||||
|
||||
foreach ($container->getParameter('phpdoc.guides.node_templates') as $nodeTemplate) {
|
||||
$definition = new Definition(
|
||||
TemplateNodeRenderer::class,
|
||||
[
|
||||
'$renderer' => new Reference(TemplateRenderer::class),
|
||||
'$template' => $nodeTemplate['file'],
|
||||
'$nodeClass' => $nodeTemplate['node'],
|
||||
],
|
||||
);
|
||||
$definition->addTag('phpdoc.guides.noderenderer.' . $nodeTemplate['format']);
|
||||
$definitions[sprintf('phpdoc.guides.noderenderer.%s.%s', $nodeTemplate['format'], $nodeTemplate['node'])] = $definition;
|
||||
}
|
||||
|
||||
$container->addDefinitions($definitions);
|
||||
}
|
||||
}
|
||||
39
vendor/phpdocumentor/guides/src/DependencyInjection/Compiler/ParserRulesPass.php
vendored
Normal file
39
vendor/phpdocumentor/guides/src/DependencyInjection/Compiler/ParserRulesPass.php
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\DependencyInjection\Compiler;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
||||
final class ParserRulesPass implements CompilerPassInterface
|
||||
{
|
||||
use PriorityTaggedServiceTrait;
|
||||
|
||||
public function process(ContainerBuilder $container): void
|
||||
{
|
||||
$body = $container->findDefinition('phpdoc.guides.parser.rst.body_elements');
|
||||
$structual = $container->findDefinition('phpdoc.guides.parser.rst.structural_elements');
|
||||
|
||||
foreach ($this->findAndSortTaggedServices('phpdoc.guides.parser.rst.structural_element', $container) as $reference) {
|
||||
$structual->addMethodCall('push', [$reference]);
|
||||
}
|
||||
|
||||
foreach ($this->findAndSortTaggedServices('phpdoc.guides.parser.rst.body_element', $container) as $reference) {
|
||||
$body->addMethodCall('push', [$reference]);
|
||||
//TODO: remove this call to $structual, body elements should not be part of it once subparser is removed
|
||||
$structual->addMethodCall('push', [$reference]);
|
||||
}
|
||||
}
|
||||
}
|
||||
83
vendor/phpdocumentor/guides/src/DependencyInjection/Compiler/RendererPass.php
vendored
Normal file
83
vendor/phpdocumentor/guides/src/DependencyInjection/Compiler/RendererPass.php
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\DependencyInjection\Compiler;
|
||||
|
||||
use phpDocumentor\Guides\NodeRenderers\DefaultNodeRenderer;
|
||||
use phpDocumentor\Guides\NodeRenderers\DelegatingNodeRenderer;
|
||||
use phpDocumentor\Guides\NodeRenderers\InMemoryNodeRendererFactory;
|
||||
use phpDocumentor\Guides\NodeRenderers\PreRenderers\PreNodeRendererFactory;
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
use function sprintf;
|
||||
use function Symfony\Component\DependencyInjection\Loader\Configurator\tagged_iterator;
|
||||
|
||||
final class RendererPass implements CompilerPassInterface
|
||||
{
|
||||
public function process(ContainerBuilder $container): void
|
||||
{
|
||||
$definitions = [];
|
||||
foreach ($container->findTaggedServiceIds('phpdoc.renderer.typerenderer') as $id => $tags) {
|
||||
foreach ($tags as $tag) {
|
||||
if (isset($tag['noderender_tag']) === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$definitions[sprintf('phpdoc.guides.noderenderer.factory.%s', $tag['format'])] = $this->createNodeRendererFactory($tag);
|
||||
$definitions[sprintf('phpdoc.guides.noderenderer.prefactory.%s', $tag['format'])] = $this->createPreNodeRendererFactory($tag);
|
||||
$definitions[sprintf('phpdoc.guides.noderenderer.delegating.%s', $tag['format'])] = $this->createDelegatingNodeRender($tag);
|
||||
$definitions[sprintf('phpdoc.guides.noderenderer.default.%s', $tag['format'])] = (new Definition(DefaultNodeRenderer::class))->setAutowired(true)
|
||||
->addMethodCall('setNodeRendererFactory', [new Reference(sprintf('phpdoc.guides.noderenderer.factory.%s', $tag['format']))])
|
||||
->addTag(sprintf('phpdoc.guides.noderenderer.%s', $tag['format']));
|
||||
}
|
||||
}
|
||||
|
||||
$container->addDefinitions($definitions);
|
||||
}
|
||||
|
||||
/** @param array{format: string} $tag */
|
||||
private function createDelegatingNodeRender(array $tag): Definition
|
||||
{
|
||||
return (new Definition(DelegatingNodeRenderer::class))
|
||||
->addTag('phpdoc.guides.output_node_renderer', ['format' => $tag['format']])
|
||||
->addMethodCall('setNodeRendererFactory', [new Reference(sprintf('phpdoc.guides.noderenderer.factory.%s', $tag['format']))]);
|
||||
}
|
||||
|
||||
/** @param array{format: string, noderender_tag: string} $tag */
|
||||
private function createNodeRendererFactory(array $tag): Definition
|
||||
{
|
||||
return new Definition(
|
||||
InMemoryNodeRendererFactory::class,
|
||||
[
|
||||
'$nodeRenderers' => tagged_iterator($tag['noderender_tag']),
|
||||
'$defaultNodeRenderer' => new Reference(sprintf('phpdoc.guides.noderenderer.default.%s', $tag['format'])),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/** @param array{format: string, noderender_tag: string} $tag */
|
||||
private function createPreNodeRendererFactory(array $tag): Definition
|
||||
{
|
||||
return (new Definition(
|
||||
PreNodeRendererFactory::class,
|
||||
[
|
||||
'$innerFactory' => new Reference('.inner'),
|
||||
'$preRenderers' => tagged_iterator('phpdoc.guides.prerenderer'),
|
||||
],
|
||||
))
|
||||
->setDecoratedService(sprintf('phpdoc.guides.noderenderer.factory.%s', $tag['format']));
|
||||
}
|
||||
}
|
||||
521
vendor/phpdocumentor/guides/src/DependencyInjection/GuidesExtension.php
vendored
Normal file
521
vendor/phpdocumentor/guides/src/DependencyInjection/GuidesExtension.php
vendored
Normal file
@@ -0,0 +1,521 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\DependencyInjection;
|
||||
|
||||
use phpDocumentor\FileSystem\Finder\Exclude;
|
||||
use phpDocumentor\Guides\Compiler\NodeTransformers\RawNodeEscapeTransformer;
|
||||
use phpDocumentor\Guides\DependencyInjection\Compiler\NodeRendererPass;
|
||||
use phpDocumentor\Guides\DependencyInjection\Compiler\ParserRulesPass;
|
||||
use phpDocumentor\Guides\DependencyInjection\Compiler\RendererPass;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use phpDocumentor\Guides\Settings\ProjectSettings;
|
||||
use phpDocumentor\Guides\Settings\SettingsManager;
|
||||
use phpDocumentor\Guides\Twig\Theme\ThemeConfig;
|
||||
use phpDocumentor\Guides\Twig\Theme\ThemeManager;
|
||||
use Psr\Log\LogLevel;
|
||||
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
|
||||
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
||||
use Symfony\Component\Config\Definition\ConfigurationInterface;
|
||||
use Symfony\Component\Config\FileLocator;
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Extension\Extension;
|
||||
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
|
||||
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\HtmlSanitizer\HtmlSanitizerConfig;
|
||||
|
||||
use function array_keys;
|
||||
use function array_map;
|
||||
use function array_merge;
|
||||
use function array_values;
|
||||
use function assert;
|
||||
use function dirname;
|
||||
use function is_array;
|
||||
use function is_int;
|
||||
use function is_string;
|
||||
use function pathinfo;
|
||||
use function trim;
|
||||
use function var_export;
|
||||
|
||||
final class GuidesExtension extends Extension implements CompilerPassInterface, ConfigurationInterface, PrependExtensionInterface
|
||||
{
|
||||
public function getConfigTreeBuilder(): TreeBuilder
|
||||
{
|
||||
$treeBuilder = new TreeBuilder('guides');
|
||||
$rootNode = $treeBuilder->getRootNode();
|
||||
assert($rootNode instanceof ArrayNodeDefinition);
|
||||
|
||||
$rootNode
|
||||
->fixXmlConfig('template')
|
||||
->fixXmlConfig('inventory', 'inventories')
|
||||
->children()
|
||||
->arrayNode('project')
|
||||
->children()
|
||||
->scalarNode('title')->end()
|
||||
->scalarNode('version')
|
||||
->beforeNormalization()
|
||||
->always(
|
||||
// We need to revert the phpize call in XmlUtils. Version is always a string!
|
||||
static function ($value) {
|
||||
if (!is_int($value) && !is_string($value)) {
|
||||
return var_export($value, true);
|
||||
}
|
||||
|
||||
if (is_string($value)) {
|
||||
return trim($value, "'");
|
||||
}
|
||||
|
||||
return $value;
|
||||
},
|
||||
)
|
||||
->end()
|
||||
->end()
|
||||
->scalarNode('release')
|
||||
->beforeNormalization()
|
||||
->always(
|
||||
// We need to revert the phpize call in XmlUtils. Version is always a string!
|
||||
static function ($value) {
|
||||
if (!is_int($value) && !is_string($value)) {
|
||||
return var_export($value, true);
|
||||
}
|
||||
|
||||
if (is_string($value)) {
|
||||
return trim($value, "'");
|
||||
}
|
||||
|
||||
return $value;
|
||||
},
|
||||
)
|
||||
->end()
|
||||
->end()
|
||||
->scalarNode('copyright')->end()
|
||||
->end()
|
||||
->end()
|
||||
->arrayNode('inventories')
|
||||
->arrayPrototype()
|
||||
->children()
|
||||
->scalarNode('id')
|
||||
->isRequired()
|
||||
->end()
|
||||
->scalarNode('url')
|
||||
->isRequired()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->scalarNode('theme')->end()
|
||||
->scalarNode('input')->end()
|
||||
->scalarNode('input_file')->end()
|
||||
->scalarNode('index_name')->end()
|
||||
->arrayNode('exclude')
|
||||
->addDefaultsIfNotSet()
|
||||
->fixXmlConfig('path')
|
||||
->children()
|
||||
->booleanNode('hidden')->defaultTrue()->end()
|
||||
->booleanNode('symlinks')->defaultTrue()->end()
|
||||
->append($this->paths())
|
||||
->end()
|
||||
->end()
|
||||
->scalarNode('output')->end()
|
||||
->scalarNode('input_format')->end()
|
||||
->arrayNode('output_format')
|
||||
->defaultValue(['html', 'interlink'])
|
||||
->beforeNormalization()
|
||||
->ifString()
|
||||
->then(static function ($value) {
|
||||
return [$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()
|
||||
->scalarNode('show_progress')->end()
|
||||
->scalarNode('links_are_relative')->end()
|
||||
->scalarNode('max_menu_depth')->end()
|
||||
->scalarNode('automatic_menu')->end()
|
||||
->arrayNode('base_template_paths')
|
||||
->defaultValue([])
|
||||
->scalarPrototype()->end()
|
||||
->end()
|
||||
->arrayNode('templates')
|
||||
->arrayPrototype()
|
||||
->children()
|
||||
->scalarNode('node')
|
||||
->isRequired()
|
||||
->end()
|
||||
->scalarNode('file')
|
||||
->isRequired()
|
||||
->end()
|
||||
->scalarNode('format')
|
||||
->defaultValue('html')
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->arrayNode('raw_node')
|
||||
->fixXmlConfig('sanitizer')
|
||||
->children()
|
||||
->booleanNode('escape')->defaultValue(false)->end()
|
||||
->scalarNode('sanitizer_name')->end()
|
||||
->arrayNode('sanitizers')
|
||||
->defaultValue([])
|
||||
->useAttributeAsKey('name')
|
||||
->arrayPrototype()
|
||||
->fixXmlConfig('allow_element')
|
||||
->fixXmlConfig('drop_element')
|
||||
->fixXmlConfig('block_element')
|
||||
->fixXmlConfig('allow_attribute')
|
||||
->fixXmlConfig('drop_attribute')
|
||||
->children()
|
||||
->booleanNode('allow_safe_elements')->defaultValue(true)->end()
|
||||
->booleanNode('allow_static_elements')->defaultValue(true)->end()
|
||||
->arrayNode('allow_elements')
|
||||
->normalizeKeys(false)
|
||||
->useAttributeAsKey('name')
|
||||
->variablePrototype()
|
||||
->beforeNormalization()
|
||||
->ifArray()->then(static fn ($n) => $n['attribute'] ?? $n)
|
||||
->end()
|
||||
->validate()
|
||||
->ifTrue(static fn ($n): bool => !is_string($n) && !is_array($n))
|
||||
->thenInvalid('The value must be either a string or an array of strings.')
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->arrayNode('block_elements')
|
||||
->beforeNormalization()->castToArray()->end()
|
||||
->scalarPrototype()->end()
|
||||
->end()
|
||||
->arrayNode('drop_elements')
|
||||
->beforeNormalization()->castToArray()->end()
|
||||
->scalarPrototype()->end()
|
||||
->end()
|
||||
->arrayNode('allow_attributes')
|
||||
->normalizeKeys(false)
|
||||
->useAttributeAsKey('name')
|
||||
->variablePrototype()
|
||||
->beforeNormalization()
|
||||
->ifArray()->then(static fn ($n) => $n['element'] ?? $n)
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->arrayNode('drop_attributes')
|
||||
->normalizeKeys(false)
|
||||
->useAttributeAsKey('name')
|
||||
->variablePrototype()
|
||||
->beforeNormalization()
|
||||
->ifArray()->then(static fn ($n) => $n['element'] ?? $n)
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->scalarNode('default_code_language')->defaultValue('')->end()
|
||||
->arrayNode('themes')
|
||||
->defaultValue([])
|
||||
->arrayPrototype()
|
||||
->beforeNormalization()
|
||||
->ifTrue(static fn ($v) => !is_array($v) || !isset($v['templates']))
|
||||
->then(static fn (string $v) => ['templates' => (array) $v])
|
||||
->end()
|
||||
->children()
|
||||
->scalarNode('extends')->end()
|
||||
->arrayNode('templates')
|
||||
->isRequired()
|
||||
->cannotBeEmpty()
|
||||
->scalarPrototype()->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end();
|
||||
|
||||
return $treeBuilder;
|
||||
}
|
||||
|
||||
/** @param mixed[] $configs */
|
||||
public function load(array $configs, ContainerBuilder $container): void
|
||||
{
|
||||
$configuration = $this->getConfiguration($configs, $container);
|
||||
$config = $this->processConfiguration($configuration, $configs);
|
||||
$loader = new PhpFileLoader(
|
||||
$container,
|
||||
new FileLocator(dirname(__DIR__, 2) . '/resources/config'),
|
||||
);
|
||||
|
||||
$loader->load('command_bus.php');
|
||||
$loader->load('guides.php');
|
||||
|
||||
$projectSettings = new ProjectSettings();
|
||||
if (isset($config['project'])) {
|
||||
if (isset($config['project']['version'])) {
|
||||
$projectSettings->setVersion((string) $config['project']['version']);
|
||||
}
|
||||
|
||||
if (isset($config['project']['title'])) {
|
||||
$projectSettings->setTitle((string) $config['project']['title']);
|
||||
}
|
||||
|
||||
if (isset($config['project']['release'])) {
|
||||
$projectSettings->setRelease((string) $config['project']['release']);
|
||||
}
|
||||
|
||||
if (isset($config['project']['copyright'])) {
|
||||
$projectSettings->setCopyright((string) $config['project']['copyright']);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($config['inventories'])) {
|
||||
$projectSettings->setInventories($config['inventories']);
|
||||
}
|
||||
|
||||
if (isset($config['theme'])) {
|
||||
$projectSettings->setTheme((string) $config['theme']);
|
||||
}
|
||||
|
||||
if (isset($config['input'])) {
|
||||
$projectSettings->setInput((string) $config['input']);
|
||||
}
|
||||
|
||||
if (isset($config['input_file']) && $config['input_file'] !== '') {
|
||||
$inputFile = (string) $config['input_file'];
|
||||
$pathInfo = pathinfo($inputFile);
|
||||
$projectSettings->setInputFile($pathInfo['filename']);
|
||||
if (!empty($pathInfo['extension'])) {
|
||||
$projectSettings->setInputFormat($pathInfo['extension']);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($config['index_name']) && $config['index_name'] !== '') {
|
||||
$projectSettings->setIndexName((string) $config['index_name']);
|
||||
}
|
||||
|
||||
if (isset($config['output'])) {
|
||||
$projectSettings->setOutput((string) $config['output']);
|
||||
}
|
||||
|
||||
if (isset($config['input_format'])) {
|
||||
$projectSettings->setInputFormat((string) $config['input_format']);
|
||||
}
|
||||
|
||||
if (isset($config['output_format']) && is_array($config['output_format'])) {
|
||||
$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']);
|
||||
}
|
||||
|
||||
if (isset($config['show_progress'])) {
|
||||
$projectSettings->setShowProgressBar((bool) $config['show_progress']);
|
||||
}
|
||||
|
||||
if (isset($config['fail_on_error'])) {
|
||||
$projectSettings->setFailOnError(LogLevel::ERROR);
|
||||
}
|
||||
|
||||
if (isset($config['fail_on_log'])) {
|
||||
$projectSettings->setFailOnError(LogLevel::WARNING);
|
||||
}
|
||||
|
||||
if (isset($config['max_menu_depth'])) {
|
||||
$projectSettings->setMaxMenuDepth((int) $config['max_menu_depth']);
|
||||
}
|
||||
|
||||
if (isset($config['automatic_menu'])) {
|
||||
$projectSettings->setAutomaticMenu((bool) $config['automatic_menu']);
|
||||
}
|
||||
|
||||
if (isset($config['default_code_language'])) {
|
||||
$projectSettings->setDefaultCodeLanguage((string) $config['default_code_language']);
|
||||
}
|
||||
|
||||
$projectSettings->setExcludes(
|
||||
new Exclude(
|
||||
$config['exclude']['paths'],
|
||||
$config['exclude']['hidden'],
|
||||
$config['exclude']['symlinks'],
|
||||
),
|
||||
);
|
||||
|
||||
$container->getDefinition(SettingsManager::class)
|
||||
->addMethodCall('setProjectSettings', [$projectSettings]);
|
||||
|
||||
$config['base_template_paths'][] = dirname(__DIR__, 2) . '/resources/template/html';
|
||||
$config['base_template_paths'][] = dirname(__DIR__, 2) . '/resources/template/tex';
|
||||
$container->setParameter('phpdoc.guides.base_template_paths', $config['base_template_paths']);
|
||||
$container->setParameter('phpdoc.guides.node_templates', $config['templates']);
|
||||
$container->setParameter('phpdoc.guides.inventories', $config['inventories']);
|
||||
$container->setParameter('phpdoc.guides.raw_node.escape', $config['raw_node']['escape'] ?? false);
|
||||
|
||||
if ($config['raw_node'] ?? false) {
|
||||
$this->configureSanitizers($config['raw_node'], $container);
|
||||
}
|
||||
|
||||
foreach ($config['themes'] as $themeName => $themeConfig) {
|
||||
$container->getDefinition(ThemeManager::class)
|
||||
->addMethodCall('registerTheme', [new ThemeConfig($themeName, $themeConfig['templates'], $themeConfig['extends'] ?? null)]);
|
||||
}
|
||||
}
|
||||
|
||||
/** @param array<string> $defaultValue */
|
||||
private function paths(array $defaultValue = []): ArrayNodeDefinition
|
||||
{
|
||||
$treebuilder = new TreeBuilder('paths');
|
||||
|
||||
return $treebuilder->getRootNode()
|
||||
->beforeNormalization()
|
||||
->castToArray()
|
||||
->end()
|
||||
->defaultValue($defaultValue)
|
||||
->prototype('scalar')
|
||||
->end();
|
||||
}
|
||||
|
||||
public function process(ContainerBuilder $container): void
|
||||
{
|
||||
(new ParserRulesPass())->process($container);
|
||||
(new NodeRendererPass())->process($container);
|
||||
(new RendererPass())->process($container);
|
||||
}
|
||||
|
||||
/** @param mixed[] $config */
|
||||
public function getConfiguration(array $config, ContainerBuilder $container): ConfigurationInterface
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function prepend(ContainerBuilder $container): void
|
||||
{
|
||||
$container->prependExtensionConfig(
|
||||
'guides',
|
||||
[
|
||||
'templates' => array_merge(
|
||||
templateArray(
|
||||
require dirname(__DIR__, 2) . '/resources/template/html/template.php',
|
||||
'html',
|
||||
),
|
||||
templateArray(
|
||||
require dirname(__DIR__, 2) . '/resources/template/tex/template.php',
|
||||
'tex',
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/** @param array<string, mixed> $rawNodeConfig */
|
||||
private function configureSanitizers(array $rawNodeConfig, ContainerBuilder $container): void
|
||||
{
|
||||
if ($rawNodeConfig['sanitizer_name'] ?? false) {
|
||||
$container->getDefinition(RawNodeEscapeTransformer::class)
|
||||
->setArgument('$htmlSanitizerConfig', new Reference('phpdoc.guides.raw_node.sanitizer.' . $rawNodeConfig['sanitizer_name']));
|
||||
}
|
||||
|
||||
if (!is_array($rawNodeConfig['sanitizers'] ?? false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($rawNodeConfig['sanitizers'] as $sanitizerName => $sanitizerConfig) {
|
||||
$def = $container->register('phpdoc.guides.raw_node.sanitizer.' . $sanitizerName, HtmlSanitizerConfig::class);
|
||||
|
||||
// Base
|
||||
if ($sanitizerConfig['allow_safe_elements']) {
|
||||
$def->addMethodCall('allowSafeElements', [], true);
|
||||
}
|
||||
|
||||
if ($sanitizerConfig['allow_static_elements']) {
|
||||
$def->addMethodCall('allowStaticElements', [], true);
|
||||
}
|
||||
|
||||
// Configures elements
|
||||
foreach ($sanitizerConfig['allow_elements'] as $element => $attributes) {
|
||||
$def->addMethodCall('allowElement', [$element, $attributes], true);
|
||||
}
|
||||
|
||||
foreach ($sanitizerConfig['block_elements'] as $element) {
|
||||
$def->addMethodCall('blockElement', [$element], true);
|
||||
}
|
||||
|
||||
foreach ($sanitizerConfig['drop_elements'] as $element) {
|
||||
$def->addMethodCall('dropElement', [$element], true);
|
||||
}
|
||||
|
||||
// Configures attributes
|
||||
foreach ($sanitizerConfig['allow_attributes'] as $attribute => $elements) {
|
||||
$def->addMethodCall('allowAttribute', [$attribute, $elements], true);
|
||||
}
|
||||
|
||||
foreach ($sanitizerConfig['drop_attributes'] as $attribute => $elements) {
|
||||
$def->addMethodCall('dropAttribute', [$attribute, $elements], true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to configure multiple templates.
|
||||
*
|
||||
* This function is used to configure the templates in the configuration file.
|
||||
*
|
||||
* @param array<class-string<Node>, string> $input
|
||||
*
|
||||
* @return array<array-key, array{node: class-string<Node>, file: string, format: string}>
|
||||
*/
|
||||
function templateArray(array $input, string $format = 'html'): array
|
||||
{
|
||||
return array_map(
|
||||
static fn ($node, $template) => template($node, $template, $format),
|
||||
array_keys($input),
|
||||
array_values($input),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to configure templates.
|
||||
*
|
||||
* This function is used to configure the templates in the configuration file.
|
||||
*
|
||||
* @param class-string<Node> $node
|
||||
*
|
||||
* @return array{node: class-string<Node>, file: string, format: string}
|
||||
*/
|
||||
function template(string $node, string $template, string $format = 'html'): array
|
||||
{
|
||||
return [
|
||||
'node' => $node,
|
||||
'file' => $template,
|
||||
'format' => $format,
|
||||
];
|
||||
}
|
||||
48
vendor/phpdocumentor/guides/src/DependencyInjection/TestExtension.php
vendored
Normal file
48
vendor/phpdocumentor/guides/src/DependencyInjection/TestExtension.php
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\DependencyInjection;
|
||||
|
||||
use Monolog\Handler\TestHandler;
|
||||
use Monolog\Logger;
|
||||
use phpDocumentor\Guides\Compiler\Compiler;
|
||||
use phpDocumentor\Guides\Parser;
|
||||
use Psr\Clock\ClockInterface;
|
||||
use Symfony\Component\Clock\MockClock;
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Extension\Extension;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
final class TestExtension extends Extension implements CompilerPassInterface
|
||||
{
|
||||
/** @param array<mixed> $configs */
|
||||
public function load(array $configs, ContainerBuilder $container): void
|
||||
{
|
||||
}
|
||||
|
||||
public function process(ContainerBuilder $container): void
|
||||
{
|
||||
$container->getDefinition(Parser::class)->setPublic(true);
|
||||
$container->getDefinition(Compiler::class)->setPublic(true);
|
||||
$container->getDefinition('phpdoc.guides.output_node_renderer')->setPublic(true);
|
||||
|
||||
$clockDefinition = new Definition(MockClock::class, ['2023-01-01 12:00:00']);
|
||||
$container->setDefinition(ClockInterface::class, $clockDefinition);
|
||||
|
||||
$container->register(TestHandler::class, TestHandler::class)->setPublic(true);
|
||||
$container->getDefinition(Logger::class)
|
||||
->addMethodCall('pushHandler', [new Reference(TestHandler::class)]);
|
||||
}
|
||||
}
|
||||
53
vendor/phpdocumentor/guides/src/Event/ModifyDocumentEntryAdditionalData.php
vendored
Normal file
53
vendor/phpdocumentor/guides/src/Event/ModifyDocumentEntryAdditionalData.php
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Event;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContextInterface;
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
|
||||
final class ModifyDocumentEntryAdditionalData
|
||||
{
|
||||
/** @param array<string, Node> $additionalData */
|
||||
public function __construct(
|
||||
private array $additionalData,
|
||||
private readonly DocumentNode $documentNode,
|
||||
private readonly CompilerContextInterface $compilerContext,
|
||||
) {
|
||||
}
|
||||
|
||||
/** @return array<string, Node> */
|
||||
public function getAdditionalData(): array
|
||||
{
|
||||
return $this->additionalData;
|
||||
}
|
||||
|
||||
/** @param array<string, Node> $additionalData */
|
||||
public function setAdditionalData(array $additionalData): ModifyDocumentEntryAdditionalData
|
||||
{
|
||||
$this->additionalData = $additionalData;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDocumentNode(): DocumentNode
|
||||
{
|
||||
return $this->documentNode;
|
||||
}
|
||||
|
||||
public function getCompilerContext(): CompilerContextInterface
|
||||
{
|
||||
return $this->compilerContext;
|
||||
}
|
||||
}
|
||||
47
vendor/phpdocumentor/guides/src/Event/PostCollectFilesForParsingEvent.php
vendored
Normal file
47
vendor/phpdocumentor/guides/src/Event/PostCollectFilesForParsingEvent.php
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Event;
|
||||
|
||||
use phpDocumentor\Guides\Files;
|
||||
use phpDocumentor\Guides\Handlers\ParseDirectoryCommand;
|
||||
|
||||
/**
|
||||
* This event is called after all files have been collected for parsing
|
||||
* But before the actual parsing begins.
|
||||
*
|
||||
* It can be used to manipulate the files to be parsed.
|
||||
*/
|
||||
final class PostCollectFilesForParsingEvent
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ParseDirectoryCommand $command,
|
||||
private Files $files,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getCommand(): ParseDirectoryCommand
|
||||
{
|
||||
return $this->command;
|
||||
}
|
||||
|
||||
public function getFiles(): Files
|
||||
{
|
||||
return $this->files;
|
||||
}
|
||||
|
||||
public function setFiles(Files $files): void
|
||||
{
|
||||
$this->files = $files;
|
||||
}
|
||||
}
|
||||
51
vendor/phpdocumentor/guides/src/Event/PostParseDocument.php
vendored
Normal file
51
vendor/phpdocumentor/guides/src/Event/PostParseDocument.php
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Event;
|
||||
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
|
||||
/**
|
||||
* This event is called after the parsing of each document is completed by the responsible extension.
|
||||
*
|
||||
* It can for example be used to display a progress bar.
|
||||
*/
|
||||
final class PostParseDocument
|
||||
{
|
||||
public function __construct(
|
||||
private readonly string $fileName,
|
||||
private DocumentNode|null $documentNode,
|
||||
private readonly string $originalFile,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getDocumentNode(): DocumentNode|null
|
||||
{
|
||||
return $this->documentNode;
|
||||
}
|
||||
|
||||
public function setDocumentNode(DocumentNode|null $documentNode): void
|
||||
{
|
||||
$this->documentNode = $documentNode;
|
||||
}
|
||||
|
||||
public function getFileName(): string
|
||||
{
|
||||
return $this->fileName;
|
||||
}
|
||||
|
||||
public function getOriginalFileName(): string
|
||||
{
|
||||
return $this->originalFile;
|
||||
}
|
||||
}
|
||||
43
vendor/phpdocumentor/guides/src/Event/PostParseProcess.php
vendored
Normal file
43
vendor/phpdocumentor/guides/src/Event/PostParseProcess.php
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Event;
|
||||
|
||||
use phpDocumentor\Guides\Handlers\ParseDirectoryCommand;
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
|
||||
/**
|
||||
* This event is dispatched right after the overall parsing process is
|
||||
* finished, Before the compiler passes, including the node transformers
|
||||
* are called.
|
||||
*/
|
||||
final class PostParseProcess
|
||||
{
|
||||
/** @param DocumentNode[] $documents */
|
||||
public function __construct(
|
||||
private readonly ParseDirectoryCommand $parseDirectoryCommand,
|
||||
private readonly array $documents,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getParseDirectoryCommand(): ParseDirectoryCommand
|
||||
{
|
||||
return $this->parseDirectoryCommand;
|
||||
}
|
||||
|
||||
/** @return DocumentNode[] */
|
||||
public function getDocuments(): array
|
||||
{
|
||||
return $this->documents;
|
||||
}
|
||||
}
|
||||
46
vendor/phpdocumentor/guides/src/Event/PostProjectNodeCreated.php
vendored
Normal file
46
vendor/phpdocumentor/guides/src/Event/PostProjectNodeCreated.php
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Event;
|
||||
|
||||
use phpDocumentor\Guides\Nodes\ProjectNode;
|
||||
use phpDocumentor\Guides\Settings\ProjectSettings;
|
||||
|
||||
final class PostProjectNodeCreated
|
||||
{
|
||||
public function __construct(
|
||||
private ProjectNode $projectNode,
|
||||
private ProjectSettings $settings,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getProjectNode(): ProjectNode
|
||||
{
|
||||
return $this->projectNode;
|
||||
}
|
||||
|
||||
public function setProjectNode(ProjectNode $projectNode): void
|
||||
{
|
||||
$this->projectNode = $projectNode;
|
||||
}
|
||||
|
||||
public function getSettings(): ProjectSettings
|
||||
{
|
||||
return $this->settings;
|
||||
}
|
||||
|
||||
public function setSettings(ProjectSettings $settings): void
|
||||
{
|
||||
$this->settings = $settings;
|
||||
}
|
||||
}
|
||||
44
vendor/phpdocumentor/guides/src/Event/PostRenderDocument.php
vendored
Normal file
44
vendor/phpdocumentor/guides/src/Event/PostRenderDocument.php
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Event;
|
||||
|
||||
use phpDocumentor\Guides\Handlers\RenderDocumentCommand;
|
||||
use phpDocumentor\Guides\NodeRenderers\NodeRenderer;
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
|
||||
/**
|
||||
* This event is called after the rendering of each document.
|
||||
*
|
||||
* It can for example be used to display a progress bar or to post-process the rendered documents one by one.
|
||||
*/
|
||||
final class PostRenderDocument
|
||||
{
|
||||
/** @param NodeRenderer<DocumentNode> $renderer */
|
||||
public function __construct(
|
||||
private readonly NodeRenderer $renderer,
|
||||
private readonly RenderDocumentCommand $command,
|
||||
) {
|
||||
}
|
||||
|
||||
/** @return NodeRenderer<DocumentNode> */
|
||||
public function getRenderer(): NodeRenderer
|
||||
{
|
||||
return $this->renderer;
|
||||
}
|
||||
|
||||
public function getCommand(): RenderDocumentCommand
|
||||
{
|
||||
return $this->command;
|
||||
}
|
||||
}
|
||||
33
vendor/phpdocumentor/guides/src/Event/PostRenderProcess.php
vendored
Normal file
33
vendor/phpdocumentor/guides/src/Event/PostRenderProcess.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Event;
|
||||
|
||||
use phpDocumentor\Guides\Handlers\RenderCommand;
|
||||
|
||||
/**
|
||||
* This event is called once after each rendering method after all documents have been rendered.
|
||||
*
|
||||
* It can for example be used to copy assets into the target directory after rendering.
|
||||
*/
|
||||
final class PostRenderProcess
|
||||
{
|
||||
public function __construct(private readonly RenderCommand $command)
|
||||
{
|
||||
}
|
||||
|
||||
public function getCommand(): RenderCommand
|
||||
{
|
||||
return $this->command;
|
||||
}
|
||||
}
|
||||
48
vendor/phpdocumentor/guides/src/Event/PreParseDocument.php
vendored
Normal file
48
vendor/phpdocumentor/guides/src/Event/PreParseDocument.php
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Event;
|
||||
|
||||
use phpDocumentor\Guides\Parser;
|
||||
|
||||
/**
|
||||
* This event is called before the parsing of each document is passed to the responsible extension.
|
||||
*
|
||||
* It can be used to manipulate the content passed to the parser by calling PreParseDocument::setContents
|
||||
*/
|
||||
final class PreParseDocument
|
||||
{
|
||||
public function __construct(private readonly Parser $parser, private readonly string $fileName, private string $contents)
|
||||
{
|
||||
}
|
||||
|
||||
public function getParser(): Parser
|
||||
{
|
||||
return $this->parser;
|
||||
}
|
||||
|
||||
public function setContents(string $contents): void
|
||||
{
|
||||
$this->contents = $contents;
|
||||
}
|
||||
|
||||
public function getContents(): string
|
||||
{
|
||||
return $this->contents;
|
||||
}
|
||||
|
||||
public function getFileName(): string
|
||||
{
|
||||
return $this->fileName;
|
||||
}
|
||||
}
|
||||
43
vendor/phpdocumentor/guides/src/Event/PreParseProcess.php
vendored
Normal file
43
vendor/phpdocumentor/guides/src/Event/PreParseProcess.php
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Event;
|
||||
|
||||
use phpDocumentor\Guides\Handlers\ParseDirectoryCommand;
|
||||
|
||||
/**
|
||||
* This event is dispatched right before the overall parsing process is
|
||||
* started.
|
||||
*
|
||||
* It can be used to modify the ParseDirectoryCommand, so it could be used to alter the
|
||||
* directory to be parsed or the file system to be used.
|
||||
*/
|
||||
final class PreParseProcess
|
||||
{
|
||||
public function __construct(
|
||||
private ParseDirectoryCommand $parseDirectoryCommand,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getParseDirectoryCommand(): ParseDirectoryCommand
|
||||
{
|
||||
return $this->parseDirectoryCommand;
|
||||
}
|
||||
|
||||
public function setParseDirectoryCommand(ParseDirectoryCommand $parseDirectoryCommand): PreParseProcess
|
||||
{
|
||||
$this->parseDirectoryCommand = $parseDirectoryCommand;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
40
vendor/phpdocumentor/guides/src/Event/PreRenderDocument.php
vendored
Normal file
40
vendor/phpdocumentor/guides/src/Event/PreRenderDocument.php
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Event;
|
||||
|
||||
use phpDocumentor\Guides\Handlers\RenderDocumentCommand;
|
||||
use phpDocumentor\Guides\NodeRenderers\NodeRenderer;
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
|
||||
/**
|
||||
* This event is called before the rendering of each document.
|
||||
*/
|
||||
final class PreRenderDocument
|
||||
{
|
||||
/** @param NodeRenderer<DocumentNode> $renderer */
|
||||
public function __construct(private readonly NodeRenderer $renderer, private readonly RenderDocumentCommand $command)
|
||||
{
|
||||
}
|
||||
|
||||
/** @return NodeRenderer<DocumentNode> */
|
||||
public function getRenderer(): NodeRenderer
|
||||
{
|
||||
return $this->renderer;
|
||||
}
|
||||
|
||||
public function getCommand(): RenderDocumentCommand
|
||||
{
|
||||
return $this->command;
|
||||
}
|
||||
}
|
||||
56
vendor/phpdocumentor/guides/src/Event/PreRenderProcess.php
vendored
Normal file
56
vendor/phpdocumentor/guides/src/Event/PreRenderProcess.php
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Event;
|
||||
|
||||
use phpDocumentor\Guides\Handlers\RenderCommand;
|
||||
|
||||
/**
|
||||
* This event is called once before each rendering method after all documents have been parsed and
|
||||
* all compiler passes (including node transformers have been called.)
|
||||
*
|
||||
* It can be used to exit the rendering process before anything was rendered. A third party extension could then
|
||||
* take over the rendering with its own means.
|
||||
*/
|
||||
final class PreRenderProcess
|
||||
{
|
||||
private bool $exitRendering = false;
|
||||
|
||||
public function __construct(
|
||||
private readonly RenderCommand $command,
|
||||
private readonly int $steps = 1,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getCommand(): RenderCommand
|
||||
{
|
||||
return $this->command;
|
||||
}
|
||||
|
||||
public function isExitRendering(): bool
|
||||
{
|
||||
return $this->exitRendering;
|
||||
}
|
||||
|
||||
public function setExitRendering(bool $exitRendering): PreRenderProcess
|
||||
{
|
||||
$this->exitRendering = $exitRendering;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSteps(): int
|
||||
{
|
||||
return $this->steps;
|
||||
}
|
||||
}
|
||||
58
vendor/phpdocumentor/guides/src/EventListener/LoadSettingsFromComposer.php
vendored
Normal file
58
vendor/phpdocumentor/guides/src/EventListener/LoadSettingsFromComposer.php
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\EventListener;
|
||||
|
||||
use phpDocumentor\Guides\Event\PostProjectNodeCreated;
|
||||
use phpDocumentor\Guides\Settings\ComposerSettingsLoader;
|
||||
|
||||
use function dirname;
|
||||
use function file_exists;
|
||||
use function getcwd;
|
||||
use function is_string;
|
||||
|
||||
final class LoadSettingsFromComposer
|
||||
{
|
||||
public function __construct(private readonly ComposerSettingsLoader $composerSettingsLoader)
|
||||
{
|
||||
}
|
||||
|
||||
public function __invoke(PostProjectNodeCreated $event): void
|
||||
{
|
||||
$workDir = getcwd();
|
||||
if ($workDir === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
$composerjson = $this->findComposerJson($workDir);
|
||||
if (!is_string($composerjson)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$projectNode = $event->getProjectNode();
|
||||
$settings = $event->getSettings();
|
||||
|
||||
$this->composerSettingsLoader->loadSettings($projectNode, $settings, $composerjson);
|
||||
}
|
||||
|
||||
private function findComposerJson(string $currentDir): string|null
|
||||
{
|
||||
// Navigate up the directory structure until finding the composer.json file
|
||||
while (!file_exists($currentDir . '/composer.json') && $currentDir !== '/') {
|
||||
$currentDir = dirname($currentDir);
|
||||
}
|
||||
|
||||
// If found, return the path to the composer.json file; otherwise, return null
|
||||
return file_exists($currentDir . '/composer.json') ? $currentDir . '/composer.json' : null;
|
||||
}
|
||||
}
|
||||
20
vendor/phpdocumentor/guides/src/Exception/DocumentEntryNotFound.php
vendored
Normal file
20
vendor/phpdocumentor/guides/src/Exception/DocumentEntryNotFound.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Exception;
|
||||
|
||||
use Exception;
|
||||
|
||||
final class DocumentEntryNotFound extends Exception
|
||||
{
|
||||
}
|
||||
20
vendor/phpdocumentor/guides/src/Exception/DuplicateLinkAnchorException.php
vendored
Normal file
20
vendor/phpdocumentor/guides/src/Exception/DuplicateLinkAnchorException.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Exception;
|
||||
|
||||
use Exception;
|
||||
|
||||
final class DuplicateLinkAnchorException extends Exception
|
||||
{
|
||||
}
|
||||
20
vendor/phpdocumentor/guides/src/Exception/InvalidTableStructure.php
vendored
Normal file
20
vendor/phpdocumentor/guides/src/Exception/InvalidTableStructure.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Exception;
|
||||
|
||||
use Exception;
|
||||
|
||||
final class InvalidTableStructure extends Exception
|
||||
{
|
||||
}
|
||||
140
vendor/phpdocumentor/guides/src/FileCollector.php
vendored
Normal file
140
vendor/phpdocumentor/guides/src/FileCollector.php
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides;
|
||||
|
||||
use Doctrine\Deprecations\Deprecation;
|
||||
use Flyfinder\Specification\AndSpecification;
|
||||
use Flyfinder\Specification\HasExtension;
|
||||
use Flyfinder\Specification\InPath;
|
||||
use Flyfinder\Specification\NotSpecification;
|
||||
use Flyfinder\Specification\SpecificationInterface;
|
||||
use InvalidArgumentException;
|
||||
use League\Flysystem\FilesystemInterface;
|
||||
use phpDocumentor\FileSystem\FileSystem;
|
||||
use phpDocumentor\FileSystem\Finder\Exclude;
|
||||
use phpDocumentor\FileSystem\Finder\SpecificationFactory;
|
||||
use phpDocumentor\FileSystem\Finder\SpecificationFactoryInterface;
|
||||
use phpDocumentor\FileSystem\Path;
|
||||
|
||||
use function sprintf;
|
||||
use function strlen;
|
||||
use function substr;
|
||||
use function trim;
|
||||
|
||||
final class FileCollector
|
||||
{
|
||||
/** @var string[][] */
|
||||
private array $fileInfos = [];
|
||||
private SpecificationFactoryInterface $specificationFactory;
|
||||
|
||||
public function __construct(SpecificationFactoryInterface|null $specificationFactory = null)
|
||||
{
|
||||
$this->specificationFactory = $specificationFactory ?? new SpecificationFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans a directory recursively looking for all files to parse.
|
||||
*
|
||||
* This takes into account the presence of cached & fresh MetaEntry
|
||||
* objects, and avoids adding files to the parse queue that have
|
||||
* not changed and whose direct dependencies have not changed.
|
||||
*
|
||||
* @param SpecificationInterface|Exclude|null $excludedSpecification specification that is used to exclude specific files/directories.
|
||||
* Passing a {@see SpecificationInterface} is deprecated, use {@see Exclude} instead.
|
||||
*/
|
||||
public function collect(FilesystemInterface|FileSystem $filesystem, string $directory, string $extension, SpecificationInterface|Exclude|null $excludedSpecification = null): Files
|
||||
{
|
||||
if ($excludedSpecification instanceof SpecificationInterface) {
|
||||
Deprecation::triggerIfCalledFromOutside(
|
||||
'phpdocumentor/guides',
|
||||
'https://github.com/phpDocumentor/guides/issues/1209',
|
||||
'Passing %s to %s::collect() is deprecated, use %s instead.',
|
||||
$excludedSpecification::class,
|
||||
self::class,
|
||||
Exclude::class,
|
||||
);
|
||||
}
|
||||
|
||||
$directory = trim($directory, '/');
|
||||
$specification = $this->getSpecification($excludedSpecification, $directory, $extension);
|
||||
|
||||
/** @var array<array<string>> $files */
|
||||
$files = $filesystem->find($specification);
|
||||
|
||||
// completely populate the splFileInfos property
|
||||
$this->fileInfos = [];
|
||||
foreach ($files as $fileInfo) {
|
||||
$dirname = $fileInfo['dirname'];
|
||||
|
||||
if (strlen($directory) > 0) {
|
||||
// Make paths relative to the provided source folder
|
||||
$dirname = substr($fileInfo['dirname'], strlen($directory) + 1) ?: '';
|
||||
}
|
||||
|
||||
$documentPath = $this->getFilenameFromFile($fileInfo['filename'], $dirname);
|
||||
|
||||
$this->fileInfos[$documentPath] = $fileInfo;
|
||||
}
|
||||
|
||||
$parseQueue = new Files();
|
||||
foreach ($this->fileInfos as $filename => $_fileInfo) {
|
||||
if (!$this->doesFileRequireParsing((string) $filename)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$parseQueue->add((string) $filename);
|
||||
}
|
||||
|
||||
return $parseQueue;
|
||||
}
|
||||
|
||||
private function doesFileRequireParsing(string $filename): bool
|
||||
{
|
||||
if (!isset($this->fileInfos[$filename])) {
|
||||
throw new InvalidArgumentException(
|
||||
sprintf('No file info found for "%s" - file does not exist.', $filename),
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts foo/bar.rst to foo/bar (the document filename)
|
||||
*/
|
||||
private function getFilenameFromFile(string $filename, string $dirname): string
|
||||
{
|
||||
$directory = $dirname ? $dirname . '/' : '';
|
||||
|
||||
return $directory . $filename;
|
||||
}
|
||||
|
||||
private function getSpecification(Exclude|SpecificationInterface|null $excludedSpecification, string $directory, string $extension): SpecificationInterface
|
||||
{
|
||||
if ($excludedSpecification instanceof Exclude) {
|
||||
if ($directory === '') {
|
||||
$directory = new Path('./');
|
||||
}
|
||||
|
||||
return $this->specificationFactory->create([$directory], $excludedSpecification, [$extension]);
|
||||
}
|
||||
|
||||
$specification = new AndSpecification(new InPath(new \Flyfinder\Path($directory)), new HasExtension([$extension]));
|
||||
if ($excludedSpecification) {
|
||||
$specification = new AndSpecification($specification, new NotSpecification($excludedSpecification));
|
||||
}
|
||||
|
||||
return $specification;
|
||||
}
|
||||
}
|
||||
55
vendor/phpdocumentor/guides/src/Files.php
vendored
Normal file
55
vendor/phpdocumentor/guides/src/Files.php
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides;
|
||||
|
||||
use ArrayIterator;
|
||||
use Countable;
|
||||
use Iterator;
|
||||
use IteratorAggregate;
|
||||
|
||||
use function array_key_exists;
|
||||
use function count;
|
||||
use function sort;
|
||||
|
||||
use const SORT_FLAG_CASE;
|
||||
use const SORT_NATURAL;
|
||||
|
||||
/** @implements IteratorAggregate<string> */
|
||||
final class Files implements IteratorAggregate, Countable
|
||||
{
|
||||
/** @var string[] */
|
||||
private array $files = [];
|
||||
|
||||
public function add(string $filename): void
|
||||
{
|
||||
if (array_key_exists($filename, $this->files)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->files[$filename] = $filename;
|
||||
}
|
||||
|
||||
/** @return Iterator<string> */
|
||||
public function getIterator(): Iterator
|
||||
{
|
||||
sort($this->files, SORT_NATURAL | SORT_FLAG_CASE);
|
||||
|
||||
return new ArrayIterator($this->files);
|
||||
}
|
||||
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->files);
|
||||
}
|
||||
}
|
||||
38
vendor/phpdocumentor/guides/src/Handlers/CompileDocumentsCommand.php
vendored
Normal file
38
vendor/phpdocumentor/guides/src/Handlers/CompileDocumentsCommand.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Handlers;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\CompilerContext;
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
|
||||
final class CompileDocumentsCommand
|
||||
{
|
||||
/** @param DocumentNode[] $documents */
|
||||
public function __construct(
|
||||
private readonly array $documents,
|
||||
private readonly CompilerContext $compilerContext,
|
||||
) {
|
||||
}
|
||||
|
||||
/** @return DocumentNode[] */
|
||||
public function getDocuments(): array
|
||||
{
|
||||
return $this->documents;
|
||||
}
|
||||
|
||||
public function getCompilerContext(): CompilerContext
|
||||
{
|
||||
return $this->compilerContext;
|
||||
}
|
||||
}
|
||||
30
vendor/phpdocumentor/guides/src/Handlers/CompileDocumentsHandler.php
vendored
Normal file
30
vendor/phpdocumentor/guides/src/Handlers/CompileDocumentsHandler.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Handlers;
|
||||
|
||||
use phpDocumentor\Guides\Compiler\Compiler;
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
|
||||
final class CompileDocumentsHandler
|
||||
{
|
||||
public function __construct(private readonly Compiler $compiler)
|
||||
{
|
||||
}
|
||||
|
||||
/** @return DocumentNode[] */
|
||||
public function handle(CompileDocumentsCommand $command): array
|
||||
{
|
||||
return $this->compiler->run($command->getDocuments(), $command->getCompilerContext());
|
||||
}
|
||||
}
|
||||
31
vendor/phpdocumentor/guides/src/Handlers/LoadCacheCommand.php
vendored
Normal file
31
vendor/phpdocumentor/guides/src/Handlers/LoadCacheCommand.php
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Handlers;
|
||||
|
||||
final class LoadCacheCommand
|
||||
{
|
||||
public function __construct(private readonly string $cacheDirectory, private readonly bool $useCaching = true)
|
||||
{
|
||||
}
|
||||
|
||||
public function getCacheDirectory(): string
|
||||
{
|
||||
return $this->cacheDirectory;
|
||||
}
|
||||
|
||||
public function useCaching(): bool
|
||||
{
|
||||
return $this->useCaching;
|
||||
}
|
||||
}
|
||||
26
vendor/phpdocumentor/guides/src/Handlers/LoadCacheHandler.php
vendored
Normal file
26
vendor/phpdocumentor/guides/src/Handlers/LoadCacheHandler.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Handlers;
|
||||
|
||||
final class LoadCacheHandler
|
||||
{
|
||||
public function handle(LoadCacheCommand $command): void
|
||||
{
|
||||
if (!$command->useCaching()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO:: Load Cache
|
||||
}
|
||||
}
|
||||
99
vendor/phpdocumentor/guides/src/Handlers/ParseDirectoryCommand.php
vendored
Normal file
99
vendor/phpdocumentor/guides/src/Handlers/ParseDirectoryCommand.php
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Handlers;
|
||||
|
||||
use Doctrine\Deprecations\Deprecation;
|
||||
use Flyfinder\Specification\SpecificationInterface;
|
||||
use League\Flysystem\FilesystemInterface;
|
||||
use phpDocumentor\FileSystem\FileSystem;
|
||||
use phpDocumentor\FileSystem\Finder\Exclude;
|
||||
use phpDocumentor\Guides\Nodes\ProjectNode;
|
||||
|
||||
final class ParseDirectoryCommand
|
||||
{
|
||||
private readonly SpecificationInterface|null $excludedSpecification;
|
||||
private readonly Exclude|null $exclude;
|
||||
|
||||
public function __construct(
|
||||
private readonly FilesystemInterface|FileSystem $origin,
|
||||
private readonly string $directory,
|
||||
private readonly string $inputFormat,
|
||||
private readonly ProjectNode $projectNode,
|
||||
SpecificationInterface|Exclude|null $excludedSpecification = null,
|
||||
) {
|
||||
if ($excludedSpecification instanceof SpecificationInterface) {
|
||||
Deprecation::trigger(
|
||||
'phpdocumentor/guides',
|
||||
'https://github.com/phpDocumentor/guides/issues/1209',
|
||||
'Passing %s to %s is deprecated, use %s instead.',
|
||||
$excludedSpecification::class,
|
||||
self::class,
|
||||
Exclude::class,
|
||||
);
|
||||
$this->excludedSpecification = $excludedSpecification;
|
||||
$this->exclude = null;
|
||||
} else {
|
||||
$this->exclude = $excludedSpecification;
|
||||
$this->excludedSpecification = null;
|
||||
}
|
||||
}
|
||||
|
||||
public function getOrigin(): FilesystemInterface|FileSystem
|
||||
{
|
||||
return $this->origin;
|
||||
}
|
||||
|
||||
public function getDirectory(): string
|
||||
{
|
||||
return $this->directory;
|
||||
}
|
||||
|
||||
public function getInputFormat(): string
|
||||
{
|
||||
return $this->inputFormat;
|
||||
}
|
||||
|
||||
public function getProjectNode(): ProjectNode
|
||||
{
|
||||
return $this->projectNode;
|
||||
}
|
||||
|
||||
/** @deprecated Specification definition on parse directory is deprecated. Use {@see self::getExclude()} instead. */
|
||||
public function getExcludedSpecification(): SpecificationInterface|null
|
||||
{
|
||||
Deprecation::triggerIfCalledFromOutside(
|
||||
'phpdocumentor/guides',
|
||||
'https://github.com/phpDocumentor/guides/issues/1209',
|
||||
'Specification definition on parse directory is deprecated. Use getExclude() instead.',
|
||||
);
|
||||
|
||||
return $this->excludedSpecification;
|
||||
}
|
||||
|
||||
public function getExclude(): Exclude
|
||||
{
|
||||
return $this->exclude ?? new Exclude();
|
||||
}
|
||||
|
||||
public function hasExclude(): bool
|
||||
{
|
||||
return isset($this->exclude);
|
||||
}
|
||||
|
||||
/** @internal Used by {@see ParseDirectoryHandler} to dispatch without triggering the deprecation on {@see self::getExcludedSpecification()}. */
|
||||
public function hasExcludedSpecification(): bool
|
||||
{
|
||||
return isset($this->excludedSpecification);
|
||||
}
|
||||
}
|
||||
135
vendor/phpdocumentor/guides/src/Handlers/ParseDirectoryHandler.php
vendored
Normal file
135
vendor/phpdocumentor/guides/src/Handlers/ParseDirectoryHandler.php
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Handlers;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use League\Flysystem\FilesystemInterface;
|
||||
use League\Tactician\CommandBus;
|
||||
use phpDocumentor\FileSystem\FileSystem;
|
||||
use phpDocumentor\Guides\Event\PostCollectFilesForParsingEvent;
|
||||
use phpDocumentor\Guides\Event\PostParseProcess;
|
||||
use phpDocumentor\Guides\Event\PreParseProcess;
|
||||
use phpDocumentor\Guides\FileCollector;
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
use phpDocumentor\Guides\Settings\ProjectSettings;
|
||||
use phpDocumentor\Guides\Settings\SettingsManager;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
use function array_map;
|
||||
use function assert;
|
||||
use function explode;
|
||||
use function implode;
|
||||
use function sprintf;
|
||||
|
||||
final class ParseDirectoryHandler
|
||||
{
|
||||
private SettingsManager $settingsManager;
|
||||
|
||||
public function __construct(
|
||||
private readonly FileCollector $fileCollector,
|
||||
private readonly CommandBus $commandBus,
|
||||
private readonly EventDispatcherInterface $eventDispatcher,
|
||||
SettingsManager|null $settingsManager = null,
|
||||
) {
|
||||
// if for backward compatibility reasons no settings manager was passed, use the defaults
|
||||
$this->settingsManager = $settingsManager ?? new SettingsManager(new ProjectSettings());
|
||||
}
|
||||
|
||||
/** @return DocumentNode[] */
|
||||
public function handle(ParseDirectoryCommand $command): array
|
||||
{
|
||||
$preParseProcessEvent = $this->eventDispatcher->dispatch(
|
||||
new PreParseProcess($command),
|
||||
);
|
||||
assert($preParseProcessEvent instanceof PreParseProcess);
|
||||
$command = $preParseProcessEvent->getParseDirectoryCommand();
|
||||
|
||||
$origin = $command->getOrigin();
|
||||
$currentDirectory = $command->getDirectory();
|
||||
$extension = $command->getInputFormat();
|
||||
|
||||
$indexName = $this->getDirectoryIndexFile(
|
||||
$origin,
|
||||
$currentDirectory,
|
||||
$extension,
|
||||
);
|
||||
|
||||
$files = $this->fileCollector->collect(
|
||||
$origin,
|
||||
$currentDirectory,
|
||||
$extension,
|
||||
match (true) {
|
||||
$command->hasExclude() => $command->getExclude(),
|
||||
$command->hasExcludedSpecification() => $command->getExcludedSpecification(),
|
||||
default => null,
|
||||
},
|
||||
);
|
||||
|
||||
$postCollectFilesForParsingEvent = $this->eventDispatcher->dispatch(
|
||||
new PostCollectFilesForParsingEvent($command, $files),
|
||||
);
|
||||
assert($postCollectFilesForParsingEvent instanceof PostCollectFilesForParsingEvent);
|
||||
/** @var DocumentNode[] $documents */
|
||||
$documents = [];
|
||||
foreach ($postCollectFilesForParsingEvent->getFiles() as $file) {
|
||||
$documents[] = $this->commandBus->handle(
|
||||
new ParseFileCommand($origin, $currentDirectory, $file, $extension, 1, $command->getProjectNode(), $indexName === $file),
|
||||
);
|
||||
}
|
||||
|
||||
$postCollectFilesForParsingEvent = $this->eventDispatcher->dispatch(
|
||||
new PostParseProcess($command, $documents),
|
||||
);
|
||||
assert($postCollectFilesForParsingEvent instanceof PostParseProcess);
|
||||
|
||||
return $documents;
|
||||
}
|
||||
|
||||
private function getDirectoryIndexFile(
|
||||
FilesystemInterface|FileSystem $filesystem,
|
||||
string $directory,
|
||||
string $sourceFormat,
|
||||
): string {
|
||||
$extension = $sourceFormat;
|
||||
|
||||
// On macOS filesystems, a file-check against "index.rst"
|
||||
// using $filesystem->has() would return TRUE, when in fact
|
||||
// a file might be stored as "Index.rst". Thus, at this point
|
||||
// we fetch the whole directory list and compare the contents
|
||||
// with if the INDEX_FILE_NAMES entry matches. This ensures
|
||||
// that we get the file with exactly the casing that is returned
|
||||
// from the filesystem.
|
||||
$contentFromFilesystem = $filesystem->listContents($directory);
|
||||
$hashedContentFromFilesystem = [];
|
||||
foreach ($contentFromFilesystem as $itemFromFilesystem) {
|
||||
$hashedContentFromFilesystem[$itemFromFilesystem['basename']] = true;
|
||||
}
|
||||
|
||||
$indexFileNames = array_map('trim', explode(',', $this->settingsManager->getProjectSettings()->getIndexName()));
|
||||
|
||||
$indexNamesNotFound = [];
|
||||
foreach ($indexFileNames as $indexName) {
|
||||
$fullIndexFilename = sprintf('%s.%s', $indexName, $extension);
|
||||
if (isset($hashedContentFromFilesystem[$fullIndexFilename])) {
|
||||
return $indexName;
|
||||
}
|
||||
|
||||
$indexNamesNotFound[] = $fullIndexFilename;
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException(
|
||||
sprintf('Could not find an index file "%s", expected file names: %s', $directory, implode(', ', $indexNamesNotFound)),
|
||||
);
|
||||
}
|
||||
}
|
||||
67
vendor/phpdocumentor/guides/src/Handlers/ParseFileCommand.php
vendored
Normal file
67
vendor/phpdocumentor/guides/src/Handlers/ParseFileCommand.php
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Handlers;
|
||||
|
||||
use League\Flysystem\FilesystemInterface;
|
||||
use phpDocumentor\FileSystem\FileSystem;
|
||||
use phpDocumentor\Guides\Nodes\ProjectNode;
|
||||
|
||||
final class ParseFileCommand
|
||||
{
|
||||
public function __construct(
|
||||
private readonly FilesystemInterface|FileSystem $origin,
|
||||
private readonly string $directory,
|
||||
private readonly string $file,
|
||||
private readonly string $extension,
|
||||
private readonly int $initialHeaderLevel,
|
||||
private readonly ProjectNode $projectNode,
|
||||
private readonly bool $isRoot,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getOrigin(): FilesystemInterface|FileSystem
|
||||
{
|
||||
return $this->origin;
|
||||
}
|
||||
|
||||
public function getDirectory(): string
|
||||
{
|
||||
return $this->directory;
|
||||
}
|
||||
|
||||
public function getFile(): string
|
||||
{
|
||||
return $this->file;
|
||||
}
|
||||
|
||||
public function getExtension(): string
|
||||
{
|
||||
return $this->extension;
|
||||
}
|
||||
|
||||
public function getInitialHeaderLevel(): int
|
||||
{
|
||||
return $this->initialHeaderLevel;
|
||||
}
|
||||
|
||||
public function getProjectNode(): ProjectNode
|
||||
{
|
||||
return $this->projectNode;
|
||||
}
|
||||
|
||||
public function isRoot(): bool
|
||||
{
|
||||
return $this->isRoot;
|
||||
}
|
||||
}
|
||||
117
vendor/phpdocumentor/guides/src/Handlers/ParseFileHandler.php
vendored
Normal file
117
vendor/phpdocumentor/guides/src/Handlers/ParseFileHandler.php
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Handlers;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use League\Flysystem\FilesystemInterface;
|
||||
use phpDocumentor\FileSystem\FileSystem;
|
||||
use phpDocumentor\Guides\Event\PostParseDocument;
|
||||
use phpDocumentor\Guides\Event\PreParseDocument;
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
use phpDocumentor\Guides\Nodes\ProjectNode;
|
||||
use phpDocumentor\Guides\Parser;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use RuntimeException;
|
||||
|
||||
use function assert;
|
||||
use function ltrim;
|
||||
use function sprintf;
|
||||
use function trim;
|
||||
|
||||
final class ParseFileHandler
|
||||
{
|
||||
public function __construct(
|
||||
private readonly LoggerInterface $logger,
|
||||
private readonly EventDispatcherInterface $eventDispatcher,
|
||||
private readonly Parser $parser,
|
||||
) {
|
||||
}
|
||||
|
||||
public function handle(ParseFileCommand $command): DocumentNode|null
|
||||
{
|
||||
$this->logger->info(sprintf('Parsing %s', $command->getFile()));
|
||||
|
||||
return $this->createDocument(
|
||||
$command->getOrigin(),
|
||||
$command->getDirectory(),
|
||||
$command->getFile(),
|
||||
$command->getExtension(),
|
||||
$command->getInitialHeaderLevel(),
|
||||
$command->getProjectNode(),
|
||||
$command->isRoot(),
|
||||
);
|
||||
}
|
||||
|
||||
private function getFileContents(FilesystemInterface|FileSystem $origin, string $file): string
|
||||
{
|
||||
if (!$origin->has($file)) {
|
||||
throw new InvalidArgumentException(sprintf('File at path %s does not exist', $file));
|
||||
}
|
||||
|
||||
$contents = $origin->read($file);
|
||||
|
||||
if ($contents === false) {
|
||||
throw new InvalidArgumentException(sprintf('Could not load file from path %s', $file));
|
||||
}
|
||||
|
||||
return $contents;
|
||||
}
|
||||
|
||||
private function createDocument(
|
||||
FilesystemInterface|FileSystem $origin,
|
||||
string $documentFolder,
|
||||
string $fileName,
|
||||
string $extension,
|
||||
int $initialHeaderLevel,
|
||||
ProjectNode $projectNode,
|
||||
bool $isRoot,
|
||||
): DocumentNode|null {
|
||||
$path = $this->buildPathOnFileSystem($fileName, $documentFolder, $extension);
|
||||
$fileContents = $this->getFileContents($origin, $path);
|
||||
|
||||
$this->parser->prepare(
|
||||
$origin,
|
||||
$documentFolder,
|
||||
$fileName,
|
||||
$projectNode,
|
||||
$initialHeaderLevel,
|
||||
);
|
||||
|
||||
$preParseDocumentEvent = $this->eventDispatcher->dispatch(
|
||||
new PreParseDocument($this->parser, $path, $fileContents),
|
||||
);
|
||||
assert($preParseDocumentEvent instanceof PreParseDocument);
|
||||
|
||||
$document = null;
|
||||
try {
|
||||
$document = $this->parser->parse($preParseDocumentEvent->getContents(), $extension)->withIsRoot($isRoot);
|
||||
} catch (RuntimeException $e) {
|
||||
$this->logger->error(
|
||||
sprintf('Unable to parse %s, input format was not recognized', $path),
|
||||
['error' => $e],
|
||||
);
|
||||
}
|
||||
|
||||
$event = $this->eventDispatcher->dispatch(new PostParseDocument($fileName, $document, $path));
|
||||
assert($event instanceof PostParseDocument);
|
||||
|
||||
return $event->getDocumentNode();
|
||||
}
|
||||
|
||||
private function buildPathOnFileSystem(string $file, string $currentDirectory, string $extension): string
|
||||
{
|
||||
return ltrim(sprintf('%s/%s.%s', trim($currentDirectory, '/'), $file, $extension), '/');
|
||||
}
|
||||
}
|
||||
31
vendor/phpdocumentor/guides/src/Handlers/PersistCacheCommand.php
vendored
Normal file
31
vendor/phpdocumentor/guides/src/Handlers/PersistCacheCommand.php
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Handlers;
|
||||
|
||||
final class PersistCacheCommand
|
||||
{
|
||||
public function __construct(private readonly string $cacheDirectory, private readonly bool $useCache = false)
|
||||
{
|
||||
}
|
||||
|
||||
public function getCacheDirectory(): string
|
||||
{
|
||||
return $this->cacheDirectory;
|
||||
}
|
||||
|
||||
public function useCache(): bool
|
||||
{
|
||||
return $this->useCache;
|
||||
}
|
||||
}
|
||||
26
vendor/phpdocumentor/guides/src/Handlers/PersistCacheHandler.php
vendored
Normal file
26
vendor/phpdocumentor/guides/src/Handlers/PersistCacheHandler.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Handlers;
|
||||
|
||||
final class PersistCacheHandler
|
||||
{
|
||||
public function handle(PersistCacheCommand $command): void
|
||||
{
|
||||
if (!$command->useCache()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Introduce Caching
|
||||
}
|
||||
}
|
||||
76
vendor/phpdocumentor/guides/src/Handlers/RenderCommand.php
vendored
Normal file
76
vendor/phpdocumentor/guides/src/Handlers/RenderCommand.php
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Handlers;
|
||||
|
||||
use League\Flysystem\FilesystemInterface;
|
||||
use phpDocumentor\FileSystem\FileSystem;
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
use phpDocumentor\Guides\Nodes\ProjectNode;
|
||||
use phpDocumentor\Guides\Renderer\DocumentListIterator;
|
||||
|
||||
final class RenderCommand
|
||||
{
|
||||
private DocumentListIterator $documentIterator;
|
||||
|
||||
/** @param DocumentNode[] $documentArray */
|
||||
public function __construct(
|
||||
private readonly string $outputFormat,
|
||||
private readonly array $documentArray,
|
||||
private readonly FilesystemInterface|FileSystem $origin,
|
||||
private readonly FilesystemInterface|FileSystem $destination,
|
||||
private readonly ProjectNode $projectNode,
|
||||
private readonly string $destinationPath = '/',
|
||||
) {
|
||||
$this->documentIterator = DocumentListIterator::create(
|
||||
$this->projectNode->getRootDocumentEntry(),
|
||||
$this->documentArray,
|
||||
);
|
||||
}
|
||||
|
||||
public function getOutputFormat(): string
|
||||
{
|
||||
return $this->outputFormat;
|
||||
}
|
||||
|
||||
/** @return DocumentNode[] $documentArray */
|
||||
public function getDocumentArray(): array
|
||||
{
|
||||
return $this->documentArray;
|
||||
}
|
||||
|
||||
public function getDocumentIterator(): DocumentListIterator
|
||||
{
|
||||
return $this->documentIterator;
|
||||
}
|
||||
|
||||
public function getOrigin(): FilesystemInterface|FileSystem
|
||||
{
|
||||
return $this->origin;
|
||||
}
|
||||
|
||||
public function getDestination(): FilesystemInterface|FileSystem
|
||||
{
|
||||
return $this->destination;
|
||||
}
|
||||
|
||||
public function getDestinationPath(): string
|
||||
{
|
||||
return $this->destinationPath;
|
||||
}
|
||||
|
||||
public function getProjectNode(): ProjectNode
|
||||
{
|
||||
return $this->projectNode;
|
||||
}
|
||||
}
|
||||
41
vendor/phpdocumentor/guides/src/Handlers/RenderDocumentCommand.php
vendored
Normal file
41
vendor/phpdocumentor/guides/src/Handlers/RenderDocumentCommand.php
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Handlers;
|
||||
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
use phpDocumentor\Guides\RenderContext;
|
||||
|
||||
final class RenderDocumentCommand
|
||||
{
|
||||
public function __construct(
|
||||
private readonly DocumentNode $document,
|
||||
private readonly RenderContext $renderContext,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getDocument(): DocumentNode
|
||||
{
|
||||
return $this->document;
|
||||
}
|
||||
|
||||
public function getContext(): RenderContext
|
||||
{
|
||||
return $this->renderContext;
|
||||
}
|
||||
|
||||
public function getFileDestination(): string
|
||||
{
|
||||
return $this->renderContext->getDestinationPath() . '/' . $this->renderContext->getCurrentFileName() . '.' . $this->renderContext->getOutputFormat();
|
||||
}
|
||||
}
|
||||
53
vendor/phpdocumentor/guides/src/Handlers/RenderDocumentHandler.php
vendored
Normal file
53
vendor/phpdocumentor/guides/src/Handlers/RenderDocumentHandler.php
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Handlers;
|
||||
|
||||
use phpDocumentor\Guides\Event\PostRenderDocument;
|
||||
use phpDocumentor\Guides\Event\PreRenderDocument;
|
||||
use phpDocumentor\Guides\NodeRenderers\NodeRenderer;
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
use function assert;
|
||||
|
||||
final class RenderDocumentHandler
|
||||
{
|
||||
/** @param NodeRenderer<DocumentNode> $renderer */
|
||||
public function __construct(
|
||||
private readonly NodeRenderer $renderer,
|
||||
private readonly EventDispatcherInterface $eventDispatcher,
|
||||
) {
|
||||
}
|
||||
|
||||
public function handle(RenderDocumentCommand $command): void
|
||||
{
|
||||
$preRenderDocumentEvent = $this->eventDispatcher->dispatch(
|
||||
new PreRenderDocument($this->renderer, $command),
|
||||
);
|
||||
assert($preRenderDocumentEvent instanceof PreRenderDocument);
|
||||
|
||||
$command->getContext()->getDestination()->put(
|
||||
$command->getFileDestination(),
|
||||
$this->renderer->render(
|
||||
$command->getDocument(),
|
||||
$command->getContext(),
|
||||
),
|
||||
);
|
||||
|
||||
$postRenderDocumentEvent = $this->eventDispatcher->dispatch(
|
||||
new PostRenderDocument($this->renderer, $command),
|
||||
);
|
||||
assert($postRenderDocumentEvent instanceof PostRenderDocument);
|
||||
}
|
||||
}
|
||||
48
vendor/phpdocumentor/guides/src/Handlers/RenderHandler.php
vendored
Normal file
48
vendor/phpdocumentor/guides/src/Handlers/RenderHandler.php
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Handlers;
|
||||
|
||||
use phpDocumentor\Guides\Event\PostRenderProcess;
|
||||
use phpDocumentor\Guides\Event\PreRenderProcess;
|
||||
use phpDocumentor\Guides\Renderer\TypeRendererFactory;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
use function assert;
|
||||
|
||||
final class RenderHandler
|
||||
{
|
||||
public function __construct(
|
||||
private readonly TypeRendererFactory $renderSetFactory,
|
||||
private readonly EventDispatcherInterface $eventDispatcher,
|
||||
) {
|
||||
}
|
||||
|
||||
public function handle(RenderCommand $command): void
|
||||
{
|
||||
$preRenderProcessEvent = $this->eventDispatcher->dispatch(
|
||||
new PreRenderProcess($command),
|
||||
);
|
||||
assert($preRenderProcessEvent instanceof PreRenderProcess);
|
||||
if ($preRenderProcessEvent->isExitRendering()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$renderSet = $this->renderSetFactory->getRenderSet($command->getOutputFormat());
|
||||
$renderSet->render($command);
|
||||
$postRenderProcessEvent = $this->eventDispatcher->dispatch(
|
||||
new PostRenderProcess($command),
|
||||
);
|
||||
assert($postRenderProcessEvent instanceof PostRenderProcess);
|
||||
}
|
||||
}
|
||||
27
vendor/phpdocumentor/guides/src/MarkupLanguageParser.php
vendored
Normal file
27
vendor/phpdocumentor/guides/src/MarkupLanguageParser.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides;
|
||||
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
|
||||
interface MarkupLanguageParser
|
||||
{
|
||||
public function supports(string $inputFormat): bool;
|
||||
|
||||
public function getParserContext(): ParserContext;
|
||||
|
||||
public function parse(ParserContext $parserContext, string $contents): DocumentNode;
|
||||
|
||||
public function getDocument(): DocumentNode;
|
||||
}
|
||||
27
vendor/phpdocumentor/guides/src/Meta/AnnotationTarget.php
vendored
Normal file
27
vendor/phpdocumentor/guides/src/Meta/AnnotationTarget.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Meta;
|
||||
|
||||
class AnnotationTarget extends InternalTarget
|
||||
{
|
||||
public function __construct(string $documentPath, string $anchorName, private readonly string $name)
|
||||
{
|
||||
parent::__construct($documentPath, $anchorName);
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
}
|
||||
18
vendor/phpdocumentor/guides/src/Meta/CitationTarget.php
vendored
Normal file
18
vendor/phpdocumentor/guides/src/Meta/CitationTarget.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Meta;
|
||||
|
||||
final class CitationTarget extends AnnotationTarget
|
||||
{
|
||||
}
|
||||
33
vendor/phpdocumentor/guides/src/Meta/ExternalTarget.php
vendored
Normal file
33
vendor/phpdocumentor/guides/src/Meta/ExternalTarget.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Meta;
|
||||
|
||||
final class ExternalTarget implements Target
|
||||
{
|
||||
public function __construct(
|
||||
private readonly string $url,
|
||||
private readonly string|null $title = null,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getUrl(): string
|
||||
{
|
||||
return $this->url;
|
||||
}
|
||||
|
||||
public function getTitle(): string|null
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
}
|
||||
33
vendor/phpdocumentor/guides/src/Meta/FootnoteTarget.php
vendored
Normal file
33
vendor/phpdocumentor/guides/src/Meta/FootnoteTarget.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Meta;
|
||||
|
||||
final class FootnoteTarget extends AnnotationTarget
|
||||
{
|
||||
public function __construct(string $documentPath, string $anchorName, string $name, private int $number)
|
||||
{
|
||||
parent::__construct($documentPath, $anchorName, $name);
|
||||
}
|
||||
|
||||
public function getNumber(): int
|
||||
{
|
||||
return $this->number;
|
||||
}
|
||||
|
||||
public function setNumber(int $number): void
|
||||
{
|
||||
$this->number = $number;
|
||||
$this->anchorName = 'footnote-' . $number;
|
||||
}
|
||||
}
|
||||
72
vendor/phpdocumentor/guides/src/Meta/InternalTarget.php
vendored
Normal file
72
vendor/phpdocumentor/guides/src/Meta/InternalTarget.php
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Meta;
|
||||
|
||||
use phpDocumentor\Guides\Nodes\SectionNode;
|
||||
|
||||
class InternalTarget implements Target
|
||||
{
|
||||
private string $url;
|
||||
|
||||
public function __construct(
|
||||
private readonly string $documentPath,
|
||||
protected string $anchorName,
|
||||
private readonly string|null $title = null,
|
||||
private readonly string $linkType = SectionNode::STD_LABEL,
|
||||
private readonly string $prefix = '',
|
||||
) {
|
||||
}
|
||||
|
||||
public function getDocumentPath(): string
|
||||
{
|
||||
return $this->documentPath;
|
||||
}
|
||||
|
||||
public function getAnchor(): string
|
||||
{
|
||||
return $this->anchorName;
|
||||
}
|
||||
|
||||
public function setAnchorName(string $anchorName): void
|
||||
{
|
||||
$this->anchorName = $anchorName;
|
||||
}
|
||||
|
||||
public function getTitle(): string|null
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
public function getUrl(): string
|
||||
{
|
||||
return $this->url;
|
||||
}
|
||||
|
||||
public function setUrl(string $url): InternalTarget
|
||||
{
|
||||
$this->url = $url;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLinkType(): string
|
||||
{
|
||||
return $this->linkType;
|
||||
}
|
||||
|
||||
public function getPrefix(): string
|
||||
{
|
||||
return $this->prefix;
|
||||
}
|
||||
}
|
||||
21
vendor/phpdocumentor/guides/src/Meta/Target.php
vendored
Normal file
21
vendor/phpdocumentor/guides/src/Meta/Target.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\Meta;
|
||||
|
||||
interface Target
|
||||
{
|
||||
public function getUrl(): string;
|
||||
|
||||
public function getTitle(): string|null;
|
||||
}
|
||||
81
vendor/phpdocumentor/guides/src/NodeRenderers/DefaultNodeRenderer.php
vendored
Normal file
81
vendor/phpdocumentor/guides/src/NodeRenderers/DefaultNodeRenderer.php
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\NodeRenderers;
|
||||
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use phpDocumentor\Guides\RenderContext;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
use function assert;
|
||||
use function is_array;
|
||||
use function is_string;
|
||||
use function sprintf;
|
||||
|
||||
/** @implements NodeRenderer<Node> */
|
||||
final class DefaultNodeRenderer implements NodeRenderer, NodeRendererFactoryAware
|
||||
{
|
||||
private NodeRendererFactory|null $nodeRendererFactory = null;
|
||||
|
||||
public function __construct(private readonly LoggerInterface $logger)
|
||||
{
|
||||
}
|
||||
|
||||
public function setNodeRendererFactory(NodeRendererFactory $nodeRendererFactory): void
|
||||
{
|
||||
$this->nodeRendererFactory = $nodeRendererFactory;
|
||||
}
|
||||
|
||||
public function render(Node $node, RenderContext $renderContext): string
|
||||
{
|
||||
$value = $node->getValue();
|
||||
|
||||
if ($value instanceof Node) {
|
||||
assert($this->nodeRendererFactory !== null);
|
||||
|
||||
return $this->nodeRendererFactory->get($value)->render($value, $renderContext);
|
||||
}
|
||||
|
||||
if (is_array($value)) {
|
||||
$returnValue = '';
|
||||
foreach ($value as $child) {
|
||||
if ($child instanceof Node) {
|
||||
$returnValue .= $this->render($child, $renderContext);
|
||||
} else {
|
||||
$this->logger->error(
|
||||
sprintf('The default renderer cannot be applied to node %s', $node::class),
|
||||
$renderContext->getLoggerInformation(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $returnValue;
|
||||
}
|
||||
|
||||
if (is_string($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
$this->logger->error(
|
||||
sprintf('The default renderer cannot be applied to node %s', $node::class),
|
||||
$renderContext->getLoggerInformation(),
|
||||
);
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public function supports(string $nodeFqcn): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
42
vendor/phpdocumentor/guides/src/NodeRenderers/DelegatingNodeRenderer.php
vendored
Normal file
42
vendor/phpdocumentor/guides/src/NodeRenderers/DelegatingNodeRenderer.php
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\NodeRenderers;
|
||||
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use phpDocumentor\Guides\RenderContext;
|
||||
|
||||
/** @implements NodeRenderer<Node> */
|
||||
final class DelegatingNodeRenderer implements NodeRenderer, NodeRendererFactoryAware
|
||||
{
|
||||
private NodeRendererFactory $nodeRendererFactory;
|
||||
|
||||
public function setNodeRendererFactory(NodeRendererFactory $nodeRendererFactory): void
|
||||
{
|
||||
if (isset($this->nodeRendererFactory)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->nodeRendererFactory = $nodeRendererFactory;
|
||||
}
|
||||
|
||||
public function supports(string $nodeFqcn): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function render(Node $node, RenderContext $renderContext): string
|
||||
{
|
||||
return $this->nodeRendererFactory->get($node)->render($node, $renderContext);
|
||||
}
|
||||
}
|
||||
59
vendor/phpdocumentor/guides/src/NodeRenderers/Html/AdmonitionNodeRenderer.php
vendored
Normal file
59
vendor/phpdocumentor/guides/src/NodeRenderers/Html/AdmonitionNodeRenderer.php
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\NodeRenderers\Html;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use phpDocumentor\Guides\NodeRenderers\NodeRenderer;
|
||||
use phpDocumentor\Guides\Nodes\AdmonitionNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use phpDocumentor\Guides\RenderContext;
|
||||
use phpDocumentor\Guides\TemplateRenderer;
|
||||
|
||||
use function implode;
|
||||
use function is_a;
|
||||
|
||||
/** @implements NodeRenderer<AdmonitionNode> */
|
||||
class AdmonitionNodeRenderer implements NodeRenderer
|
||||
{
|
||||
public function __construct(private readonly TemplateRenderer $renderer)
|
||||
{
|
||||
}
|
||||
|
||||
public function supports(string $nodeFqcn): bool
|
||||
{
|
||||
return $nodeFqcn === AdmonitionNode::class || is_a($nodeFqcn, AdmonitionNode::class, true);
|
||||
}
|
||||
|
||||
public function render(Node $node, RenderContext $renderContext): string
|
||||
{
|
||||
if ($node instanceof AdmonitionNode === false) {
|
||||
throw new InvalidArgumentException('Node must be an instance of ' . AdmonitionNode::class);
|
||||
}
|
||||
|
||||
$classes = $node->getClasses();
|
||||
|
||||
return $this->renderer->renderTemplate(
|
||||
$renderContext,
|
||||
'body/admonition.html.twig',
|
||||
[
|
||||
'name' => $node->getName(),
|
||||
'text' => $node->getText(),
|
||||
'title' => $node->getTitle(),
|
||||
'isTitled' => $node->isTitled(),
|
||||
'class' => implode(' ', $classes),
|
||||
'node' => $node->getValue(),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
146
vendor/phpdocumentor/guides/src/NodeRenderers/Html/BreadCrumbNodeRenderer.php
vendored
Normal file
146
vendor/phpdocumentor/guides/src/NodeRenderers/Html/BreadCrumbNodeRenderer.php
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\NodeRenderers\Html;
|
||||
|
||||
use phpDocumentor\Guides\NodeRenderers\NodeRenderer;
|
||||
use phpDocumentor\Guides\Nodes\BreadCrumbNode;
|
||||
use phpDocumentor\Guides\Nodes\DocumentTree\DocumentEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\InternalMenuEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\MenuEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use phpDocumentor\Guides\Nodes\TitleNode;
|
||||
use phpDocumentor\Guides\RenderContext;
|
||||
use phpDocumentor\Guides\TemplateRenderer;
|
||||
|
||||
use function array_reverse;
|
||||
use function assert;
|
||||
use function is_a;
|
||||
|
||||
/**
|
||||
* @template T as Node
|
||||
* @implements NodeRenderer<BreadCrumbNode>
|
||||
*/
|
||||
final class BreadCrumbNodeRenderer implements NodeRenderer
|
||||
{
|
||||
private string $template = 'body/menu/breadcrumb.html.twig';
|
||||
|
||||
public function __construct(
|
||||
private readonly TemplateRenderer $renderer,
|
||||
) {
|
||||
}
|
||||
|
||||
public function supports(string $nodeFqcn): bool
|
||||
{
|
||||
return $nodeFqcn === BreadCrumbNode::class || is_a($nodeFqcn, BreadCrumbNode::class, true);
|
||||
}
|
||||
|
||||
/** @param T $node */
|
||||
public function render(Node $node, RenderContext $renderContext): string
|
||||
{
|
||||
assert($node instanceof BreadCrumbNode);
|
||||
$documentEntry = $renderContext->getCurrentDocumentEntry();
|
||||
$data = [
|
||||
'node' => $node,
|
||||
'rootline' => $documentEntry === null ? [] :
|
||||
$this->buildBreadcrumb(
|
||||
$node,
|
||||
$renderContext,
|
||||
$documentEntry,
|
||||
[],
|
||||
$this->getBreadcrumbMaxLevel($node, $renderContext, $documentEntry, 0),
|
||||
true,
|
||||
),
|
||||
];
|
||||
|
||||
return $this->renderer->renderTemplate(
|
||||
$renderContext,
|
||||
$this->template,
|
||||
$data,
|
||||
);
|
||||
}
|
||||
|
||||
private function getBreadcrumbMaxLevel(
|
||||
BreadCrumbNode $node,
|
||||
RenderContext $renderContext,
|
||||
DocumentEntryNode $documentEntry,
|
||||
int $level,
|
||||
): int {
|
||||
if ($documentEntry->getParent() === null) {
|
||||
if ($documentEntry->isRoot()) {
|
||||
return $level;
|
||||
}
|
||||
|
||||
// Current document has no parent but is not the root, add the overall root to the breadcrumb
|
||||
$entries = $renderContext->getProjectNode()->getAllDocumentEntries();
|
||||
foreach ($entries as $entry) {
|
||||
if ($entry->isRoot() && $entry->getParent() === null) {
|
||||
return $this->getBreadcrumbMaxLevel($node, $renderContext, $entry, ++$level);
|
||||
}
|
||||
}
|
||||
|
||||
return $level;
|
||||
}
|
||||
|
||||
return $this->getBreadcrumbMaxLevel($node, $renderContext, $documentEntry->getParent(), ++$level);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param MenuEntryNode[] $currentBreadcrumb
|
||||
*
|
||||
* @return MenuEntryNode[]
|
||||
*/
|
||||
private function buildBreadcrumb(
|
||||
BreadCrumbNode $node,
|
||||
RenderContext $renderContext,
|
||||
DocumentEntryNode $documentEntry,
|
||||
array $currentBreadcrumb,
|
||||
int $level,
|
||||
bool $isCurrent,
|
||||
): array {
|
||||
$title = $documentEntry->getTitle();
|
||||
$navigationTitle = $documentEntry->getAdditionalData('navigationTitle');
|
||||
if ($navigationTitle instanceof TitleNode) {
|
||||
$title = $navigationTitle;
|
||||
}
|
||||
|
||||
$entry = new InternalMenuEntryNode(
|
||||
$documentEntry->getFile(),
|
||||
$title,
|
||||
[],
|
||||
false,
|
||||
$level,
|
||||
'',
|
||||
true,
|
||||
$isCurrent,
|
||||
);
|
||||
$currentBreadcrumb[] = $entry;
|
||||
if ($documentEntry->getParent() === null) {
|
||||
if ($documentEntry->isRoot()) {
|
||||
return array_reverse($currentBreadcrumb);
|
||||
}
|
||||
|
||||
// Current document has no parent but is not the root, add the overall root to the breadcrumb
|
||||
$entries = $renderContext->getProjectNode()->getAllDocumentEntries();
|
||||
foreach ($entries as $entry) {
|
||||
if ($entry->isRoot() && $entry->getParent() === null) {
|
||||
return $this->buildBreadcrumb($node, $renderContext, $entry, $currentBreadcrumb, --$level, false);
|
||||
}
|
||||
}
|
||||
|
||||
return array_reverse($currentBreadcrumb);
|
||||
}
|
||||
|
||||
return $this->buildBreadcrumb($node, $renderContext, $documentEntry->getParent(), $currentBreadcrumb, --$level, false);
|
||||
}
|
||||
}
|
||||
59
vendor/phpdocumentor/guides/src/NodeRenderers/Html/DocumentNodeRenderer.php
vendored
Normal file
59
vendor/phpdocumentor/guides/src/NodeRenderers/Html/DocumentNodeRenderer.php
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\NodeRenderers\Html;
|
||||
|
||||
use phpDocumentor\Guides\NodeRenderers\NodeRenderer;
|
||||
use phpDocumentor\Guides\Nodes\DocumentNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use phpDocumentor\Guides\RenderContext;
|
||||
use phpDocumentor\Guides\TemplateRenderer;
|
||||
|
||||
use function assert;
|
||||
use function is_a;
|
||||
|
||||
/**
|
||||
* @template T as Node
|
||||
* @implements NodeRenderer<DocumentNode>
|
||||
*/
|
||||
final class DocumentNodeRenderer implements NodeRenderer
|
||||
{
|
||||
private string $template = 'structure/document.html.twig';
|
||||
|
||||
public function __construct(
|
||||
private readonly TemplateRenderer $renderer,
|
||||
) {
|
||||
}
|
||||
|
||||
public function supports(string $nodeFqcn): bool
|
||||
{
|
||||
return $nodeFqcn === DocumentNode::class || is_a($nodeFqcn, DocumentNode::class, true);
|
||||
}
|
||||
|
||||
/** @param T $node */
|
||||
public function render(Node $node, RenderContext $renderContext): string
|
||||
{
|
||||
assert($node instanceof DocumentNode);
|
||||
$data = [
|
||||
'node' => $node,
|
||||
'title' => $node->getPageTitle(),
|
||||
'parts' => $node->getDocumentPartNodes(),
|
||||
];
|
||||
|
||||
return $this->renderer->renderTemplate(
|
||||
$renderContext,
|
||||
$this->template,
|
||||
$data,
|
||||
);
|
||||
}
|
||||
}
|
||||
52
vendor/phpdocumentor/guides/src/NodeRenderers/Html/MenuEntryRenderer.php
vendored
Normal file
52
vendor/phpdocumentor/guides/src/NodeRenderers/Html/MenuEntryRenderer.php
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\NodeRenderers\Html;
|
||||
|
||||
use phpDocumentor\Guides\NodeRenderers\NodeRenderer;
|
||||
use phpDocumentor\Guides\Nodes\Menu\MenuEntryNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use phpDocumentor\Guides\RenderContext;
|
||||
use phpDocumentor\Guides\Renderer\UrlGenerator\UrlGeneratorInterface;
|
||||
use phpDocumentor\Guides\TemplateRenderer;
|
||||
|
||||
use function is_a;
|
||||
|
||||
/** @implements NodeRenderer<MenuEntryNode> */
|
||||
final class MenuEntryRenderer implements NodeRenderer
|
||||
{
|
||||
public function __construct(
|
||||
private readonly TemplateRenderer $renderer,
|
||||
private readonly UrlGeneratorInterface $urlGenerator,
|
||||
) {
|
||||
}
|
||||
|
||||
public function supports(string $nodeFqcn): bool
|
||||
{
|
||||
return $nodeFqcn === MenuEntryNode::class || is_a($nodeFqcn, MenuEntryNode::class, true);
|
||||
}
|
||||
|
||||
public function render(Node $node, RenderContext $renderContext): string
|
||||
{
|
||||
$url = $this->urlGenerator->generateCanonicalOutputUrl($renderContext, $node->getUrl(), $node->getValue()?->getId());
|
||||
|
||||
return $this->renderer->renderTemplate(
|
||||
$renderContext,
|
||||
'body/menu/menu-item.html.twig',
|
||||
[
|
||||
'url' => $url,
|
||||
'node' => $node,
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
66
vendor/phpdocumentor/guides/src/NodeRenderers/Html/MenuNodeRenderer.php
vendored
Normal file
66
vendor/phpdocumentor/guides/src/NodeRenderers/Html/MenuNodeRenderer.php
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\NodeRenderers\Html;
|
||||
|
||||
use phpDocumentor\Guides\NodeRenderers\NodeRenderer;
|
||||
use phpDocumentor\Guides\Nodes\Menu\ContentMenuNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\MenuNode;
|
||||
use phpDocumentor\Guides\Nodes\Menu\TocNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use phpDocumentor\Guides\RenderContext;
|
||||
use phpDocumentor\Guides\TemplateRenderer;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
use function is_a;
|
||||
|
||||
/** @implements NodeRenderer<MenuNode> */
|
||||
final class MenuNodeRenderer implements NodeRenderer
|
||||
{
|
||||
public function __construct(private readonly TemplateRenderer $renderer)
|
||||
{
|
||||
}
|
||||
|
||||
public function render(Node $node, RenderContext $renderContext): string
|
||||
{
|
||||
Assert::isInstanceOf($node, MenuNode::class);
|
||||
|
||||
if ($node->getOption('hidden', false)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->renderer->renderTemplate(
|
||||
$renderContext,
|
||||
$this->getTemplate($node),
|
||||
['node' => $node],
|
||||
);
|
||||
}
|
||||
|
||||
private function getTemplate(Node $node): string
|
||||
{
|
||||
if ($node instanceof TocNode) {
|
||||
return 'body/menu/table-of-content.html.twig';
|
||||
}
|
||||
|
||||
if ($node instanceof ContentMenuNode) {
|
||||
return 'body/menu/content-menu.html.twig';
|
||||
}
|
||||
|
||||
return 'body/menu/menu.html.twig';
|
||||
}
|
||||
|
||||
public function supports(string $nodeFqcn): bool
|
||||
{
|
||||
return $nodeFqcn === MenuNode::class || is_a($nodeFqcn, MenuNode::class, true);
|
||||
}
|
||||
}
|
||||
51
vendor/phpdocumentor/guides/src/NodeRenderers/Html/TableNodeRenderer.php
vendored
Normal file
51
vendor/phpdocumentor/guides/src/NodeRenderers/Html/TableNodeRenderer.php
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\NodeRenderers\Html;
|
||||
|
||||
use phpDocumentor\Guides\NodeRenderers\NodeRenderer;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use phpDocumentor\Guides\Nodes\TableNode;
|
||||
use phpDocumentor\Guides\RenderContext;
|
||||
use phpDocumentor\Guides\TemplateRenderer;
|
||||
|
||||
use function is_a;
|
||||
|
||||
/** @implements NodeRenderer<TableNode> */
|
||||
final class TableNodeRenderer implements NodeRenderer
|
||||
{
|
||||
public function __construct(private readonly TemplateRenderer $renderer)
|
||||
{
|
||||
}
|
||||
|
||||
public function render(Node $node, RenderContext $renderContext): string
|
||||
{
|
||||
$headers = $node->getHeaders();
|
||||
$rows = $node->getData();
|
||||
|
||||
return $this->renderer->renderTemplate(
|
||||
$renderContext,
|
||||
'body/table.html.twig',
|
||||
[
|
||||
'tableNode' => $node,
|
||||
'tableHeaderRows' => $headers,
|
||||
'tableRows' => $rows,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
public function supports(string $nodeFqcn): bool
|
||||
{
|
||||
return $nodeFqcn === TableNode::class || is_a($nodeFqcn, TableNode::class, true);
|
||||
}
|
||||
}
|
||||
59
vendor/phpdocumentor/guides/src/NodeRenderers/InMemoryNodeRendererFactory.php
vendored
Normal file
59
vendor/phpdocumentor/guides/src/NodeRenderers/InMemoryNodeRendererFactory.php
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\NodeRenderers;
|
||||
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
|
||||
final class InMemoryNodeRendererFactory implements NodeRendererFactory
|
||||
{
|
||||
/** @var array<class-string<Node>, NodeRenderer<Node>> */
|
||||
private array $cache = [];
|
||||
|
||||
/**
|
||||
* @param iterable<NodeRenderer<Node>> $nodeRenderers
|
||||
* @param NodeRenderer<Node> $defaultNodeRenderer
|
||||
*/
|
||||
public function __construct(private readonly iterable $nodeRenderers, private readonly NodeRenderer $defaultNodeRenderer)
|
||||
{
|
||||
foreach ($nodeRenderers as $nodeRenderer) {
|
||||
if (!$nodeRenderer instanceof NodeRendererFactoryAware) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$nodeRenderer->setNodeRendererFactory($this);
|
||||
}
|
||||
|
||||
if (!$defaultNodeRenderer instanceof NodeRendererFactoryAware) {
|
||||
return;
|
||||
}
|
||||
|
||||
$defaultNodeRenderer->setNodeRendererFactory($this);
|
||||
}
|
||||
|
||||
public function get(Node $node): NodeRenderer
|
||||
{
|
||||
$nodeFqcn = $node::class;
|
||||
if (isset($this->cache[$nodeFqcn])) {
|
||||
return $this->cache[$nodeFqcn];
|
||||
}
|
||||
|
||||
foreach ($this->nodeRenderers as $nodeRenderer) {
|
||||
if ($nodeRenderer->supports($nodeFqcn)) {
|
||||
return $this->cache[$nodeFqcn] = $nodeRenderer;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->cache[$nodeFqcn] = $this->defaultNodeRenderer;
|
||||
}
|
||||
}
|
||||
85
vendor/phpdocumentor/guides/src/NodeRenderers/LaTeX/TableNodeRenderer.php
vendored
Normal file
85
vendor/phpdocumentor/guides/src/NodeRenderers/LaTeX/TableNodeRenderer.php
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\NodeRenderers\LaTeX;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use phpDocumentor\Guides\NodeRenderers\NodeRenderer;
|
||||
use phpDocumentor\Guides\NodeRenderers\NodeRendererFactory;
|
||||
use phpDocumentor\Guides\NodeRenderers\NodeRendererFactoryAware;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use phpDocumentor\Guides\Nodes\SpanNode;
|
||||
use phpDocumentor\Guides\Nodes\TableNode;
|
||||
use phpDocumentor\Guides\RenderContext;
|
||||
|
||||
use function assert;
|
||||
use function count;
|
||||
use function implode;
|
||||
use function is_a;
|
||||
use function max;
|
||||
|
||||
/** @implements NodeRenderer<TableNode> */
|
||||
final class TableNodeRenderer implements NodeRenderer, NodeRendererFactoryAware
|
||||
{
|
||||
private NodeRendererFactory|null $nodeRendererFactory = null;
|
||||
|
||||
public function setNodeRendererFactory(NodeRendererFactory $nodeRendererFactory): void
|
||||
{
|
||||
$this->nodeRendererFactory = $nodeRendererFactory;
|
||||
}
|
||||
|
||||
public function render(Node $node, RenderContext $renderContext): string
|
||||
{
|
||||
if ($node instanceof TableNode === false) {
|
||||
throw new InvalidArgumentException('Invalid node presented');
|
||||
}
|
||||
|
||||
$cols = 0;
|
||||
|
||||
$rows = [];
|
||||
foreach ($node->getData() as $row) {
|
||||
$rowTex = '';
|
||||
$cols = max($cols, count($row->getColumns()));
|
||||
|
||||
assert($this->nodeRendererFactory !== null);
|
||||
foreach ($row->getColumns() as $n => $col) {
|
||||
assert($col instanceof SpanNode);
|
||||
$rowTex .= $this->nodeRendererFactory->get($col)->render($col, $renderContext);
|
||||
|
||||
if ((int) $n + 1 >= count($row->getColumns())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$rowTex .= ' & ';
|
||||
}
|
||||
|
||||
$rowTex .= ' \\\\' . "\n";
|
||||
$rows[] = $rowTex;
|
||||
}
|
||||
|
||||
$aligns = [];
|
||||
for ($i = 0; $i < $cols; $i++) {
|
||||
$aligns[] = 'l';
|
||||
}
|
||||
|
||||
$aligns = '|' . implode('|', $aligns) . '|';
|
||||
$rows = "\\hline\n" . implode("\\hline\n", $rows) . "\\hline\n";
|
||||
|
||||
return "\\begin{tabular}{" . $aligns . "}\n" . $rows . "\n\\end{tabular}\n";
|
||||
}
|
||||
|
||||
public function supports(string $nodeFqcn): bool
|
||||
{
|
||||
return $nodeFqcn === TableNode::class || is_a($nodeFqcn, TableNode::class, true);
|
||||
}
|
||||
}
|
||||
62
vendor/phpdocumentor/guides/src/NodeRenderers/LaTeX/TitleNodeRenderer.php
vendored
Normal file
62
vendor/phpdocumentor/guides/src/NodeRenderers/LaTeX/TitleNodeRenderer.php
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\NodeRenderers\LaTeX;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use phpDocumentor\Guides\NodeRenderers\NodeRenderer;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use phpDocumentor\Guides\Nodes\TitleNode;
|
||||
use phpDocumentor\Guides\RenderContext;
|
||||
use phpDocumentor\Guides\TemplateRenderer;
|
||||
|
||||
use function is_a;
|
||||
|
||||
/** @implements NodeRenderer<TitleNode> */
|
||||
final class TitleNodeRenderer implements NodeRenderer
|
||||
{
|
||||
public function __construct(private readonly TemplateRenderer $renderer)
|
||||
{
|
||||
}
|
||||
|
||||
public function render(Node $node, RenderContext $renderContext): string
|
||||
{
|
||||
if ($node instanceof TitleNode === false) {
|
||||
throw new InvalidArgumentException('Invalid node presented');
|
||||
}
|
||||
|
||||
$type = 'chapter';
|
||||
|
||||
if ($node->getLevel() > 1) {
|
||||
$type = 'section';
|
||||
|
||||
for ($i = 2; $i < $node->getLevel(); $i++) {
|
||||
$type = 'sub' . $type;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->renderer->renderTemplate(
|
||||
$renderContext,
|
||||
'page/header/title.tex.twig',
|
||||
[
|
||||
'type' => $type,
|
||||
'titleNode' => $node,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
public function supports(string $nodeFqcn): bool
|
||||
{
|
||||
return $nodeFqcn === TitleNode::class || is_a($nodeFqcn, TitleNode::class, true);
|
||||
}
|
||||
}
|
||||
49
vendor/phpdocumentor/guides/src/NodeRenderers/LaTeX/TocNodeRenderer.php
vendored
Normal file
49
vendor/phpdocumentor/guides/src/NodeRenderers/LaTeX/TocNodeRenderer.php
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\NodeRenderers\LaTeX;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use phpDocumentor\Guides\NodeRenderers\NodeRenderer;
|
||||
use phpDocumentor\Guides\Nodes\Menu\TocNode;
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use phpDocumentor\Guides\RenderContext;
|
||||
use phpDocumentor\Guides\TemplateRenderer;
|
||||
|
||||
use function is_a;
|
||||
|
||||
/** @implements NodeRenderer<TocNode> */
|
||||
final class TocNodeRenderer implements NodeRenderer
|
||||
{
|
||||
public function __construct(private readonly TemplateRenderer $renderer)
|
||||
{
|
||||
}
|
||||
|
||||
public function render(Node $node, RenderContext $renderContext): string
|
||||
{
|
||||
if ($node instanceof TocNode === false) {
|
||||
throw new InvalidArgumentException('Invalid node presented');
|
||||
}
|
||||
|
||||
return $this->renderer->renderTemplate(
|
||||
$renderContext,
|
||||
'toc.tex.twig',
|
||||
['tocNode' => $node],
|
||||
);
|
||||
}
|
||||
|
||||
public function supports(string $nodeFqcn): bool
|
||||
{
|
||||
return $nodeFqcn === TocNode::class || is_a($nodeFqcn, TocNode::class, true);
|
||||
}
|
||||
}
|
||||
38
vendor/phpdocumentor/guides/src/NodeRenderers/LazyNodeRendererFactory.php
vendored
Normal file
38
vendor/phpdocumentor/guides/src/NodeRenderers/LazyNodeRendererFactory.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\NodeRenderers;
|
||||
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
|
||||
final class LazyNodeRendererFactory implements NodeRendererFactory
|
||||
{
|
||||
/** @var callable */
|
||||
private $factory;
|
||||
|
||||
private NodeRendererFactory|null $innerFactory = null;
|
||||
|
||||
public function __construct(callable $factory)
|
||||
{
|
||||
$this->factory = $factory;
|
||||
}
|
||||
|
||||
public function get(Node $node): NodeRenderer
|
||||
{
|
||||
if ($this->innerFactory === null) {
|
||||
$this->innerFactory = ($this->factory)();
|
||||
}
|
||||
|
||||
return $this->innerFactory->get($node);
|
||||
}
|
||||
}
|
||||
27
vendor/phpdocumentor/guides/src/NodeRenderers/NodeRenderer.php
vendored
Normal file
27
vendor/phpdocumentor/guides/src/NodeRenderers/NodeRenderer.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\NodeRenderers;
|
||||
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
use phpDocumentor\Guides\RenderContext;
|
||||
|
||||
/** @template T of Node */
|
||||
interface NodeRenderer
|
||||
{
|
||||
/** @param class-string<Node> $nodeFqcn */
|
||||
public function supports(string $nodeFqcn): bool;
|
||||
|
||||
/** @param T $node */
|
||||
public function render(Node $node, RenderContext $renderContext): string;
|
||||
}
|
||||
22
vendor/phpdocumentor/guides/src/NodeRenderers/NodeRendererFactory.php
vendored
Normal file
22
vendor/phpdocumentor/guides/src/NodeRenderers/NodeRendererFactory.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\NodeRenderers;
|
||||
|
||||
use phpDocumentor\Guides\Nodes\Node;
|
||||
|
||||
interface NodeRendererFactory
|
||||
{
|
||||
/** @return NodeRenderer<Node> */
|
||||
public function get(Node $node): NodeRenderer;
|
||||
}
|
||||
19
vendor/phpdocumentor/guides/src/NodeRenderers/NodeRendererFactoryAware.php
vendored
Normal file
19
vendor/phpdocumentor/guides/src/NodeRenderers/NodeRendererFactoryAware.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Guides\NodeRenderers;
|
||||
|
||||
interface NodeRendererFactoryAware
|
||||
{
|
||||
public function setNodeRendererFactory(NodeRendererFactory $nodeRendererFactory): void;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user