Implemented headers and paragraphs
This commit is contained in:
parent
a4e5243ab3
commit
93d5949eff
14
README.md
14
README.md
@ -4,7 +4,8 @@ Markdown renderer.
|
|||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
|
- Headers
|
||||||
|
- Paragraphs
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@ -15,16 +16,25 @@ go get git.akyoto.dev/go/markdown
|
|||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
html := markdown.Render("# Header")
|
||||||
|
fmt.Println(html)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
|
|
||||||
```
|
```
|
||||||
|
PASS: TestEmpty
|
||||||
|
PASS: TestParagraphs
|
||||||
|
PASS: TestHeader
|
||||||
|
PASS: TestCombined
|
||||||
|
coverage: 100.0% of statements
|
||||||
```
|
```
|
||||||
|
|
||||||
## Benchmarks
|
## Benchmarks
|
||||||
|
|
||||||
|
```
|
||||||
|
BenchmarkSmall-12 2187232 544.9 ns/op 296 B/op 9 allocs/op
|
||||||
|
```
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
67
Render.go
67
Render.go
@ -1,6 +1,71 @@
|
|||||||
package markdown
|
package markdown
|
||||||
|
|
||||||
|
import (
|
||||||
|
"html"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
headerStart = []string{"<h1>", "<h2>", "<h3>", "<h4>", "<h5>", "<h6>"}
|
||||||
|
headerEnd = []string{"</h1>", "</h2>", "</h3>", "</h4>", "</h5>", "</h6>"}
|
||||||
|
)
|
||||||
|
|
||||||
// Render creates HTML from the supplied markdown text.
|
// Render creates HTML from the supplied markdown text.
|
||||||
func Render(markdown string) string {
|
func Render(markdown string) string {
|
||||||
return ""
|
var (
|
||||||
|
out = strings.Builder{}
|
||||||
|
paragraph = strings.Builder{}
|
||||||
|
i = 0
|
||||||
|
lineStart = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
flush := func() {
|
||||||
|
if paragraph.Len() == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
out.WriteString("<p>")
|
||||||
|
out.WriteString(html.EscapeString(paragraph.String()))
|
||||||
|
out.WriteString("</p>")
|
||||||
|
paragraph.Reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
if i > len(markdown) {
|
||||||
|
flush()
|
||||||
|
return out.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
if i != len(markdown) && markdown[i] != '\n' {
|
||||||
|
i++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
line := markdown[lineStart:i]
|
||||||
|
lineStart = i + 1
|
||||||
|
i++
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case strings.HasPrefix(line, "#"):
|
||||||
|
flush()
|
||||||
|
space := strings.IndexByte(line, ' ')
|
||||||
|
|
||||||
|
if space > 0 && space <= 6 {
|
||||||
|
out.WriteString(headerStart[space-1])
|
||||||
|
out.WriteString(html.EscapeString(line[space+1:]))
|
||||||
|
out.WriteString(headerEnd[space-1])
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
if len(line) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if paragraph.Len() > 0 {
|
||||||
|
paragraph.WriteByte(' ')
|
||||||
|
}
|
||||||
|
|
||||||
|
paragraph.WriteString(line)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,28 @@ import (
|
|||||||
"git.akyoto.dev/go/markdown"
|
"git.akyoto.dev/go/markdown"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRender(t *testing.T) {
|
func TestEmpty(t *testing.T) {
|
||||||
html := markdown.Render("# Hello")
|
assert.Equal(t, markdown.Render(""), "")
|
||||||
assert.Equal(t, html, "<h1>Hello</h1>")
|
}
|
||||||
|
|
||||||
|
func TestParagraphs(t *testing.T) {
|
||||||
|
assert.Equal(t, markdown.Render("Text"), "<p>Text</p>")
|
||||||
|
assert.Equal(t, markdown.Render("Text\n"), "<p>Text</p>")
|
||||||
|
assert.Equal(t, markdown.Render("Text\n\n"), "<p>Text</p>")
|
||||||
|
assert.Equal(t, markdown.Render("Text\n\n\n"), "<p>Text</p>")
|
||||||
|
assert.Equal(t, markdown.Render("Line 1\nLine 2"), "<p>Line 1 Line 2</p>")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHeader(t *testing.T) {
|
||||||
|
assert.Equal(t, markdown.Render("# Header"), "<h1>Header</h1>")
|
||||||
|
assert.Equal(t, markdown.Render("## Header"), "<h2>Header</h2>")
|
||||||
|
assert.Equal(t, markdown.Render("### Header"), "<h3>Header</h3>")
|
||||||
|
assert.Equal(t, markdown.Render("#### Header"), "<h4>Header</h4>")
|
||||||
|
assert.Equal(t, markdown.Render("##### Header"), "<h5>Header</h5>")
|
||||||
|
assert.Equal(t, markdown.Render("###### Header"), "<h6>Header</h6>")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCombined(t *testing.T) {
|
||||||
|
assert.Equal(t, markdown.Render("# Header\nLine 1.\nLine 2.\nLine 3."), "<h1>Header</h1><p>Line 1. Line 2. Line 3.</p>")
|
||||||
|
assert.Equal(t, markdown.Render("# Header 1\nLine 1.\n# Header 2\nLine 2."), "<h1>Header 1</h1><p>Line 1.</p><h1>Header 2</h1><p>Line 2.</p>")
|
||||||
}
|
}
|
||||||
|
13
benchmarks_test.go
Normal file
13
benchmarks_test.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package markdown_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.akyoto.dev/go/markdown"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BenchmarkSmall(b *testing.B) {
|
||||||
|
for range b.N {
|
||||||
|
markdown.Render("# Header\nText.\nText.\n# Header\nText.\nText.")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user