85 lines
2.5 KiB
PHP
85 lines
2.5 KiB
PHP
|
<?php
|
||
|
|
||
|
declare(strict_types=1);
|
||
|
|
||
|
namespace Doctrine\RST\Directives;
|
||
|
|
||
|
use Doctrine\RST\Nodes\BlockNode;
|
||
|
use Doctrine\RST\Nodes\Node;
|
||
|
use Doctrine\RST\Parser;
|
||
|
|
||
|
/**
|
||
|
* A directive that parses the sub block and call the processSub that can
|
||
|
* be overloaded, like :
|
||
|
*
|
||
|
* .. sub-directive::
|
||
|
* Some block of code
|
||
|
*
|
||
|
* You can imagine anything here, like adding *emphasis*, lists or
|
||
|
* titles
|
||
|
*/
|
||
|
abstract class SubDirective extends Directive
|
||
|
{
|
||
|
/** @param string[] $options */
|
||
|
final public function process(
|
||
|
Parser $parser,
|
||
|
?Node $node,
|
||
|
string $variable,
|
||
|
string $data,
|
||
|
array $options
|
||
|
): void {
|
||
|
/*
|
||
|
* A BlockNode indicates that the content was passed in "raw" and should
|
||
|
* be sub-parsed. This is the main use-case.
|
||
|
*
|
||
|
* However, there are some odd cases where a directive appears
|
||
|
* to "end"... and DocumentParser continues parsing the next
|
||
|
* section, for example as a ParagraphNode or ListNode. When
|
||
|
* that terminates, the original directive is THEN processed
|
||
|
* and called.
|
||
|
*
|
||
|
* A key example is the "class::" directive (see class-directive.rst test case).
|
||
|
* That is where it is legal to have a format like this:
|
||
|
*
|
||
|
* .. class:: special-list
|
||
|
*
|
||
|
* - Test list item 1.
|
||
|
* - Test list item 2.
|
||
|
*
|
||
|
* Notice the 2 list items are NOT indented. This is legal, and ultimately
|
||
|
* those two items would be parsed as a ListNode and THEN passed to
|
||
|
* ClassDirective (which extends SubDirective) for processing.
|
||
|
*/
|
||
|
if ($node instanceof BlockNode) {
|
||
|
$document = $parser->getSubParser()->parseLocal($node->getValue());
|
||
|
} else {
|
||
|
// If the $node is null, it represents a node with no content.
|
||
|
// Some directives - like "figure" - both allow content AND no content.
|
||
|
$document = $node;
|
||
|
}
|
||
|
|
||
|
$newNode = $this->processSub($parser, $document, $variable, $data, $options);
|
||
|
|
||
|
if ($newNode === null) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ($variable !== '') {
|
||
|
$parser->getEnvironment()->setVariable($variable, $newNode);
|
||
|
} else {
|
||
|
$parser->getDocument()->addNode($newNode);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/** @param string[] $options */
|
||
|
public function processSub(
|
||
|
Parser $parser,
|
||
|
?Node $document,
|
||
|
string $variable,
|
||
|
string $data,
|
||
|
array $options
|
||
|
): ?Node {
|
||
|
return null;
|
||
|
}
|
||
|
}
|