feat: CI/CD pipeline setup complete - Ansible playbooks updated, secrets configured, workflow ready
This commit is contained in:
@@ -54,9 +54,11 @@ final readonly class FileHighlighter
|
||||
// Optionen für Syntax-Highlighting
|
||||
$options = [
|
||||
'filename' => basename($filename), // Dateiname für Window-Bar
|
||||
'includeCss' => true, // CSS immer mit ausgeben für Error-Templates
|
||||
];
|
||||
if ($errorLine !== null) {
|
||||
$options['highlightLines'] = [$errorLine - 1];
|
||||
// highlightLines erwartet die tatsächliche Zeilennummer (nicht 0-basiert)
|
||||
$options['highlightLines'] = [$errorLine];
|
||||
}
|
||||
|
||||
return $highlighter->highlightFileSegment($code, $startLine, $options);
|
||||
|
||||
@@ -50,6 +50,19 @@ final class HtmlFormatter implements FormatterInterface
|
||||
// Group tokens by line for line number display
|
||||
$tokensByLine = $tokens->groupByLine();
|
||||
|
||||
// Fill in missing lines (empty lines between code)
|
||||
if (!empty($tokensByLine)) {
|
||||
$minLine = min(array_keys($tokensByLine));
|
||||
$maxLine = max(array_keys($tokensByLine));
|
||||
|
||||
for ($line = $minLine; $line <= $maxLine; $line++) {
|
||||
if (!isset($tokensByLine[$line])) {
|
||||
$tokensByLine[$line] = []; // Empty line
|
||||
}
|
||||
}
|
||||
ksort($tokensByLine); // Sort by line number
|
||||
}
|
||||
|
||||
foreach ($tokensByLine as $lineNum => $lineTokens) {
|
||||
$displayLineNum = $lineNum + $lineOffset;
|
||||
$isHighlighted = in_array($displayLineNum, $highlightLines, true);
|
||||
@@ -84,9 +97,20 @@ final class HtmlFormatter implements FormatterInterface
|
||||
*/
|
||||
public function formatSingle(Token $token, array $options = []): string
|
||||
{
|
||||
// Skip whitespace tokens unless explicitly requested
|
||||
if ($token->type === TokenType::WHITESPACE && ! ($options['showWhitespace'] ?? false)) {
|
||||
return htmlspecialchars($token->value, ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||
// Handle whitespace tokens
|
||||
if ($token->type === TokenType::WHITESPACE) {
|
||||
// Remove newlines from whitespace - we handle line breaks via <div class="line">
|
||||
$whitespace = str_replace(["\r\n", "\n", "\r"], '', $token->value);
|
||||
|
||||
// If empty after removing newlines, skip it
|
||||
if ($whitespace === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Wrap in span to ensure white-space: pre CSS is applied
|
||||
// Without the span, HTML collapses multiple spaces to one
|
||||
$escapedValue = htmlspecialchars($whitespace, ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||
return sprintf('<span class="token-whitespace">%s</span>', $escapedValue);
|
||||
}
|
||||
|
||||
$cssClass = $token->type->getCssClass();
|
||||
@@ -211,6 +235,12 @@ final class HtmlFormatter implements FormatterInterface
|
||||
|
||||
.syntax-highlight .code {
|
||||
flex: 1;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
/* Whitespace tokens must preserve spaces */
|
||||
.token-whitespace {
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
/* Token colors */
|
||||
@@ -290,6 +320,16 @@ CSS;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.syntax-highlight .code {
|
||||
flex: 1;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
/* Whitespace tokens must preserve spaces */
|
||||
.token-whitespace {
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
/* Light theme token colors */
|
||||
.token-keyword { color: #a626a4; font-weight: bold; }
|
||||
.token-class-name { color: #c18401; }
|
||||
@@ -343,7 +383,8 @@ CSS;
|
||||
$css .= " min-width: 3em;\n";
|
||||
$css .= " text-align: right;\n";
|
||||
$css .= "}\n";
|
||||
$css .= ".syntax-highlight .code { flex: 1; }\n\n";
|
||||
$css .= ".syntax-highlight .code { flex: 1; white-space: pre; }\n";
|
||||
$css .= ".token-whitespace { white-space: pre; }\n\n";
|
||||
|
||||
// Map theme keys to CSS token classes
|
||||
$tokenMapping = [
|
||||
|
||||
Reference in New Issue
Block a user