Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
25b3bea
feat: render safe lazy Mermaid diagrams in commit blocks
Xauele Oct 26, 2026
5f36d27
feat(mermaid): align diagram palette with the native dev-null colors
Xauele Oct 27, 2026
649f9dd
feat(mermaid): apply native light/dark lane palette to rendered diagrams
Xauele Oct 27, 2026
76e4d8a
feat(mermaid): native code-block polish and readable scrolling on mobile
Xauele Oct 27, 2026
4928de0
fix(mermaid): parse SVG viewBox correctly for responsive diagrams
Xauele Oct 27, 2026
514e56e
test(mermaid): lock native light-dark palette and semantic decision c…
Xauele Oct 27, 2026
0a739cd
docs(mermaid): native palette and mobile pan behavior
Xauele Oct 27, 2026
02b7cb8
style(mermaid): apply native Vite+ formatting to visual polish
Xauele Oct 27, 2026
6133b4f
fix(mermaid): prevent clipped SVG labels across font contexts
Xauele Oct 27, 2026
4d44c3a
test(mermaid): keep image-safe font to avoid clipped labels
Xauele Oct 27, 2026
9387166
style(mermaid): preserve native right-aligned controls on desktop
Xauele Oct 27, 2026
968cda8
fix(mermaid): block embedded media, suppress errors and run TSX tests
Xauele Oct 27, 2026
1d6e8ec
test(mermaid): use real multiline fixtures for image and shape regres…
Xauele Oct 27, 2026
a7cd824
fix(test): allow Vitest runner in CI without Laravel HMR server
Xauele Oct 27, 2026
de06b3a
test(mermaid): require new React regressions without unrelated legacy…
Xauele Oct 27, 2026
cc29b6f
fix(mermaid): reject escaped YAML image keys before renderer
Xauele Oct 27, 2026
7c507c5
style(mermaid): match repository formatter
Xauele Oct 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions KNOWLEDGE_BASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,11 @@ Sources: [translation endpoint](app/Http/Controllers/CommitTranslationController

Commit and reply text supports inline code in backticks and fenced code blocks with syntax highlighting, a **Wrap lines** toggle, and a copy control. Text outside code supports emoji shortcodes, clickable URLs, and `@username` mentions. This is developer-oriented text formatting, not a full rich-text editor.

A fenced `mermaid` block in a commit or reply renders as a diagram when it approaches the viewport, including in the draft preview. Switch to **Show source** to read or copy the exact diagram definition; zoom controls appear on rendered diagrams. Colors follow /dev/null's blue primary and green/purple/amber lane palette in both themes. Wide diagrams scroll horizontally on narrow screens instead of shrinking their labels; Mermaid `classDef` supports explicit semantic colors for success and failure. The diagram engine is loaded on demand, not with every log page. Invalid and oversized definitions (more than 6,000 characters) remain readable as source rather than disappearing. Rendering runs in Mermaid's strict security mode and its SVG is shown as an inert image, not inserted as live HTML. Static excerpts and private Remotes keep ordinary code blocks. No images or other diagram data are saved separately.

Sources: [diagram component](resources/js/components/mermaid-diagram.tsx), [lazy renderer](resources/js/lib/mermaid-renderer.ts), [source parser](app/Services/CodeSpans.php).


In commits, replies, and remotes, start a line with `>` to render a quote block. Consecutive quoted lines stay together; an unquoted line ends the block. Quotes keep inline code, links, mentions, and emoji formatting. A `>` inside code or in the middle of a line stays literal.

Typing **@** in a composer opens developer suggestions. Use ↑/↓ to move, Enter or Tab to select, and Esc to dismiss. A bare @ suggests people you follow; typing more searches names and usernames. In replies, matching suggestions put the direct recipient first, then the root commit author, then other visible participants in that thread, followed by ordinary suggestions. Quotes prioritize only the quoted commit author. These priorities also apply to a bare @; typing a term still filters everyone, and yourself, muted developers, and blocked developers are excluded. In an org's messages, suggestions search the loaded member list instantly and update as membership refreshes. Suggestions are limited to the org's members, but you can still type anyone's handle yourself. Mentions link to profiles and can notify the mentioned developer after approval. Email addresses and scoped packages such as `@inertiajs/react` are not treated as mentions.
Expand Down
18 changes: 15 additions & 3 deletions app/Services/CodeSpans.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public function withoutCode(string $text): string
* Splits the text into prose, inline code and highlighted code blocks. The highlighter escapes the code, so a
* block's HTML is safe to render as is. The line breaks around a block are dropped, since it is a block already.
*
* @return list<array{type: 'text', text: string}|array{type: 'code', code: string}|array{type: 'block', language: string|null, html: string}>
* @return list<array{type: 'text', text: string}|array{type: 'code', code: string}|array{type: 'block', language: string|null, html: string, source?: string}>
*/
public function highlight(string $text): array
{
Expand Down Expand Up @@ -124,17 +124,29 @@ private function isBlock(?string $part): bool
}

/**
* @return array{type: 'block', language: string|null, html: string}
* @return array{type: 'block', language: string|null, html: string, source?: string}
*/
private function block(string $part): array
{
$lines = explode("\n", str_replace("\r\n", "\n", $part));
$language = strtok(mb_ltrim($lines[0], '`'), " \t") ?: null;
$source = implode("\n", array_slice($lines, 1, -1));

// Preserve exact Mermaid source instead of sending highlighted HTML to the diagram renderer.
// The regular HTML field stays escaped for previews and non-interactive surfaces.
if ($language !== null && mb_strtolower($language) === 'mermaid') {
return [
'type' => 'block',
'language' => $language,
'html' => htmlspecialchars($source, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'),
'source' => $source,
];
}

return [
'type' => 'block',
'language' => $language,
'html' => $this->highlighter->parse(implode("\n", array_slice($lines, 1, -1)), $language === null ? null : mb_strtolower($language)),
'html' => $this->highlighter->parse($source, $language === null ? null : mb_strtolower($language)),
];
}
}
Loading