1
0
mirror of https://github.com/erusev/parsedown.git synced 2023-08-10 21:13:06 +03:00

Implement Link

This commit is contained in:
Aidan Woods 2019-01-20 02:35:32 +00:00
parent 79a38a1ebb
commit dad0088adb
No known key found for this signature in database
GPG Key ID: 9A6A8EFAA512BBB9
2 changed files with 128 additions and 64 deletions

View File

@ -0,0 +1,128 @@
<?php
namespace Erusev\Parsedown\Components\Inlines;
use Erusev\Parsedown\AST\Handler;
use Erusev\Parsedown\AST\StateRenderable;
use Erusev\Parsedown\Components\Inline;
use Erusev\Parsedown\Configurables\DefinitionBook;
use Erusev\Parsedown\Configurables\SafeMode;
use Erusev\Parsedown\Html\Renderables\Element;
use Erusev\Parsedown\Html\Renderables\Text;
use Erusev\Parsedown\Parsedown;
use Erusev\Parsedown\Parsing\Excerpt;
use Erusev\Parsedown\State;
/** @psalm-type _Metadata=array{href: string, title?: string} */
final class Link implements Inline
{
use WidthTrait, DefaultBeginPosition;
/** @var string */
private $label;
/** @var _Metadata */
private $attributes;
/**
* @param string $label
* @param _Metadata $attributes
* @param int $width
*/
public function __construct($label, $attributes, $width)
{
$this->label = $label;
$this->attributes = $attributes;
$this->width = $width;
}
/**
* @param Excerpt $Excerpt
* @param State $State
* @return static|null
*/
public static function build(Excerpt $Excerpt, State $State)
{
$remainder = $Excerpt->text();
if (! \preg_match('/\[((?:[^][]++|(?R))*+)\]/', $remainder, $matches)) {
return null;
}
$rawLabelPart = $matches[0];
$label = $matches[1];
/** @var _Metadata|null */
$attributes = null;
$extent = \strlen($matches[0]);
$remainder = \substr($remainder, $extent);
if (\preg_match('/^[(]\s*+((?:[^ ()]++|[(][^ )]+[)])++)(?:[ ]+("[^"]*+"|\'[^\']*+\'))?\s*+[)]/', $remainder, $matches)) {
$attributes = ['href' => $matches[1]];
if (isset($matches[2])) {
$attributes['title'] = \substr($matches[2], 1, - 1);
}
$extent += \strlen($matches[0]);
} else {
if (\preg_match('/^\s*\[(.*?)\]/', $remainder, $matches)) {
$definition = \strlen($matches[1]) ? $matches[1] : $label;
$definition = \strtolower($definition);
$extent += \strlen($matches[0]);
} else {
$definition = \strtolower($label);
}
$data = $State->getOrDefault(DefinitionBook::class)->lookup($definition);
if (! isset($data)) {
return null;
}
$attributes = ['href' => $data['url']];
if (isset($data['title'])) {
$attributes['title'] = $data['title'];
}
}
return new self($label, $attributes, $extent);
}
/** @return string */
public function label()
{
return $this->label;
}
/** @return _Metadata */
public function attributes()
{
return $this->attributes;
}
/**
* @return Handler<Element|Text>
*/
public function stateRenderable(Parsedown $Parsedown)
{
return new Handler(
/** @return Element|Text */
function (State $State) use ($Parsedown) {
$attributes = $this->attributes;
if ($State->getOrDefault(SafeMode::class)->enabled()) {
$attributes['href'] = Element::filterUnsafeUrl($attributes['href']);
}
return new Element(
'a',
$attributes,
$State->applyTo($Parsedown->lineElements($this->label))
);
}
);
}
}

View File

@ -444,70 +444,6 @@ class Parsedown
return $Inline;
}
protected function inlineLink($Excerpt)
{
$Element = [
'name' => 'a',
'handler' => [
'function' => 'lineElements',
'argument' => null,
'destination' => 'elements',
],
'nonNestables' => ['Url', 'Link'],
'attributes' => [
'href' => null,
'title' => null,
],
];
$extent = 0;
$remainder = $Excerpt['text'];
if (\preg_match('/\[((?:[^][]++|(?R))*+)\]/', $remainder, $matches)) {
$Element['handler']['argument'] = $matches[1];
$extent += \strlen($matches[0]);
$remainder = \substr($remainder, $extent);
} else {
return;
}
if (\preg_match('/^[(]\s*+((?:[^ ()]++|[(][^ )]+[)])++)(?:[ ]+("[^"]*+"|\'[^\']*+\'))?\s*+[)]/', $remainder, $matches)) {
$Element['attributes']['href'] = $matches[1];
if (isset($matches[2])) {
$Element['attributes']['title'] = \substr($matches[2], 1, - 1);
}
$extent += \strlen($matches[0]);
} else {
if (\preg_match('/^\s*\[(.*?)\]/', $remainder, $matches)) {
$definition = \strlen($matches[1]) ? $matches[1] : $Element['handler']['argument'];
$definition = \strtolower($definition);
$extent += \strlen($matches[0]);
} else {
$definition = \strtolower($Element['handler']['argument']);
}
if (! isset($this->DefinitionData['Reference'][$definition])) {
return;
}
$Definition = $this->DefinitionData['Reference'][$definition];
$Element['attributes']['href'] = $Definition['url'];
$Element['attributes']['title'] = $Definition['title'];
}
return [
'extent' => $extent,
'element' => $Element,
];
}
protected function inlineMarkup($Excerpt)
{
if ($this->markupEscaped or $this->safeMode or \strpos($Excerpt['text'], '>') === false) {