From 36922b6e952ddd87bedca16e38b34b913fcb6236 Mon Sep 17 00:00:00 2001 From: Timur Demin Date: Fri, 13 Aug 2021 09:49:06 +0500 Subject: [PATCH] Keep line breaks in blockquotes This makes the renderer preserve existing line breaks in blockquotes, provided they do not split paragraphs. Some clients/sites may use this to form semantic around line breaks (for instance, for poems). See #5. --- internal/gemini/renderer.go | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/internal/gemini/renderer.go b/internal/gemini/renderer.go index c022e14..39702ec 100644 --- a/internal/gemini/renderer.go +++ b/internal/gemini/renderer.go @@ -18,6 +18,7 @@ package gemini import ( + "bytes" "fmt" "io" "regexp" @@ -32,6 +33,7 @@ var ( lineBreak = []byte{'\n'} space = []byte{' '} linkPrefix = []byte("=> ") + quoteBrPrefix = []byte("\n> ") quotePrefix = []byte("> ") itemPrefix = []byte("* ") itemIndent = []byte{'\t'} @@ -89,8 +91,7 @@ func (r Renderer) blockquote(w io.Writer, node *ast.BlockQuote, entering bool) { if node := node.AsContainer(); node != nil { for _, child := range node.Children { w.Write(quotePrefix) - // assume children would be paragraphs - r.text(w, child) + r.blockquoteText(w, child) // double linebreak to ensure Gemini clients don't merge // quotes; gomarkdown assumes separate blockquotes are // paragraphs of the same blockquote while we don't @@ -260,6 +261,21 @@ func (r Renderer) text(w io.Writer, node ast.Node) { } } +// TODO: this really should've been unified with text(), but having two +// extra params for prefix/line breaks is not neat +func (r Renderer) blockquoteText(w io.Writer, node ast.Node) { + if node := node.AsLeaf(); node != nil { + // pad every line break with blockquote symbol + w.Write([]byte(bytes.ReplaceAll(node.Literal, lineBreak, quoteBrPrefix))) + return + } + if node := node.AsContainer(); node != nil { + for _, child := range node.Children { + r.blockquoteText(w, child) + } + } +} + func extractText(node ast.Node) string { if node := node.AsLeaf(); node != nil { return strings.ReplaceAll(string(node.Literal), "\n", " ")