in src/inlines/Link.php [67:224]
public static function consumeLinkish(
Context $ctx,
string $string,
int $offset,
keyset<classname<Inline>> $inners,
): ?(Link, int) {
if ($string[$offset] !== '[') {
return null;
}
$offset++;
$depth = 1;
$len = Str\length($string);
$key = '';
$start = $offset;
for ($offset = $offset; $offset < $len; ++$offset) {
$chr = $string[$offset];
if ($chr === ']') {
--$depth;
if ($depth === 0) {
$offset;
break;
}
continue;
}
if ($chr === '[') {
if (
$string[$offset - 1] !== '!' &&
!C\contains_key($inners, Link::class) &&
self::consume($ctx, $string, $offset) !== null
) {
return null;
}
++$depth;
continue;
}
if ($chr === '\\') {
if ($offset + 1 < $len) {
$next = $string[$offset + 1];
if (C\contains_key(ASCII_PUNCTUATION, $next)) {
++$offset;
continue;
}
}
}
$result = null;
foreach ($inners as $type) {
$result = $type::consume($ctx, $string, $offset);
if ($result !== null) {
break;
}
}
if ($result !== null) {
list($_, $offset) = $result;
--$offset;
continue;
}
}
if ($depth !== 0) {
return null;
}
$key = Str\slice($string, $start, $offset - $start);
$offset++;
$text = parse($ctx, $key);
if (Str\slice($string, $offset, 2) === '[]') {
// collapsed reference link
$def = $ctx->getBlockContext()->getLinkReferenceDefinition($key);
if ($def === null) {
return null;
}
return tuple(
new self($text, $def->getDestination(), $def->getTitle()),
$offset + 2,
);
}
if ($offset < $len && $string[$offset] === '[') {
// full reference link
$depth = 1;
$matched = '';
$offset++;
for ($i = 0; $i < 999 && $offset < $len; ++$i, ++$offset) {
$char = $string[$offset];
if ($char === '[') {
++$depth;
$matched .= $char;
continue;
}
if ($char === ']') {
--$depth;
if ($depth === 0) {
break;
}
$matched .= $char;
continue;
}
if ($char === '\\') {
if ($offset + 1 >= $len) {
return null;
}
$matched .= $char.$string[$offset + 1];
++$offset;
continue;
}
$matched .= $char;
}
if ($depth !== 0) {
return null;
}
$key = LinkReferenceDefinition::normalizeKey($matched);
$def = $ctx->getBlockContext()->getLinkReferenceDefinition($key);
if ($def === null) {
return null;
}
return tuple(
new self($text, $def->getDestination(), $def->getTitle()),
$offset + 1,
);
}
$result = self::consumeDestinationAndTitle($string, $offset);
if ($result !== null) {
list($destination, $title, $offset) = $result;
if (!$ctx->areAllURISchemesEnabled()) {
$allowed_uri_schemes = $ctx->getAllowedURISchemes();
if (
!C\any(
$allowed_uri_schemes,
$elem ==> Str\starts_with_ci($destination, $elem.':'),
)
) {
return null;
}
}
return tuple(new self($text, $destination, $title), $offset);
}
// shortcut reference link?
$def = $ctx->getBlockContext()->getLinkReferenceDefinition($key);
if ($def === null) {
return null;
}
return tuple(
new self($text, $def->getDestination(), $def->getTitle()),
$offset,
);
}