testing
This commit is contained in:
parent
7a1029d1e5
commit
82b8d4c082
@ -45,7 +45,7 @@ func escapeRoffEdit(additional ...string) func(rune, bool) ([]rune, bool) {
|
|||||||
'\u00a0': []rune("\\~"),
|
'\u00a0': []rune("\\~"),
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i > len(additional); i += 2 {
|
for i := 0; i < len(additional); i += 2 {
|
||||||
r := []rune(additional[i])
|
r := []rune(additional[i])
|
||||||
if len(r) != 1 {
|
if len(r) != 1 {
|
||||||
panic(errors.New(invalidAdditional))
|
panic(errors.New(invalidAdditional))
|
||||||
|
|||||||
6
html.go
6
html.go
@ -266,6 +266,12 @@ func renderHTMLFragment(out io.Writer, doc Document) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for i, tag := range tags {
|
for i, tag := range tags {
|
||||||
|
if i > 0 {
|
||||||
|
if _, err := fmt.Fprintln(out); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
indent := html.Indentation{
|
indent := html.Indentation{
|
||||||
Indent: "\t",
|
Indent: "\t",
|
||||||
PWidth: 120,
|
PWidth: 120,
|
||||||
|
|||||||
87
html_test.go
87
html_test.go
@ -321,15 +321,46 @@ lines.</p>
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("title", func(t *testing.T) {
|
t.Run("title", func(t *testing.T) {
|
||||||
var b bytes.Buffer
|
t.Run("basic", func(t *testing.T) {
|
||||||
doc := textfmt.Doc(textfmt.Title(0, "This is a title"))
|
var b bytes.Buffer
|
||||||
if err := textfmt.HTMLFragment(&b, doc); err != nil {
|
doc := textfmt.Doc(textfmt.Title(0, "This is a title"))
|
||||||
t.Fatal(err)
|
if err := textfmt.HTMLFragment(&b, doc); err != nil {
|
||||||
}
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
if b.String() != "<h1>This is a title</h1>\n" {
|
if b.String() != "<h1>This is a title</h1>\n" {
|
||||||
t.Fatal(b.String())
|
t.Fatal(b.String())
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("every level", func(t *testing.T) {
|
||||||
|
var b bytes.Buffer
|
||||||
|
doc := textfmt.Doc(
|
||||||
|
textfmt.Title(0, "H1"),
|
||||||
|
textfmt.Title(1, "H2"),
|
||||||
|
textfmt.Title(2, "H3"),
|
||||||
|
textfmt.Title(3, "H4"),
|
||||||
|
textfmt.Title(4, "H5"),
|
||||||
|
textfmt.Title(5, "H6"),
|
||||||
|
)
|
||||||
|
|
||||||
|
if err := textfmt.HTMLFragment(&b, doc); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
const expect = `
|
||||||
|
<h1>H1</h1>
|
||||||
|
<h2>H2</h2>
|
||||||
|
<h3>H3</h3>
|
||||||
|
<h4>H4</h4>
|
||||||
|
<h5>H5</h5>
|
||||||
|
<h6>H6</h6>
|
||||||
|
`
|
||||||
|
|
||||||
|
if "\n" + b.String() != expect {
|
||||||
|
t.Fatal("\n" + b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("paragraph", func(t *testing.T) {
|
t.Run("paragraph", func(t *testing.T) {
|
||||||
@ -673,6 +704,46 @@ lines.</p>
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("wrapped and different indents", func(t *testing.T) {
|
||||||
|
doc := textfmt.Doc(
|
||||||
|
textfmt.Wrap(
|
||||||
|
textfmt.Indent(
|
||||||
|
textfmt.List(textfmt.Item(textfmt.Text("foo bar baz"))),
|
||||||
|
4,
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
24,
|
||||||
|
),
|
||||||
|
textfmt.Wrap(
|
||||||
|
textfmt.Indent(
|
||||||
|
textfmt.List(textfmt.Item(textfmt.Text("foo bar baz"))),
|
||||||
|
8,
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
24,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := textfmt.HTMLFragment(&b, doc); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
const expect = `
|
||||||
|
<ul>
|
||||||
|
<li>foo bar baz</li>
|
||||||
|
</ul>
|
||||||
|
<ul>
|
||||||
|
<li>foo bar baz
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
`
|
||||||
|
|
||||||
|
if "\n"+b.String() != expect {
|
||||||
|
t.Fatal("\n" + b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("long numbered definition list", func(t *testing.T) {
|
t.Run("long numbered definition list", func(t *testing.T) {
|
||||||
doc := textfmt.Doc(
|
doc := textfmt.Doc(
|
||||||
textfmt.NumberedDefinitionList(
|
textfmt.NumberedDefinitionList(
|
||||||
|
|||||||
1
lib.go
1
lib.go
@ -241,6 +241,7 @@ func Sequence(items ...SyntaxItem) SyntaxItem {
|
|||||||
return SyntaxItem{sequence: items}
|
return SyntaxItem{sequence: items}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// top level on separate lines without delimiter
|
||||||
func Choice(items ...SyntaxItem) SyntaxItem {
|
func Choice(items ...SyntaxItem) SyntaxItem {
|
||||||
return SyntaxItem{choice: items}
|
return SyntaxItem{choice: items}
|
||||||
}
|
}
|
||||||
|
|||||||
35
markdown.go
35
markdown.go
@ -54,10 +54,6 @@ func renderMDText(w io.Writer, text Txt) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
text.text = editString(text.text, singleLine())
|
|
||||||
text.text = editString(text.text, escapeMarkdown())
|
|
||||||
text.link = editString(text.link, singleLine())
|
|
||||||
text.link = editString(text.link, escapeMarkdown())
|
|
||||||
if text.bold {
|
if text.bold {
|
||||||
write(w, "**")
|
write(w, "**")
|
||||||
}
|
}
|
||||||
@ -76,21 +72,30 @@ func renderMDText(w io.Writer, text Txt) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if text.link != "" {
|
if text.link == "" {
|
||||||
if text.text != "" {
|
w, f := writeWith(w, singleLine(), escapeMarkdown())
|
||||||
write(w, "[")
|
write(w, text.text)
|
||||||
write(w, text.text)
|
w, _ = f()
|
||||||
write(w, "](")
|
|
||||||
write(w, text.link)
|
|
||||||
write(w, ")")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
write(w, text.link)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if text.text == "" {
|
||||||
|
w, f := writeWith(w, singleLine(), escapeMarkdown())
|
||||||
|
write(w, text.link)
|
||||||
|
w, _ = f()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
write(w, "[")
|
||||||
|
w, f := writeWith(w, singleLine(), escapeMarkdown())
|
||||||
write(w, text.text)
|
write(w, text.text)
|
||||||
|
w, _ = f()
|
||||||
|
write(w, "](")
|
||||||
|
w, f = writeWith(w, singleLine(), escapeMarkdown())
|
||||||
|
write(w, text.link)
|
||||||
|
w, _ = f()
|
||||||
|
write(w, ")")
|
||||||
|
w, _ = f()
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderMDTitle(w io.Writer, e Entry) {
|
func renderMDTitle(w io.Writer, e Entry) {
|
||||||
|
|||||||
@ -394,6 +394,50 @@ textfmt supports the following entries:
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("link", func(t *testing.T) {
|
||||||
|
t.Run("normal", func(t *testing.T) {
|
||||||
|
doc := textfmt.Doc(
|
||||||
|
textfmt.Paragraph(
|
||||||
|
textfmt.Cat(
|
||||||
|
textfmt.Text("This is a "),
|
||||||
|
textfmt.Link("link", "https://foo.bar"),
|
||||||
|
textfmt.Text("alright."),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := textfmt.Markdown(&b, doc); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "This is a [link](https://foo.bar) alright.\n" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("without label", func(t *testing.T) {
|
||||||
|
doc := textfmt.Doc(
|
||||||
|
textfmt.Paragraph(
|
||||||
|
textfmt.Cat(
|
||||||
|
textfmt.Text("This is a "),
|
||||||
|
textfmt.Link("", "https://foo.bar"),
|
||||||
|
textfmt.Text("alright."),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := textfmt.Markdown(&b, doc); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "This is a https://foo.bar alright.\n" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("escape", func(t *testing.T) {
|
t.Run("escape", func(t *testing.T) {
|
||||||
doc := textfmt.Doc(
|
doc := textfmt.Doc(
|
||||||
textfmt.Paragraph(
|
textfmt.Paragraph(
|
||||||
@ -428,6 +472,23 @@ textfmt supports the following entries:
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("escape non link", func(t *testing.T) {
|
||||||
|
doc := textfmt.Doc(
|
||||||
|
textfmt.Paragraph(
|
||||||
|
textfmt.Text("[looks-like-a-link] but it's not"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := textfmt.Markdown(&b, doc); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != "\\[looks-like-a-link\\] but it's not\n" {
|
||||||
|
t.Fatal(b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("escape negative number on line start", func(t *testing.T) {
|
t.Run("escape negative number on line start", func(t *testing.T) {
|
||||||
doc := textfmt.Doc(
|
doc := textfmt.Doc(
|
||||||
textfmt.Paragraph(
|
textfmt.Paragraph(
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"code.squareroundforest.org/arpio/textfmt"
|
"code.squareroundforest.org/arpio/textfmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRoff(t *testing.T) {
|
func TestRoff(t *testing.T) {
|
||||||
@ -230,8 +231,16 @@ textfmt supports the following entries:
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("example man", func(t *testing.T) {
|
t.Run("example man", func(t *testing.T) {
|
||||||
|
releaseDate := time.Date(2025, 11, 2, 15, 36, 18, 0, time.FixedZone("CET", 3600))
|
||||||
doc := textfmt.Doc(
|
doc := textfmt.Doc(
|
||||||
textfmt.Title(0, "Example Text", textfmt.ManSection(1)),
|
textfmt.Title(
|
||||||
|
0,
|
||||||
|
"Example Text",
|
||||||
|
textfmt.ManSection(1),
|
||||||
|
textfmt.ManCategory("User Command"),
|
||||||
|
textfmt.ReleaseDate(releaseDate),
|
||||||
|
textfmt.ReleaseVersion("v1"),
|
||||||
|
),
|
||||||
|
|
||||||
textfmt.Indent(
|
textfmt.Indent(
|
||||||
textfmt.Paragraph(textfmt.Text("Below you can find some test text, with various text items.")),
|
textfmt.Paragraph(textfmt.Text("Below you can find some test text, with various text items.")),
|
||||||
@ -315,7 +324,7 @@ textfmt supports the following entries:
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
const expect = `.TH "Example Text" 1 "" "" ""
|
const expect = `.TH "Example Text" 1 "November 2025" "v1" "User Command"
|
||||||
.br
|
.br
|
||||||
.sp 1v
|
.sp 1v
|
||||||
.in 0
|
.in 0
|
||||||
@ -634,20 +643,38 @@ Some sample text... on multiple lines.
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("title", func(t *testing.T) {
|
t.Run("title", func(t *testing.T) {
|
||||||
var b bytes.Buffer
|
t.Run("basic", func(t *testing.T) {
|
||||||
doc := textfmt.Doc(textfmt.Title(0, "This is a title"))
|
var b bytes.Buffer
|
||||||
if err := textfmt.Runoff(&b, doc); err != nil {
|
doc := textfmt.Doc(textfmt.Title(0, "This is a title"))
|
||||||
t.Fatal(err)
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
||||||
}
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
const expect = `.in 0
|
const expect = `.in 0
|
||||||
.ti 0
|
.ti 0
|
||||||
\fBThis is a title\fR
|
\fBThis is a title\fR
|
||||||
`
|
`
|
||||||
|
|
||||||
if b.String() != expect {
|
if b.String() != expect {
|
||||||
t.Fatal(b.String())
|
t.Fatal(b.String())
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("escaped man", func(t *testing.T) {
|
||||||
|
var b bytes.Buffer
|
||||||
|
doc := textfmt.Doc(textfmt.Title(0, "This is a title \"\\\"", textfmt.ManSection(1)))
|
||||||
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
const expect = `
|
||||||
|
.TH "This is a title \(dq\\\(dq" 1 "" "" ""
|
||||||
|
`
|
||||||
|
|
||||||
|
if "\n" + b.String() != expect {
|
||||||
|
t.Fatal("\n" + b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("paragraph", func(t *testing.T) {
|
t.Run("paragraph", func(t *testing.T) {
|
||||||
|
|||||||
@ -316,14 +316,28 @@ Entry explanations:
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("failing writer", func(t *testing.T) {
|
t.Run("failing writer", func(t *testing.T) {
|
||||||
w := &failingWriter{failAfter: 15}
|
t.Run("once", func(t *testing.T) {
|
||||||
doc := textfmt.Doc(
|
w := &failingWriter{failAfter: 15}
|
||||||
textfmt.Paragraph(textfmt.Text("Some sample text...\non multiple lines.")),
|
doc := textfmt.Doc(
|
||||||
)
|
textfmt.Paragraph(textfmt.Text("Some sample text...\non multiple lines.")),
|
||||||
|
)
|
||||||
|
|
||||||
if err := textfmt.Teletype(w, doc); err == nil {
|
if err := textfmt.Teletype(w, doc); err == nil {
|
||||||
t.Fatal("failed to fail")
|
t.Fatal("failed to fail")
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("multple times", func(t *testing.T) {
|
||||||
|
w := &failingWriter{failAfter: 15}
|
||||||
|
doc := textfmt.Doc(
|
||||||
|
textfmt.Paragraph(textfmt.Text("Some sample text...\non multiple lines.")),
|
||||||
|
textfmt.Paragraph(textfmt.Text("Some more sample text...\non multiple lines.")),
|
||||||
|
)
|
||||||
|
|
||||||
|
if err := textfmt.Teletype(w, doc); err == nil {
|
||||||
|
t.Fatal("failed to fail")
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("concatenate", func(t *testing.T) {
|
t.Run("concatenate", func(t *testing.T) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user