public static function consumeLinkish()

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,
    );
  }