\n
" . self::escape(implode("\n", $code)) . "\n";
continue;
}
if (preg_match('/^\s{0,3}([-*_])(?:\s*\1){2,}\s*$/', $line)) {
$blocks[] = "\n" . self::paragraph(implode("\n", $quote)) . "\n"; continue; } $text = []; while ($i < $count && trim($lines[$i]) !== '' && !preg_match('/^(#{1,6}\s|```|\s*([-*+]|\d+[.)])\s|\s*>|\s{0,3}([-*_])(\s*\3){2,}\s*$)/', $lines[$i]) && !($i + 1 < $count && self::isTableRow($lines[$i]) && self::isTableRule($lines[$i + 1]))) { $text[] = trim($lines[$i]); $i++; } $blocks[] = self::paragraph(implode("\n", $text)); } return implode("\n\n", $blocks); } private static function isTableRow(string $line): bool { return str_contains($line, '|') && trim($line) !== '' && count(self::cells($line)) >= 2; } private static function isTableRule(string $line): bool { return (bool) preg_match('/^\s*\|?\s*:?-{2,}:?\s*(\|\s*:?-{2,}:?\s*)+\|?\s*$/', $line); } /** * @return list
" . str_replace("\n", '
', self::inline(trim($text))) . "
' . self::escape($m[1]) . '';
return "\u{E000}" . (count($code) - 1) . "\u{E001}";
}, $text);
$text = self::escape($text);
$text = (string) preg_replace_callback('/\[([^\]]+)\]\(([^)\s]+)\)/', static function (array $m): string {
$url = html_entity_decode($m[2], ENT_QUOTES | ENT_HTML5, 'UTF-8');
if (!preg_match('~^(https?://|/|#)~i', $url)) {
return $m[1];
}
return '' . $m[1] . '';
}, $text);
$text = (string) preg_replace('/\*\*(.+?)\*\*/', '$1', $text);
$text = (string) preg_replace('/(?$1', $text);
$text = (string) preg_replace('/(?$1', $text);
return (string) preg_replace_callback("/\u{E000}(\d+)\u{E001}/u", static fn (array $m): string => $code[(int) $m[1]] ?? '', $text);
}
private static function escape(string $text): string
{
return htmlspecialchars($text, ENT_QUOTES | ENT_HTML5, 'UTF-8');
}
}