src/includes/classes/Core/Utils/GitHub.php
public function mdIssueRefs($value, array $args = [])
    {
        if (is_array($value) || is_object($value)) {
            foreach ($value as $_key => &$_value) {
                $_value = $this->mdIssueRefs($_value, $args);
            } // unset($_key, $_value);
            return $value;
        }
        $markdown = (string) $value;

        if (!isset($markdown[0])) {
            return $markdown;
        }
        $default_args = [
            'current_owner' => '',
            'current_repo'  => '',
        ];
        $args += $default_args; // Merge defaults.

        $current_owner = (string) $args['current_owner'];
        $current_repo  = (string) $args['current_repo'];
        $have_currents = $current_owner && $current_repo;

        $current_owner_regex = '(?<owner>'.$this->c::escRegex($current_owner).')';
        $owner_regex         = '(?<owner>[a-z][a-z0-9_\-]*?[a-z0-9])';
        $repo_regex          = '(?<repo>[a-z][a-z0-9_\-]*?[a-z0-9])';
        $issue_regex         = '(?<issue>[0-9]+)';
        $comment_regex       = '(?<comment>#[^#\s]+)?';

        $pull_url_regex            = '/(?<=^|[\s;,<]|(?<!\])\()https?\:\/\/github\.com\/'.$owner_regex.'\/'.$repo_regex.'\/(?<is_pull>pull)\/'.$issue_regex.$comment_regex.'(?=$|[\s.!?;,)>])/ui';
        $issue_url_regex           = '/(?<=^|[\s;,<]|(?<!\])\()https?\:\/\/github\.com\/'.$owner_regex.'\/'.$repo_regex.'\/issues\/'.$issue_regex.$comment_regex.'(?=$|[\s.!?;,)>])/ui';
        $owner_repo_issue_regex    = '/(?<=^|[\s;,]|(?<!\])\()'.$owner_regex.'\/'.$repo_regex.'#'.$issue_regex.'(?=$|[\s.!?;,)])/ui';
        $current_owner_issue_regex = $have_currents ? '/(?<=^|[\s;,]|(?<!\])\()'.$current_owner_regex.'#'.$issue_regex.'(?=$|[\s.!?;,)])/ui' : '';
        $issue_number_regex        = $have_currents ? '/(?<=^|[\s;,]|(?<!\])\()#'.$issue_regex.'(?=$|[\s.!?;,)])/ui' : '';

        $Tokenizer = $this->c::tokenize($markdown, ['md-fences']);
        $markdown  = &$Tokenizer->getString(); // By reference.

        foreach ([$pull_url_regex, $issue_url_regex, $owner_repo_issue_regex, $current_owner_issue_regex, $issue_number_regex] as $_regex) {
            if (!$_regex) { // Skip if empty; e.g., currents not available.
                continue; // Not possible; regex is empty.
            }
            $markdown = preg_replace_callback($_regex, function ($m) use ($current_owner, $current_repo, $have_currents) {
                if (!$have_currents && (empty($m['owner']) || empty($m['repo']))) {
                    return $m[0]; // Not possible.
                }
                $is_pull = isset($m['is_pull']);
                $owner = !empty($m['owner']) ? $m['owner'] : $current_owner;
                $repo = !empty($m['repo']) ? $m['repo'] : $current_repo;
                $number = $m['issue']; // Always have this.
                $comment = $m['comment'] ?? '';

                $url = 'https://github.com/'.urlencode($owner).
                       '/'.urlencode($repo).'/'.($is_pull ? 'pull' : 'issues').
                       '/'.urlencode($number).$comment;

                if ($have_currents && $owner === $current_owner) {
                    if ($repo === $current_repo) {
                        return '['.$this->c::escHtmlChars('#'.$number.($comment ? ' (comment)' : '')).']('.$url.')';
                    } else {
                        return '['.$this->c::escHtmlChars($repo.'#'.$number.($comment ? ' (comment)' : '')).']('.$url.')';
                    }
                } else {
                    return '['.$this->c::escHtmlChars($owner.'/'.$repo.'#'.$number.($comment ? ' (comment)' : '')).']('.$url.')';
                }
            }, $markdown);
        } // unset($_regex); // Housekeeping.

        return $markdown = $Tokenizer->restoreGetString();
    }
public function mdIssueRefs($value, array $args = [])
    {
        if (is_array($value) || is_object($value)) {
            foreach ($value as $_key => &$_value) {
                $_value = $this->mdIssueRefs($_value, $args);
            } // unset($_key, $_value);
            return $value;
        }
        $markdown = (string) $value;

        if (!isset($markdown[0])) {
            return $markdown;
        }
        $default_args = [
            'current_owner' => '',
            'current_repo'  => '',
        ];
        $args += $default_args; // Merge defaults.

        $current_owner = (string) $args['current_owner'];
        $current_repo  = (string) $args['current_repo'];
        $have_currents = $current_owner && $current_repo;

        $current_owner_regex = '(?<owner>'.$this->c::escRegex($current_owner).')';
        $owner_regex         = '(?<owner>[a-z][a-z0-9_\-]*?[a-z0-9])';
        $repo_regex          = '(?<repo>[a-z][a-z0-9_\-]*?[a-z0-9])';
        $issue_regex         = '(?<issue>[0-9]+)';
        $comment_regex       = '(?<comment>#[^#\s]+)?';

        $pull_url_regex            = '/(?<=^|[\s;,<]|(?<!\])\()https?\:\/\/github\.com\/'.$owner_regex.'\/'.$repo_regex.'\/(?<is_pull>pull)\/'.$issue_regex.$comment_regex.'(?=$|[\s.!?;,)>])/ui';
        $issue_url_regex           = '/(?<=^|[\s;,<]|(?<!\])\()https?\:\/\/github\.com\/'.$owner_regex.'\/'.$repo_regex.'\/issues\/'.$issue_regex.$comment_regex.'(?=$|[\s.!?;,)>])/ui';
        $owner_repo_issue_regex    = '/(?<=^|[\s;,]|(?<!\])\()'.$owner_regex.'\/'.$repo_regex.'#'.$issue_regex.'(?=$|[\s.!?;,)])/ui';
        $current_owner_issue_regex = $have_currents ? '/(?<=^|[\s;,]|(?<!\])\()'.$current_owner_regex.'#'.$issue_regex.'(?=$|[\s.!?;,)])/ui' : '';
        $issue_number_regex        = $have_currents ? '/(?<=^|[\s;,]|(?<!\])\()#'.$issue_regex.'(?=$|[\s.!?;,)])/ui' : '';

        $Tokenizer = $this->c::tokenize($markdown, ['md-fences']);
        $markdown  = &$Tokenizer->getString(); // By reference.

        foreach ([$pull_url_regex, $issue_url_regex, $owner_repo_issue_regex, $current_owner_issue_regex, $issue_number_regex] as $_regex) {
            if (!$_regex) { // Skip if empty; e.g., currents not available.
                continue; // Not possible; regex is empty.
            }
            $markdown = preg_replace_callback($_regex, function ($m) use ($current_owner, $current_repo, $have_currents) {
                if (!$have_currents && (empty($m['owner']) || empty($m['repo']))) {
                    return $m[0]; // Not possible.
                }
                $is_pull = isset($m['is_pull']);
                $owner = !empty($m['owner']) ? $m['owner'] : $current_owner;
                $repo = !empty($m['repo']) ? $m['repo'] : $current_repo;
                $number = $m['issue']; // Always have this.
                $comment = $m['comment'] ?? '';

                $url = 'https://github.com/'.urlencode($owner).
                       '/'.urlencode($repo).'/'.($is_pull ? 'pull' : 'issues').
                       '/'.urlencode($number).$comment;

                if ($have_currents && $owner === $current_owner) {
                    if ($repo === $current_repo) {
                        return '['.$this->c::escHtmlChars('#'.$number.($comment ? ' (comment)' : '')).']('.$url.')';
                    } else {
                        return '['.$this->c::escHtmlChars($repo.'#'.$number.($comment ? ' (comment)' : '')).']('.$url.')';
                    }
                } else {
                    return '['.$this->c::escHtmlChars($owner.'/'.$repo.'#'.$number.($comment ? ' (comment)' : '')).']('.$url.')';
                }
            }, $markdown);
        } // unset($_regex); // Housekeeping.

        return $markdown = $Tokenizer->restoreGetString();
    }
Markdown issue refs.

@since 170124.74961 GitHub utils.

@param mixed $value Input value.
@param array $args  Additional args.

@return string|array|object Markdown'd issue refs.