diff --git a/framework/core/src/Extend/Link.php b/framework/core/src/Extend/Link.php new file mode 100644 index 000000000..b9c484414 --- /dev/null +++ b/framework/core/src/Extend/Link.php @@ -0,0 +1,62 @@ +setRel = $callable; + + return $this; + } + + public function setTarget(callable $callable): static + { + $this->setTarget = $callable; + + return $this; + } + + public function extend(Container $container, Extension $extension = null) + { + $siteUrl = $container->make(Config::class)->url(); + + (new Formatter)->render(function (Renderer $renderer, $context, string $xml) use ($siteUrl) { + return Utils::replaceAttributes($xml, 'URL', function ($attributes) use ($siteUrl) { + $uri = isset($attributes['url']) + ? new Uri($attributes['url']) + : null; + + $setRel = $this->setRel; + if ($setRel && $rel = $setRel($uri, $siteUrl, $attributes)) { + $attributes['rel'] = $rel; + } + + $setTarget = $this->setTarget; + if ($setTarget && $target = $setTarget($uri, $siteUrl, $attributes)) { + $attributes['target'] = $target; + } + + return $attributes; + }); + })->extend($container); + } +} diff --git a/framework/core/src/Formatter/Formatter.php b/framework/core/src/Formatter/Formatter.php index d2396ea27..7cd872401 100644 --- a/framework/core/src/Formatter/Formatter.php +++ b/framework/core/src/Formatter/Formatter.php @@ -9,10 +9,14 @@ namespace Flarum\Formatter; +use DOMDocument; +use DOMElement; use Illuminate\Contracts\Cache\Repository; use Psr\Http\Message\ServerRequestInterface; use s9e\TextFormatter\Configurator; +use s9e\TextFormatter\Renderer; use s9e\TextFormatter\Unparser; +use s9e\TextFormatter\Utils; class Formatter { @@ -98,7 +102,7 @@ class Formatter * Render parsed XML. * * @param string $xml - * @param mixed $context + * @param mixed|null $context * @param ServerRequestInterface|null $request * @return string */ @@ -110,6 +114,8 @@ class Formatter $xml = $callback($renderer, $context, $xml, $request); } + $xml = $this->configureDefaultsOnLinks($renderer, $xml, $context, $request); + return $renderer->render($xml); } @@ -174,11 +180,13 @@ class Formatter */ protected function configureExternalLinks(Configurator $configurator) { + /** @var DOMDocument $dom */ $dom = $configurator->tags['URL']->template->asDOM(); + /** @var DOMElement $a */ foreach ($dom->getElementsByTagName('a') as $a) { - $rel = $a->getAttribute('rel'); - $a->setAttribute('rel', "$rel nofollow ugc"); + $a->prependXslCopyOf('@target'); + $a->prependXslCopyOf('@rel'); } $dom->saveChanges(); @@ -217,7 +225,7 @@ class Formatter /** * Get the renderer. * - * @return \s9e\TextFormatter\Renderer + * @return Renderer */ protected function getRenderer() { @@ -239,4 +247,17 @@ class Formatter { return $this->getComponent('js'); } + + protected function configureDefaultsOnLinks( + Renderer $renderer, + string $xml, + $context = null, + ServerRequestInterface $request = null + ): string { + return Utils::replaceAttributes($xml, 'URL', function ($attributes) { + $attributes['rel'] = $attributes['rel'] ?? 'ugc nofollow'; + + return $attributes; + }); + } }