diff --git a/packages/guides-restructured-text/src/RestructuredText/Directives/ImageDirective.php b/packages/guides-restructured-text/src/RestructuredText/Directives/ImageDirective.php
index 855b5ec1b..29730bad2 100644
--- a/packages/guides-restructured-text/src/RestructuredText/Directives/ImageDirective.php
+++ b/packages/guides-restructured-text/src/RestructuredText/Directives/ImageDirective.php
@@ -14,12 +14,21 @@
namespace phpDocumentor\Guides\RestructuredText\Directives;
use phpDocumentor\Guides\Nodes\ImageNode;
+use phpDocumentor\Guides\Nodes\Inline\DocReferenceNode;
+use phpDocumentor\Guides\Nodes\Inline\HyperLinkNode;
+use phpDocumentor\Guides\Nodes\Inline\LinkInlineNode;
+use phpDocumentor\Guides\Nodes\Inline\ReferenceNode;
use phpDocumentor\Guides\Nodes\Node;
use phpDocumentor\Guides\ReferenceResolvers\DocumentNameResolverInterface;
use phpDocumentor\Guides\RestructuredText\Parser\BlockContext;
use phpDocumentor\Guides\RestructuredText\Parser\Directive;
use function dirname;
+use function filter_var;
+use function preg_match;
+
+use const FILTER_VALIDATE_EMAIL;
+use const FILTER_VALIDATE_URL;
/**
* Renders an image, example :
@@ -30,6 +39,12 @@
*/
final class ImageDirective extends BaseDirective
{
+ /** @see https://regex101.com/r/9dUrzu/3 */
+ public const REFERENCE_REGEX = '/^([a-zA-Z0-9-_]+)_$/';
+
+ /** @see https://regex101.com/r/6vPoiA/2 */
+ public const REFERENCE_ESCAPED_REGEX = '/^`([^`]+)`_$/';
+
public function __construct(
private readonly DocumentNameResolverInterface $documentNameResolver,
) {
@@ -45,11 +60,38 @@ public function processNode(
BlockContext $blockContext,
Directive $directive,
): Node {
- return new ImageNode(
+ $node = new ImageNode(
$this->documentNameResolver->absoluteUrl(
dirname($blockContext->getDocumentParserContext()->getContext()->getCurrentAbsolutePath()),
$directive->getData(),
),
);
+ if ($directive->hasOption('target')) {
+ $targetReference = (string) $directive->getOption('target')->getValue();
+ $node->setTarget($this->resolveLinkTarget($targetReference));
+ }
+
+ return $node;
+ }
+
+ private function resolveLinkTarget(string $targetReference): LinkInlineNode
+ {
+ if (filter_var($targetReference, FILTER_VALIDATE_EMAIL)) {
+ return new HyperLinkNode('', $targetReference);
+ }
+
+ if (filter_var($targetReference, FILTER_VALIDATE_URL)) {
+ return new HyperLinkNode('', $targetReference);
+ }
+
+ if (preg_match(self::REFERENCE_REGEX, $targetReference, $matches)) {
+ return new ReferenceNode($matches[1], '');
+ }
+
+ if (preg_match(self::REFERENCE_ESCAPED_REGEX, $targetReference, $matches)) {
+ return new ReferenceNode($matches[1], '');
+ }
+
+ return new DocReferenceNode($targetReference, '');
}
}
diff --git a/packages/guides/resources/config/guides.php b/packages/guides/resources/config/guides.php
index 94e69a63e..a69251838 100644
--- a/packages/guides/resources/config/guides.php
+++ b/packages/guides/resources/config/guides.php
@@ -28,6 +28,7 @@
use phpDocumentor\Guides\ReferenceResolvers\DocumentNameResolverInterface;
use phpDocumentor\Guides\ReferenceResolvers\EmailReferenceResolver;
use phpDocumentor\Guides\ReferenceResolvers\ExternalReferenceResolver;
+use phpDocumentor\Guides\ReferenceResolvers\ImageReferenceResolverPreRender;
use phpDocumentor\Guides\ReferenceResolvers\Interlink\DefaultInventoryLoader;
use phpDocumentor\Guides\ReferenceResolvers\Interlink\DefaultInventoryRepository;
use phpDocumentor\Guides\ReferenceResolvers\Interlink\InventoryLoader;
@@ -192,6 +193,8 @@
->set(ReferenceResolverPreRender::class)
->tag('phpdoc.guides.prerenderer')
+ ->set(ImageReferenceResolverPreRender::class)
+ ->tag('phpdoc.guides.prerenderer')
->set(InMemoryRendererFactory::class)
->arg('$renderSets', tagged_iterator('phpdoc.renderer.typerenderer', 'format'))
diff --git a/packages/guides/resources/template/html/body/image.html.twig b/packages/guides/resources/template/html/body/image.html.twig
index 9bc9eeb05..9564e81cf 100644
--- a/packages/guides/resources/template/html/body/image.html.twig
+++ b/packages/guides/resources/template/html/body/image.html.twig
@@ -1,3 +1,4 @@
+{% if node.target %}{% endif %}
+{% if node.target %}{% endif %}
diff --git a/packages/guides/src/Nodes/ImageNode.php b/packages/guides/src/Nodes/ImageNode.php
index cb4f15256..14cbd9a57 100644
--- a/packages/guides/src/Nodes/ImageNode.php
+++ b/packages/guides/src/Nodes/ImageNode.php
@@ -13,6 +13,19 @@
namespace phpDocumentor\Guides\Nodes;
+use phpDocumentor\Guides\Nodes\Inline\LinkInlineNode;
+
final class ImageNode extends TextNode
{
+ public LinkInlineNode|null $target = null;
+
+ public function getTarget(): LinkInlineNode|null
+ {
+ return $this->target;
+ }
+
+ public function setTarget(LinkInlineNode|null $target): void
+ {
+ $this->target = $target;
+ }
}
diff --git a/packages/guides/src/ReferenceResolvers/ImageReferenceResolverPreRender.php b/packages/guides/src/ReferenceResolvers/ImageReferenceResolverPreRender.php
new file mode 100644
index 000000000..bb211a428
--- /dev/null
+++ b/packages/guides/src/ReferenceResolvers/ImageReferenceResolverPreRender.php
@@ -0,0 +1,62 @@
+getTarget() === null) {
+ return $node;
+ }
+
+ $referenceLinkNode = $node->getTarget();
+ $messages = new Messages();
+ $resolved = $this->referenceResolver->resolve($referenceLinkNode, $renderContext, $messages);
+ if (!$resolved) {
+ $this->logger->warning(
+ $messages->getLastWarning()?->getMessage() ?? sprintf(
+ 'Target %s of image could not be resolved in %s',
+ $referenceLinkNode->getTargetReference(),
+ $renderContext->getCurrentFileName(),
+ ),
+ array_merge($renderContext->getLoggerInformation(), $messages->getLastWarning()?->getDebugInfo() ?? []),
+ );
+ }
+
+ return $node;
+ }
+}
diff --git a/tests/Integration/tests/images/image-target/expected/images/hero2-illustration.svg b/tests/Integration/tests/images/image-target/expected/images/hero2-illustration.svg
new file mode 100644
index 000000000..002f8feff
--- /dev/null
+++ b/tests/Integration/tests/images/image-target/expected/images/hero2-illustration.svg
@@ -0,0 +1,180 @@
+
diff --git a/tests/Integration/tests/images/image-target/expected/index.html b/tests/Integration/tests/images/image-target/expected/index.html
new file mode 100644
index 000000000..8834b0852
--- /dev/null
+++ b/tests/Integration/tests/images/image-target/expected/index.html
@@ -0,0 +1,61 @@
+
+
Lorem Ipsum Dolor.
+