From 19966f0fc6bf08527be0c9f3ef99d9c98cc41a3b Mon Sep 17 00:00:00 2001 From: Erik Winter Date: Tue, 22 Mar 2022 06:53:01 +0100 Subject: [PATCH] most basic html formatter --- format/html.go | 68 ++++++++++++++++++ format/html_test.go | 166 ++++++++++++++++++++++++++++++++++++++++++++ format/text_test.go | 9 +-- 3 files changed, 239 insertions(+), 4 deletions(-) create mode 100644 format/html.go create mode 100644 format/html_test.go diff --git a/format/html.go b/format/html.go new file mode 100644 index 0000000..7ea8b59 --- /dev/null +++ b/format/html.go @@ -0,0 +1,68 @@ +package format + +import ( + "fmt" + "html" + + "ewintr.nl/adoc" + "ewintr.nl/adoc/element" + "ewintr.nl/go-kit/slugify" +) + +const pageTemplate = ` + + +%s + + +%s + +` + +func HTML(doc *adoc.ADoc) string { + return fmt.Sprintf(pageTemplate, html.EscapeString(doc.Title), HTMLFragment(doc.Content...)) +} + +func HTMLFragment(els ...element.Element) string { + var html string + for _, el := range els { + html += htmlElement(el) + } + + return html +} + +func htmlElement(el element.Element) string { + switch v := el.(type) { + case element.SubTitle: + return fmt.Sprintf("

%s

\n", slugify.Slugify(v.Text()), html.EscapeString(v.Text())) + case element.SubSubTitle: + return fmt.Sprintf("

%s

\n", slugify.Slugify(v.Text()), html.EscapeString(v.Text())) + case element.List: + var items []element.Element + for _, i := range v { + items = append(items, i) + } + return fmt.Sprintf("\n", HTMLFragment(items...)) + case element.ListItem: + return fmt.Sprintf("
  • %s
  • \n", HTMLFragment(v...)) + case element.CodeBlock: + return fmt.Sprintf("
    %s
    ", v.Text()) + case element.Paragraph: + return fmt.Sprintf("

    %s

    \n", HTMLFragment(v.Elements...)) + case element.Strong: + return fmt.Sprintf("%s", HTMLFragment(v...)) + case element.Emphasis: + return fmt.Sprintf("%s", HTMLFragment(v...)) + case element.Code: + return fmt.Sprintf("%s", HTMLFragment(v...)) + case element.Link: + return fmt.Sprintf("%s", v.URL, html.EscapeString(v.Title)) + case element.Word: + return html.EscapeString(v.Text()) + case element.WhiteSpace: + return " " + default: + return "" + } +} diff --git a/format/html_test.go b/format/html_test.go new file mode 100644 index 0000000..7b6517e --- /dev/null +++ b/format/html_test.go @@ -0,0 +1,166 @@ +package format_test + +import ( + "strings" + "testing" + + "ewintr.nl/adoc/element" + "ewintr.nl/adoc/format" + "ewintr.nl/adoc/parser" + "ewintr.nl/go-kit/test" +) + +func TestHTML(t *testing.T) { + input := `= A Title + +Some document + +With some text.` + + exp := ` + + +A Title + + +

    Some document

    +

    With some text.

    + + +` + doc := parser.New(strings.NewReader(input)).Parse() + test.Equals(t, exp, format.HTML(doc)) +} + +func TestHTMLFragment(t *testing.T) { + for _, tc := range []struct { + name string + input element.Element + exp string + }{ + { + name: "whitespace", + input: element.WhiteSpace("\n"), + exp: " ", + }, + { + name: "word", + input: element.Word("word"), + exp: "word", + }, + { + name: "word with html", + input: element.Word("

    hi

    "), + exp: "<h1>hi</h1>", + }, + { + name: "pararaphs", + input: element.Paragraph{ + Elements: []element.Element{ + element.Word("a"), + element.WhiteSpace(" "), + element.Word("word"), + }, + }, + exp: "

    a word

    \n", + }, + { + name: "strong", + input: element.Strong{ + element.Word("something"), + element.WhiteSpace(" "), + element.Word("strong"), + }, + exp: "something strong", + }, + { + name: "nested", + input: element.Paragraph{ + Elements: []element.Element{ + element.Word("normal"), + element.WhiteSpace(" "), + element.Word("text"), + element.Strong{ + element.WhiteSpace(" "), + element.Word("and"), + element.WhiteSpace(" "), + element.Word("strong"), + }, + element.WhiteSpace(" "), + element.Word("too"), + }, + }, + exp: "

    normal text and strong too

    \n", + }, + { + name: "emphasis", + input: element.Emphasis{ + element.Word("yes"), + }, + exp: "yes", + }, + { + name: "code", + input: element.Code{ + element.Word("simple"), + }, + exp: "simple", + }, + { + name: "link", + input: element.Link{ + URL: "http://example.com", + Title: "an example", + }, + exp: `an example`, + }, + { + name: "list", + input: element.List{ + element.ListItem{ + element.Word("item"), + element.WhiteSpace(" "), + element.Word("1"), + }, + element.ListItem{ + element.Word("item"), + element.WhiteSpace(" "), + element.Word("2"), + }, + }, + exp: ` +`, + }, + { + name: "code block", + input: element.CodeBlock{ + element.Word("some"), + element.WhiteSpace(" "), + element.Word("text"), + element.WhiteSpace("\n"), + element.Word("with"), + element.WhiteSpace("\t"), + element.Word("formatting"), + }, + exp: `
    some text
    +with	formatting
    `, + }, + { + name: "subtitle", + input: element.SubTitle("a subtitle"), + exp: "

    a subtitle

    \n", + }, + { + name: "subsubtitle", + input: element.SubSubTitle("a subsubtitle"), + exp: "

    a subsubtitle

    \n", + }, + } { + t.Run(tc.name, func(t *testing.T) { + test.Equals(t, tc.exp, format.HTMLFragment(tc.input)) + }) + } +} diff --git a/format/text_test.go b/format/text_test.go index 4aa64f5..1f53b67 100644 --- a/format/text_test.go +++ b/format/text_test.go @@ -12,14 +12,15 @@ import ( func TestText(t *testing.T) { input := `= A Title -Some Document +Some document + +With some text.` -With some text` exp := `A Title -Some Document +Some document -With some text +With some text. `