) $placeholders = []; $html = preg_replace_callback( '/(.*?)<\/span>/', function ($matches) use (&$placeholders) { $key = '___TTS_' . count($placeholders) . '___'; $placeholders[$key] = $matches[0]; return $key; }, $html ); $html = htmlspecialchars($html, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); // Restore preserved tags foreach ($placeholders as $key => $original) { $html = str_replace($key, $original, $html); } // Headers (h1-h4) $html = preg_replace('/^### (.+)$/m', '

$1

', $html); $html = preg_replace('/^## (.+)$/m', '

$1

', $html); $html = preg_replace('/^# (.+)$/m', '

$1

', $html); // Bold and italic $html = preg_replace('/\*\*\*(.+?)\*\*\*/', '$1', $html); $html = preg_replace('/\*\*(.+?)\*\*/', '$1', $html); $html = preg_replace('/\*(.+?)\*/', '$1', $html); // Inline code $html = preg_replace('/`(.+?)`/', '$1', $html); // Lines starting with dashes or asterisks (unordered list) $html = preg_replace('/^[-*] (.+)$/m', '
  • $1
  • ', $html); // Wrap consecutive
  • in