feat(markdown): add enhanced code blocks with syntax highlighting
- Add codeblock.go for custom Goldmark renderer - Add code block header with language icon, filename, copy button - Use Chroma for syntax highlighting with class-based output - Add GenerateChromaCSS for theme CSS generation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
6e2959f619
commit
771ff7615a
4 changed files with 323 additions and 4 deletions
81
internal/markdown/markdown_test.go
Normal file
81
internal/markdown/markdown_test.go
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
package markdown
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCodeBlockWithTitle(t *testing.T) {
|
||||
input := "```typescript title=\"app.ts\"\nconst x = 1\n```"
|
||||
|
||||
result, err := Render(input)
|
||||
if err != nil {
|
||||
t.Fatalf("Render failed: %v", err)
|
||||
}
|
||||
|
||||
// Check that the code-block wrapper is present
|
||||
if !strings.Contains(result, `class="code-block"`) {
|
||||
t.Error("Expected code-block wrapper class")
|
||||
}
|
||||
|
||||
// Check that the header with title is present
|
||||
if !strings.Contains(result, `class="code-title"`) {
|
||||
t.Error("Expected code-title class")
|
||||
}
|
||||
|
||||
// Check that the title text is rendered
|
||||
if !strings.Contains(result, "app.ts") {
|
||||
t.Error("Expected title 'app.ts' in output")
|
||||
}
|
||||
|
||||
// Check that the icon is present
|
||||
if !strings.Contains(result, `class="code-icon"`) {
|
||||
t.Error("Expected code-icon class")
|
||||
}
|
||||
|
||||
// Check that the copy button is present
|
||||
if !strings.Contains(result, `class="code-copy"`) {
|
||||
t.Error("Expected code-copy class")
|
||||
}
|
||||
|
||||
t.Log("Rendered output:")
|
||||
t.Log(result)
|
||||
}
|
||||
|
||||
func TestCodeBlockWithoutTitle(t *testing.T) {
|
||||
input := "```go\nfmt.Println(\"hello\")\n```"
|
||||
|
||||
result, err := Render(input)
|
||||
if err != nil {
|
||||
t.Fatalf("Render failed: %v", err)
|
||||
}
|
||||
|
||||
// Should still have header with language
|
||||
if !strings.Contains(result, `class="code-block"`) {
|
||||
t.Error("Expected code-block wrapper for language-only block")
|
||||
}
|
||||
|
||||
if !strings.Contains(result, "go") {
|
||||
t.Error("Expected language 'go' in output")
|
||||
}
|
||||
|
||||
t.Log("Rendered output:")
|
||||
t.Log(result)
|
||||
}
|
||||
|
||||
func TestCodeBlockPlain(t *testing.T) {
|
||||
input := "```\nplain code\n```"
|
||||
|
||||
result, err := Render(input)
|
||||
if err != nil {
|
||||
t.Fatalf("Render failed: %v", err)
|
||||
}
|
||||
|
||||
// Plain code blocks without language/title should not have header
|
||||
if strings.Contains(result, `class="code-header"`) {
|
||||
t.Error("Plain code blocks should not have header")
|
||||
}
|
||||
|
||||
t.Log("Rendered output:")
|
||||
t.Log(result)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue