From 4b8b192b48f1df54f3c96f5860b0d15654df53b9 Mon Sep 17 00:00:00 2001
From: Aleksei Lebedev <1329824+LastDragon-ru@users.noreply.github.com>
Date: Thu, 15 Aug 2024 11:33:40 +0400
Subject: [PATCH] Mutations will not touch links label.
---
.../src/Markdown/Location/Location.php | 12 ++--
.../src/Markdown/Mutations/Move.php | 58 +++++++++----------
.../src/Markdown/Mutations/MoveTest.php | 4 +-
.../Markdown/Mutations/ReferencesInline.php | 28 +++------
.../Mutations/ReferencesInlineTest.php | 4 +-
.../Markdown/Mutations/ReferencesPrefix.php | 28 ++++-----
.../Mutations/ReferencesPrefixTest.php | 6 +-
packages/documentator/src/Markdown/Utils.php | 53 +++++++++--------
8 files changed, 88 insertions(+), 105 deletions(-)
diff --git a/packages/documentator/src/Markdown/Location/Location.php b/packages/documentator/src/Markdown/Location/Location.php
index ec56b41e2..1d1efbe86 100644
--- a/packages/documentator/src/Markdown/Location/Location.php
+++ b/packages/documentator/src/Markdown/Location/Location.php
@@ -11,12 +11,12 @@
*/
readonly class Location implements IteratorAggregate {
public function __construct(
- private int $startLine,
- private int $endLine,
- private int $offset = 0,
- private ?int $length = null,
- private int $startLinePadding = 0,
- private ?int $internalPadding = null,
+ public int $startLine,
+ public int $endLine,
+ public int $offset = 0,
+ public ?int $length = null,
+ public int $startLinePadding = 0,
+ public ?int $internalPadding = null,
) {
// empty
}
diff --git a/packages/documentator/src/Markdown/Mutations/Move.php b/packages/documentator/src/Markdown/Mutations/Move.php
index fbdac694d..ac5bab3be 100644
--- a/packages/documentator/src/Markdown/Mutations/Move.php
+++ b/packages/documentator/src/Markdown/Mutations/Move.php
@@ -4,25 +4,25 @@
use LastDragon_ru\LaraASP\Core\Utils\Path;
use LastDragon_ru\LaraASP\Documentator\Markdown\Contracts\Mutation;
+use LastDragon_ru\LaraASP\Documentator\Markdown\Data\Data;
+use LastDragon_ru\LaraASP\Documentator\Markdown\Data\Offset;
use LastDragon_ru\LaraASP\Documentator\Markdown\Document;
use LastDragon_ru\LaraASP\Documentator\Markdown\Nodes\Reference\Block as Reference;
use LastDragon_ru\LaraASP\Documentator\Markdown\Utils;
use League\CommonMark\Extension\CommonMark\Node\Inline\AbstractWebResource;
use League\CommonMark\Extension\CommonMark\Node\Inline\Image;
use League\CommonMark\Extension\CommonMark\Node\Inline\Link;
-use League\CommonMark\Extension\Table\TableCell;
use League\CommonMark\Node\Block\Document as DocumentNode;
-use League\CommonMark\Node\Inline\Text;
use Override;
use function dirname;
use function filter_var;
+use function ltrim;
use function mb_substr;
use function preg_match;
use function preg_quote;
use function rawurldecode;
use function rtrim;
-use function str_replace;
use function str_starts_with;
use function trim;
@@ -78,45 +78,41 @@ public function __invoke(Document $document, DocumentNode $node): array {
}
// Changes
- $text = null;
- $origin = trim((string) $document->getText($location));
+ $text = null;
if ($resource instanceof Link || $resource instanceof Image) {
- $title = (string) $resource->getTitle();
- $titleWrapper = mb_substr(rtrim(mb_substr($origin, 0, -1)), -1, 1);
- $label = (string) Utils::getChild($resource, Text::class)?->getLiteral();
- $target = rawurldecode($resource->getUrl());
- $target = Path::getPath($docDirectory, $target);
- $target = Path::getRelativePath($newDirectory, $target);
- $targetWrap = (bool) preg_match('/^!?\['.preg_quote($label, '/').']\(\s*getText($location));
+ $titleValue = (string) $resource->getTitle();
+ $titleWrapper = mb_substr(rtrim(mb_substr($origin, 0, -1)), -1, 1);
+ $title = Utils::getLinkTitle($resource, $titleValue, $titleWrapper);
+ $targetValue = rawurldecode($resource->getUrl());
+ $targetValue = Path::getPath($docDirectory, $targetValue);
+ $targetValue = Path::getRelativePath($newDirectory, $targetValue);
+ $targetWrap = mb_substr(ltrim(ltrim($origin, '(')), 0, 1) === '<';
+ $target = Utils::getLinkTarget($resource, $targetValue, $targetWrap);
+ $text = $title ? "({$target} {$title})" : "({$target})";
}
} elseif ($resource instanceof Reference) {
+ $origin = trim((string) $document->getText($location));
$label = $resource->getLabel();
- $title = $resource->getTitle();
+ $titleValue = $resource->getTitle();
$titleWrapper = mb_substr($origin, -1, 1);
- $target = rawurldecode($resource->getDestination());
- $target = Path::getPath($docDirectory, $target);
- $target = Path::getRelativePath($newDirectory, $target);
+ $title = Utils::getLinkTitle($resource, $titleValue, $titleWrapper);
+ $targetValue = rawurldecode($resource->getDestination());
+ $targetValue = Path::getPath($docDirectory, $targetValue);
+ $targetValue = Path::getRelativePath($newDirectory, $targetValue);
$targetWrap = (bool) preg_match('/^\['.preg_quote($resource->getLabel(), '/').']:\s+ ') text [title](<../from/file/a> (title))
+ text [_`link`_](../from/file/b '
') text [title](<../from/file/a> (title))
[mailto](mailto:mail@example.com) text [absolute](/path/to/file 'title')
text [external](https://example.com/).
@@ -203,7 +203,7 @@ public static function dataProviderInvoke(): array {
# General
Text text [tel](tel:+70000000000 "title") text [link](./file/a)
- text [link](file/b ' ') text [title](<./file/a> (title))
+ text [_`link`_](file/b ' ') text [title](<./file/a> (title))
[mailto](mailto:mail@example.com) text [absolute](/path/to/file 'title')
text [external](https://example.com/).
diff --git a/packages/documentator/src/Markdown/Mutations/ReferencesInline.php b/packages/documentator/src/Markdown/Mutations/ReferencesInline.php
index b9b0db4c5..507d99fe9 100644
--- a/packages/documentator/src/Markdown/Mutations/ReferencesInline.php
+++ b/packages/documentator/src/Markdown/Mutations/ReferencesInline.php
@@ -3,19 +3,18 @@
namespace LastDragon_ru\LaraASP\Documentator\Markdown\Mutations;
use LastDragon_ru\LaraASP\Documentator\Markdown\Contracts\Mutation;
+use LastDragon_ru\LaraASP\Documentator\Markdown\Data\Data;
+use LastDragon_ru\LaraASP\Documentator\Markdown\Data\Offset;
use LastDragon_ru\LaraASP\Documentator\Markdown\Document;
use LastDragon_ru\LaraASP\Documentator\Markdown\Nodes\Reference\Block as Reference;
use LastDragon_ru\LaraASP\Documentator\Markdown\Utils;
use League\CommonMark\Extension\CommonMark\Node\Inline\AbstractWebResource;
use League\CommonMark\Extension\CommonMark\Node\Inline\Image;
use League\CommonMark\Extension\CommonMark\Node\Inline\Link;
-use League\CommonMark\Extension\Table\TableCell;
use League\CommonMark\Node\Block\Document as DocumentNode;
-use League\CommonMark\Node\Inline\Text;
use Override;
use function rawurldecode;
-use function str_replace;
/**
* Inlines all references.
@@ -45,22 +44,13 @@ public function __invoke(Document $document, DocumentNode $node): array {
$text = null;
if ($reference instanceof Link || $reference instanceof Image) {
- $title = (string) $reference->getTitle();
- $label = (string) Utils::getChild($reference, Text::class)?->getLiteral();
- $target = rawurldecode($reference->getUrl());
+ $offset = Data::get($reference, Offset::class);
+ $location = $offset !== null ? Utils::getOffsetLocation($location, $offset) : null;
- if (Utils::getContainer($reference) instanceof TableCell) {
- $title = str_replace('|', '\\|', $title);
- $label = str_replace('|', '\\|', $label);
- $target = str_replace('|', '\\|', $target);
- }
-
- $text = $title
- ? Utils::getLink('[%s](%s %s)', $label, $target, $title, null, null)
- : Utils::getLink('[%s](%s)', $label, $target, '', null, null);
-
- if ($reference instanceof Image) {
- $text = "!{$text}";
+ if ($location !== null) {
+ $title = Utils::getLinkTitle($reference, (string) $reference->getTitle());
+ $target = Utils::getLinkTarget($reference, rawurldecode($reference->getUrl()));
+ $text = $title ? "({$target} {$title})" : "({$target})";
}
} elseif ($reference instanceof Reference) {
$text = '';
@@ -68,7 +58,7 @@ public function __invoke(Document $document, DocumentNode $node): array {
// skipped
}
- if ($text !== null) {
+ if ($location !== null && $text !== null) {
$changes[] = [$location, $text ?: null];
}
}
diff --git a/packages/documentator/src/Markdown/Mutations/ReferencesInlineTest.php b/packages/documentator/src/Markdown/Mutations/ReferencesInlineTest.php
index bf9d8d481..16241b106 100644
--- a/packages/documentator/src/Markdown/Mutations/ReferencesInlineTest.php
+++ b/packages/documentator/src/Markdown/Mutations/ReferencesInlineTest.php
@@ -22,7 +22,7 @@ public function testInvoke(): void {
<<<'MARKDOWN'
# Header
- Text text [link](https://example.com) text text [link][link] text
+ Text text [link](https://example.com) text text [`link`][link] text
text text ![image][image] text text.
![image][image]
@@ -55,7 +55,7 @@ public function testInvoke(): void {
<<<'MARKDOWN'
# Header
- Text text [link](https://example.com) text text [link](https://example.com) text
+ Text text [link](https://example.com) text text [`link`](https://example.com) text
text text ![image](https://example.com "image") text text.
![image](https://example.com "image")
diff --git a/packages/documentator/src/Markdown/Mutations/ReferencesPrefix.php b/packages/documentator/src/Markdown/Mutations/ReferencesPrefix.php
index 89d63bc4e..288bdf143 100644
--- a/packages/documentator/src/Markdown/Mutations/ReferencesPrefix.php
+++ b/packages/documentator/src/Markdown/Mutations/ReferencesPrefix.php
@@ -3,6 +3,8 @@
namespace LastDragon_ru\LaraASP\Documentator\Markdown\Mutations;
use LastDragon_ru\LaraASP\Documentator\Markdown\Contracts\Mutation;
+use LastDragon_ru\LaraASP\Documentator\Markdown\Data\Data;
+use LastDragon_ru\LaraASP\Documentator\Markdown\Data\Offset;
use LastDragon_ru\LaraASP\Documentator\Markdown\Document;
use LastDragon_ru\LaraASP\Documentator\Markdown\Location\Location;
use LastDragon_ru\LaraASP\Documentator\Markdown\Nodes\Reference\Block as Reference;
@@ -10,14 +12,11 @@
use League\CommonMark\Extension\CommonMark\Node\Inline\AbstractWebResource;
use League\CommonMark\Extension\CommonMark\Node\Inline\Image;
use League\CommonMark\Extension\CommonMark\Node\Inline\Link;
-use League\CommonMark\Extension\Table\TableCell;
use League\CommonMark\Node\Block\Document as DocumentNode;
-use League\CommonMark\Node\Inline\Text;
use Override;
use function hash;
use function mb_strlen;
-use function str_replace;
use function uniqid;
/**
@@ -56,19 +55,14 @@ public function __invoke(Document $document, DocumentNode $node): array {
$text = null;
if ($reference instanceof Link || $reference instanceof Image) {
- $label = (string) Utils::getChild($reference, Text::class)?->getLiteral();
- $target = Utils::getReference($reference)?->getLabel();
- $target = "{$prefix}-{$target}";
-
- if (Utils::getContainer($reference) instanceof TableCell) {
- $label = str_replace('|', '\\|', $label);
- $target = str_replace('|', '\\|', $target);
- }
-
- $text = Utils::getLink('[%s][%s]', $label, $target, '', null, null);
-
- if ($reference instanceof Image) {
- $text = "!{$text}";
+ $offset = Data::get($reference, Offset::class);
+ $location = $offset !== null ? Utils::getOffsetLocation($location, $offset) : null;
+
+ if ($location !== null) {
+ $target = Utils::getReference($reference)?->getLabel();
+ $target = "{$prefix}-{$target}";
+ $target = Utils::escapeTextInTableCell($reference, $target);
+ $text = "[{$target}]";
}
} elseif ($reference instanceof Reference) {
$coordinate = null;
@@ -90,7 +84,7 @@ public function __invoke(Document $document, DocumentNode $node): array {
// skipped
}
- if ($text !== null) {
+ if ($location !== null && $text !== null) {
$changes[] = [$location, $text];
}
}
diff --git a/packages/documentator/src/Markdown/Mutations/ReferencesPrefixTest.php b/packages/documentator/src/Markdown/Mutations/ReferencesPrefixTest.php
index f6d9d0629..e781cbfec 100644
--- a/packages/documentator/src/Markdown/Mutations/ReferencesPrefixTest.php
+++ b/packages/documentator/src/Markdown/Mutations/ReferencesPrefixTest.php
@@ -20,7 +20,7 @@ final class ReferencesPrefixTest extends TestCase {
private const Markdown = <<<'MARKDOWN'
# Header
- Text text [link](https://example.com) text text [link][link] text
+ Text text [link](https://example.com) text text [`link`][link] text
text text ![image][image] text text.
![image][image]
@@ -54,7 +54,7 @@ public function testInvoke(): void {
<<<'MARKDOWN'
# Header
- Text text [link](https://example.com) text text [link][a282e9c32e7eee65-link] text
+ Text text [link](https://example.com) text text [`link`][a282e9c32e7eee65-link] text
text text ![image][a282e9c32e7eee65-image] text text.
![image][a282e9c32e7eee65-image]
@@ -91,7 +91,7 @@ public function testInvokeExplicit(): void {
<<<'MARKDOWN'
# Header
- Text text [link](https://example.com) text text [link][prefix-link] text
+ Text text [link](https://example.com) text text [`link`][prefix-link] text
text text ![image][prefix-image] text text.
![image][prefix-image]
diff --git a/packages/documentator/src/Markdown/Utils.php b/packages/documentator/src/Markdown/Utils.php
index 7d92eed50..3566bbfd3 100644
--- a/packages/documentator/src/Markdown/Utils.php
+++ b/packages/documentator/src/Markdown/Utils.php
@@ -11,6 +11,7 @@
use LastDragon_ru\LaraASP\Documentator\Markdown\Data\Padding as DataPadding;
use LastDragon_ru\LaraASP\Documentator\Markdown\Location\Location;
use League\CommonMark\Extension\CommonMark\Node\Inline\AbstractWebResource;
+use League\CommonMark\Extension\Table\TableCell;
use League\CommonMark\Node\Block\AbstractBlock;
use League\CommonMark\Node\Block\Document;
use League\CommonMark\Node\Node;
@@ -19,10 +20,9 @@
use function mb_strpos;
use function preg_match;
-use function sprintf;
use function str_contains;
+use function str_replace;
use function strtr;
-use function trim;
/**
* @internal
@@ -143,6 +143,17 @@ public static function getLocation(Node $node): ?Location {
return $location;
}
+ public static function getOffsetLocation(Location $location, int $offset): Location {
+ return new Location(
+ $location->startLine,
+ $location->endLine,
+ $location->offset + $offset,
+ $location->length !== null ? $location->length - $offset : $location->length,
+ $location->startLinePadding,
+ $location->internalPadding,
+ );
+ }
+
public static function isReference(AbstractWebResource $node): bool {
return self::getReference($node) !== null;
}
@@ -154,33 +165,16 @@ public static function getReference(AbstractWebResource $node): ?ReferenceInterf
return $reference;
}
- public static function getLink(
- string $format,
- string $label,
- string $target,
- string $title,
- ?bool $wrapTarget,
- ?string $titleWrapper,
- ): string {
- $label = self::getLinkLabel($label);
- $title = self::getLinkTitle($title, $titleWrapper);
- $target = self::getLinkTarget($target, $wrapTarget);
- $link = trim(sprintf($format, $label, $target, $title));
-
- return $link;
- }
-
- private static function getLinkLabel(string $label): string {
- return strtr($label, ['[' => '\\\\[', ']' => '\\\\]']);
- }
-
- private static function getLinkTarget(string $target, ?bool $wrap): string {
- return ($wrap ?? preg_match('/\s/u', $target))
+ public static function getLinkTarget(Node $container, string $target, ?bool $wrap = null): string {
+ $target = ($wrap ?? preg_match('/\s/u', $target))
? '<'.strtr($target, ['<' => '\\<', '>' => '\\>']).'>'
: UrlEncoder::unescapeAndEncode($target);
+ $target = self::escapeTextInTableCell($container, $target);
+
+ return $target;
}
- private static function getLinkTitle(string $title, ?string $wrapper = null): string {
+ public static function getLinkTitle(Node $container, string $title, ?string $wrapper = null): string {
if (!$title) {
return '';
}
@@ -201,10 +195,19 @@ private static function getLinkTitle(string $title, ?string $wrapper = null): st
"'" => "'".strtr($title, $wrappers['"'])."'",
default => '('.strtr($title, $wrappers[')']).')',
};
+ $title = self::escapeTextInTableCell($container, $title);
return $title;
}
+ public static function escapeTextInTableCell(Node $container, string $text): string {
+ if (self::getContainer($container) instanceof TableCell) {
+ $text = str_replace('|', '\\|', $text);
+ }
+
+ return $text;
+ }
+
/**
* @template T of object
*