gl-website-deployer/vendor/doctrine/rst-parser/lib/Renderers/SpanNodeRenderer.php
2024-11-19 08:02:04 +01:00

191 lines
5.4 KiB
PHP

<?php
declare(strict_types=1);
namespace Doctrine\RST\Renderers;
use Doctrine\RST\Environment;
use Doctrine\RST\InvalidLink;
use Doctrine\RST\Nodes\Node;
use Doctrine\RST\Nodes\SpanNode;
use Doctrine\RST\Span\SpanToken;
use InvalidArgumentException;
use function is_string;
use function preg_replace;
use function preg_replace_callback;
use function sprintf;
use function str_replace;
abstract class SpanNodeRenderer implements NodeRenderer, SpanRenderer
{
/** @var Environment */
protected $environment;
/** @var SpanNode */
protected $span;
public function __construct(
Environment $environment,
SpanNode $span
) {
$this->environment = $environment;
$this->span = $span;
}
public function render(): string
{
$value = $this->span->getValue();
$span = $this->renderSyntaxes($value);
$span = $this->renderTokens($span);
return $span;
}
private function renderSyntaxes(string $span): string
{
$span = $this->escape($span);
$span = $this->renderStrongEmphasis($span);
$span = $this->renderEmphasis($span);
$span = $this->renderNbsp($span);
$span = $this->renderVariables($span);
$span = $this->renderBrs($span);
return $span;
}
private function renderStrongEmphasis(string $span): string
{
return (string) preg_replace_callback('/\*\*(.+)\*\*/mUsi', function (array $matches): string {
return $this->strongEmphasis($matches[1]);
}, $span);
}
private function renderEmphasis(string $span): string
{
return (string) preg_replace_callback('/\*(.+)\*/mUsi', function (array $matches): string {
return $this->emphasis($matches[1]);
}, $span);
}
private function renderNbsp(string $span): string
{
return (string) preg_replace('/~/', $this->nbsp(), $span);
}
private function renderVariables(string $span): string
{
return (string) preg_replace_callback('/\|(.+)\|/mUsi', function (array $match): string {
$variable = $this->environment->getVariable($match[1]);
if ($variable === null) {
return '';
}
if ($variable instanceof Node) {
return $variable->render();
}
if (is_string($variable)) {
return $variable;
}
return (string) $variable;
}, $span);
}
private function renderBrs(string $span): string
{
// Adding brs when a space is at the end of a line
return (string) preg_replace('/ \n/', $this->br(), $span);
}
private function renderTokens(string $span): string
{
foreach ($this->span->getTokens() as $token) {
$span = $this->renderToken($token, $span);
}
return $span;
}
private function renderToken(SpanToken $spanToken, string $span): string
{
switch ($spanToken->getType()) {
case SpanToken::TYPE_LITERAL:
return $this->renderLiteral($spanToken, $span);
case SpanToken::TYPE_REFERENCE:
return $this->renderReference($spanToken, $span);
case SpanToken::TYPE_LINK:
return $this->renderLink($spanToken, $span);
}
throw new InvalidArgumentException(sprintf('Unknown token type %s', $spanToken->getType()));
}
private function renderLiteral(SpanToken $spanToken, string $span): string
{
return str_replace(
$spanToken->getId(),
$this->literal($spanToken->get('text')),
$span
);
}
private function renderReference(SpanToken $spanToken, string $span): string
{
$reference = $this->environment->resolve($spanToken->get('section'), $spanToken->get('url'));
if ($reference === null) {
$this->environment->addInvalidLink(new InvalidLink($spanToken->get('url')));
return str_replace($spanToken->getId(), $spanToken->get('text'), $span);
}
$link = $this->reference($reference, $spanToken->getTokenData());
return str_replace($spanToken->getId(), $link, $span);
}
private function renderLink(SpanToken $spanToken, string $span): string
{
$url = $spanToken->get('url');
$link = $spanToken->get('link');
if ($url === '') {
$url = $this->environment->getLink($link);
if ($url === '') {
$metaEntry = $this->environment->getMetaEntry();
if ($metaEntry !== null && $metaEntry->hasTitle($link)) {
// A strangely-complex way to simply get the current relative URL
// For example, if the current page is "reference/page", then
// this would return "page" so the final URL is href="page#some-anchor".
$currentRelativeUrl = $this->environment->relativeUrl('/' . $metaEntry->getUrl());
$url = $currentRelativeUrl . '#' . Environment::slugify($link);
}
}
if ($url === '') {
$this->environment->addInvalidLink(new InvalidLink($link));
return str_replace($spanToken->getId(), $link, $span);
}
}
$link = $this->link($url, $this->renderSyntaxes($link));
return str_replace($spanToken->getId(), $link, $span);
}
}