для 100% изоляции строки от массивов if (preg_match('/"(?P[^"]+)"/', $paramLine, $fileMatches)) { $filename = isset($fileMatches['fname']) ? (string)$fileMatches['fname'] : ''; // Вырезаем кавычки с файлом из параметров $paramLine = preg_replace('/"[^"]+"/', '', $paramLine); $parts = explode(' ', $paramLine); } foreach ($parts as $part) { $part = trim((string)$part); if (empty($part)) continue; if (str_contains($part, '=')) { $kv = explode('=', $part, 2); $key = isset($kv[0]) ? trim((string)$kv[0]) : ''; $val = isset($kv[1]) ? trim((string)$kv[1]) : ''; if ($key === 'highlight') $highlightLine = (int)$val; if ($key === 'start') $startLine = (int)$val; } elseif (empty($filename) && $part !== $lang) { $filename = $part; } } $lines = preg_split('/\r\n|\r|\n/', $code); if ($lines === false) { $lines = [$code]; } $firstCodeLineIdx = -1; foreach ($lines as $idx => $line) { $t = trim($line); if (!empty($t) && !str_starts_with($t, '*') && !str_starts_with($t, '/*') && !str_starts_with($t, '*/') && $t !== '/**') { $firstCodeLineIdx = $idx; break; } } $htmlLines = ''; $currentLineNum = $startLine; foreach ($lines as $idx => $line) { $trimmedLine = trim($line); $isCommentStar = str_starts_with($trimmedLine, '*') || str_starts_with($trimmedLine, '*/') || $trimmedLine === '/**' || ($trimmedLine === '' && $idx < $firstCodeLineIdx); $colorLine = $this->colorizeLine($line, $lang, $isCommentStar); $highlightClass = ($currentLineNum === $highlightLine) ? ' class="code-line-active"' : ''; $htmlLines .= ''; $htmlLines .= '' . $currentLineNum . ''; $htmlLines .= '' . ($colorLine === '' ? ' ' : $colorLine) . ''; $htmlLines .= ''; $currentLineNum++; } $html = '
'; if (!empty($filename)) { $html .= '
'; $html .= ''; $html .= htmlspecialchars($filename); $html .= '
'; } $html .= '
' . $htmlLines . '
'; $html .= '
'; return $html; } private function colorizeLine(string $line, string $lang, bool $isCommentStar): string { $line = htmlspecialchars($line, ENT_NOQUOTES, 'UTF-8'); if ($lang === 'php' || $lang === 'javascript' || $lang === 'js') { if ($isCommentStar) { return '' . $line . ''; } $commentPart = ''; if (preg_match('/(\/\/|#)(.*)$/', $line, $matches)) { $commentPart = isset($matches[0]) ? (string)$matches[0] : ''; $line = str_replace($commentPart, '%%DOKU_COMMENT_PLACEHOLDER%%', $line); } $line = preg_replace_callback('/(\'.*?\'|".*?")/', function(array $m): string { return '' . (isset($m[0]) ? $m[0] : '') . ''; }, $line); if ($lang === 'php') { $line = preg_replace_callback('/(?' . (isset($m[0]) ? $m[0] : '') . ''; }, $line); $controlKeywords = ['if', 'echo', 'return', 'function']; foreach ($controlKeywords as $word) { $line = preg_replace_callback('/\b' . $word . '\b/', function(array $m) use ($word): string { return '' . $word . ''; }, $line); } $funcKeywords = ['defined', 'die']; foreach ($funcKeywords as $word) { $line = preg_replace_callback('/\b' . $word . '\b/', function(array $m) use ($word): string { return '' . $word . ''; }, $line); } } // Обычная замена индексов массивов на безопасный вывод в скобках $line = preg_replace_callback('/([()\{\}\[\]])/', function(array $m): string { return '' . (isset($m[0]) ? $m[0] : '') . ''; }, $line); if (!empty($commentPart)) { $cleanComment = strip_tags($commentPart); $commentHtml = '' . $cleanComment . ''; $line = str_replace('%%DOKU_COMMENT_PLACEHOLDER%%', $commentHtml, $line); } } return $line; } }