From e19a41c792dd1f92259522fae892e37f83e5a4c4 Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Mon, 1 Apr 2024 20:59:32 +0200 Subject: [PATCH] Implemented tables --- README.md | 2 +- Render.go | 66 +++++++++++++++++++++++++++++++++++++++++++++++--- Render_test.go | 5 ++++ 3 files changed, 68 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c5f42be..cbadd97 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ coverage: 100.0% of statements ## Benchmarks ``` -BenchmarkSmall-12 2585194 462.4 ns/op 248 B/op 5 allocs/op +BenchmarkSmall-12 2411152 489.1 ns/op 248 B/op 5 allocs/op ``` ## License diff --git a/Render.go b/Render.go index d13efe2..a9c7a49 100644 --- a/Render.go +++ b/Render.go @@ -11,10 +11,12 @@ var ( ) type renderer struct { - out strings.Builder - paragraphLevel int - quoteLevel int - listLevel int + out strings.Builder + paragraphLevel int + quoteLevel int + listLevel int + tableLevel int + tableHeaderWritten bool } // Render creates HTML from the supplied markdown text. @@ -104,6 +106,51 @@ func (r *renderer) processLine(line string) { r.writeText(line) r.out.WriteString("") return + + case '|': + r.closeParagraphs() + line = line[1:] + + if r.tableLevel == 0 { + r.out.WriteString("") + r.tableLevel++ + } + + column := 0 + + for { + pipe := strings.IndexByte(line, '|') + + if pipe == -1 { + r.out.WriteString("") + return + } + + content := strings.TrimSpace(line[:pipe]) + + if strings.HasPrefix(content, "---") { + r.out.WriteString("") + r.tableHeaderWritten = true + return + } + + if column == 0 { + r.out.WriteString("") + } + + if r.tableHeaderWritten { + r.out.WriteString("") + } else { + r.out.WriteString("") + } + + line = line[pipe+1:] + column++ + } } if r.paragraphLevel == 0 { @@ -121,6 +168,7 @@ func (r *renderer) processLine(line string) { func (r *renderer) closeAll() { r.closeLists() r.closeParagraphs() + r.closeTables() } // closeParagraphs closes open paragraphs. @@ -141,6 +189,16 @@ func (r *renderer) closeLists() { r.listLevel = 0 } +// closeTables closes open tables. +func (r *renderer) closeTables() { + for range r.tableLevel { + r.out.WriteString("
") + r.writeText(content) + r.out.WriteString("") + r.writeText(content) + r.out.WriteString("
") + } + + r.tableLevel = 0 + r.tableHeaderWritten = false +} + // writeText converts inline markdown to HTML. func (r *renderer) writeText(markdown string) { var ( diff --git a/Render_test.go b/Render_test.go index 95be167..c9718ee 100644 --- a/Render_test.go +++ b/Render_test.go @@ -44,6 +44,11 @@ func TestList(t *testing.T) { assert.Equal(t, markdown.Render("- Entry 1\n- Entry 2\n- Entry 3"), "") } +func TestTables(t *testing.T) { + assert.Equal(t, markdown.Render("| Head |\n| --- |\n| Body |"), "
Head
Body
") + assert.Equal(t, markdown.Render("| 1 | 2 |\n| --- | --- |\n| 1 | 2 |"), "
12
12
") +} + func TestQuote(t *testing.T) { assert.Equal(t, markdown.Render("> Line"), "

Line

") assert.Equal(t, markdown.Render("> Line 1\n> Line 2"), "

Line 1 Line 2

")