' . self::e(implode("\n", $code)) . '';
$i++;
continue;
}
if (preg_match('/^(#{1,6})\s+(.+)$/', $line, $matches)) {
$level = strlen($matches[1]);
$html[] = '' . self::toHtml(implode("\n", $quote)) . ''; continue; } if (preg_match('/^\s*[-*+]\s+(.+)$/', $line)) { $items = []; while ($i < $count && preg_match('/^\s*[-*+]\s+(.+)$/', rtrim($lines[$i]), $matches)) { $items[] = '
' . self::inline(implode(' ', $paragraph)) . '
'; } return implode("\n", $html); } public static function excerpt(string $markdown, int $words = 28): string { $text = trim(preg_replace('/\s+/', ' ', strip_tags(self::toHtml($markdown))) ?? ''); if ($text === '') { return ''; } $parts = preg_split('/\s+/', $text) ?: []; if (count($parts) <= $words) { return $text; } return implode(' ', array_slice($parts, 0, $words)) . '...'; } private static function startsBlock(string $line): bool { return (bool) preg_match('/^(#{1,6}\s+|```|^\s*[-*+]\s+|^\s*\d+\.\s+|^\s*>\s?|(-{3,}|\*{3,}|_{3,})$)/', $line); } private static function inline(string $text): string { $placeholders = []; $text = preg_replace_callback('/`([^`]+)`/', static function (array $matches) use (&$placeholders): string { $key = "\x1A" . count($placeholders) . "\x1A"; $placeholders[$key] = '' . self::e($matches[1]) . '';
return $key;
}, $text) ?? $text;
$text = self::e($text);
$text = preg_replace_callback('/!\[([^\]]*)\]\(([^)\s]+)(?:\s+"([^"]+)")?\)/', static function (array $matches): string {
$title = isset($matches[3]) ? ' title="' . self::e($matches[3]) . '"' : '';
return '