From 315c1405e8025a223c360cea567f82a4fd00e332 Mon Sep 17 00:00:00 2001 From: Erik Winter Date: Fri, 10 Jun 2022 14:58:36 +0200 Subject: [PATCH] asciidoc formatter --- format/asciidoc.go | 65 +++++++++++++++++ format/asciidoc_test.go | 156 ++++++++++++++++++++++++++++++++++++++++ format/html.go | 4 +- 3 files changed, 223 insertions(+), 2 deletions(-) create mode 100644 format/asciidoc.go create mode 100644 format/asciidoc_test.go diff --git a/format/asciidoc.go b/format/asciidoc.go new file mode 100644 index 0000000..aa2ff79 --- /dev/null +++ b/format/asciidoc.go @@ -0,0 +1,65 @@ +package format + +import ( + "fmt" + + "ewintr.nl/adoc" + "ewintr.nl/adoc/element" +) + +func AsciiDoc(doc *adoc.ADoc) string { + return fmt.Sprintf("%s\n%s", AsciiDocHeader(doc), AsciiDocFragment(doc.Content...)) +} + +func AsciiDocHeader(doc *adoc.ADoc) string { + header := fmt.Sprintf("= %s\n", doc.Title) + for k, v := range doc.Attributes { + header += fmt.Sprintf(":%s: %s\n", k, v) + } + + return header +} + +func AsciiDocFragment(els ...element.Element) string { + var asciiDoc string + for _, el := range els { + asciiDoc += asciiDocElement(el) + } + + return asciiDoc +} + +func asciiDocElement(el element.Element) string { + switch v := el.(type) { + case element.SubTitle: + return fmt.Sprintf("== %s\n\n", v.Text()) + case element.SubSubTitle: + return fmt.Sprintf("=== %s\n\n", v.Text()) + case element.List: + var items []element.Element + for _, i := range v { + items = append(items, i) + } + return fmt.Sprintf("%s\n", AsciiDocFragment(items...)) + case element.ListItem: + return fmt.Sprintf("* %s\n", AsciiDocFragment(v...)) + case element.CodeBlock: + return fmt.Sprintf("----\n%s\n----\n\n", v.Text()) + case element.Paragraph: + return fmt.Sprintf("%s\n\n", AsciiDocFragment(v.Elements...)) + case element.Strong: + return fmt.Sprintf("*%s*", AsciiDocFragment(v...)) + case element.Emphasis: + return fmt.Sprintf("_%s_", AsciiDocFragment(v...)) + case element.Code: + return fmt.Sprintf("`%s`", AsciiDocFragment(v...)) + case element.Link: + return fmt.Sprintf("%s[%s]", v.URL, v.Title) + case element.Word: + return v.Text() + case element.WhiteSpace: + return " " + default: + return "" + } +} diff --git a/format/asciidoc_test.go b/format/asciidoc_test.go new file mode 100644 index 0000000..aad1e47 --- /dev/null +++ b/format/asciidoc_test.go @@ -0,0 +1,156 @@ +package format_test + +import ( + "strings" + "testing" + + "ewintr.nl/adoc/element" + "ewintr.nl/adoc/format" + "ewintr.nl/adoc/parser" + "ewintr.nl/go-kit/test" +) + +func TestAsciiDoc(t *testing.T) { + input := `= A Title + +Some document + +With some text. + +` + + doc := parser.New(strings.NewReader(input)).Parse() + test.Equals(t, input, format.AsciiDoc(doc)) +} + +func TestAsciiDocFragment(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: "pararaphs", + input: element.Paragraph{ + Elements: []element.Element{ + element.Word("a"), + element.WhiteSpace(" "), + element.Word("word"), + }, + }, + exp: "a word\n\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.WhiteSpace(" "), + element.Strong{ + element.WhiteSpace(" "), + element.Word("and"), + element.WhiteSpace(" "), + element.Word("strong"), + }, + element.WhiteSpace(" "), + element.Word("too"), + }, + }, + exp: "normal text * and strong* too\n\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: `http://example.com[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: `* item 1 +* item 2 + +`, + }, + { + 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\n", + }, + { + name: "subsubtitle", + input: element.SubSubTitle("a subsubtitle"), + exp: "=== a subsubtitle\n\n", + }, + } { + t.Run(tc.name, func(t *testing.T) { + test.Equals(t, tc.exp, format.AsciiDocFragment(tc.input)) + }) + } +} diff --git a/format/html.go b/format/html.go index a3dee36..020546a 100644 --- a/format/html.go +++ b/format/html.go @@ -9,7 +9,7 @@ import ( "ewintr.nl/go-kit/slugify" ) -const pageTemplate = ` +const htmlPageTemplate = ` %s @@ -20,7 +20,7 @@ const pageTemplate = ` ` func HTML(doc *adoc.ADoc) string { - return fmt.Sprintf(pageTemplate, html.EscapeString(doc.Title), HTMLFragment(doc.Content...)) + return fmt.Sprintf(htmlPageTemplate, html.EscapeString(doc.Title), HTMLFragment(doc.Content...)) } func HTMLFragment(els ...element.Element) string {