From a570fc736f438c0056830ad8516010e69b39ea1b Mon Sep 17 00:00:00 2001 From: Niklas Fasching Date: Sun, 2 Dec 2018 17:24:10 +0100 Subject: [PATCH] Add lossless inline-definition-footnote rendering for the OrgWriter --- org/footnote.go | 3 ++- org/html.go | 26 ++++++++++++++------------ org/inline.go | 12 ++++++++---- org/org.go | 29 ++++++++++++++++++++--------- org/testdata/example.html | 5 ++++- org/testdata/example.org | 3 +-- 6 files changed, 49 insertions(+), 29 deletions(-) diff --git a/org/footnote.go b/org/footnote.go index 91cbff7..147ddcd 100644 --- a/org/footnote.go +++ b/org/footnote.go @@ -14,6 +14,7 @@ type Footnotes struct { type FootnoteDefinition struct { Name string Children []Node + Inline bool } var footnoteDefinitionRegexp = regexp.MustCompile(`^\[fn:([\w-]+)\]\s+(.+)`) @@ -33,6 +34,6 @@ func (d *Document) parseFootnoteDefinition(i int, parentStop stopFn) (int, Node) d.tokens[i].kind == "headline" || d.tokens[i].kind == "footnoteDefinition" } consumed, nodes := d.parseMany(i, stop) - d.Footnotes.Definitions[name] = FootnoteDefinition{name, nodes} + d.Footnotes.Definitions[name] = FootnoteDefinition{name, nodes, false} return consumed, nil } diff --git a/org/html.go b/org/html.go index 97b8d35..41af658 100644 --- a/org/html.go +++ b/org/html.go @@ -44,19 +44,8 @@ func (w *HTMLWriter) emptyClone() *HTMLWriter { } func (w *HTMLWriter) before(d *Document) {} - func (w *HTMLWriter) after(d *Document) { - fs := d.Footnotes - if len(fs.Definitions) == 0 { - return - } - w.WriteString(`
` + "\n") - w.WriteString(`

` + fs.Title + `

` + "\n") - w.WriteString(`
` + "\n") - for _, name := range fs.Order { - w.writeNodes(fs.Definitions[name]) - } - w.WriteString("
\n
\n") + w.writeFootnotes(d) } func (w *HTMLWriter) writeNodes(ns ...Node) { @@ -141,6 +130,19 @@ func (w *HTMLWriter) writeFootnoteDefinition(f FootnoteDefinition) { w.WriteString("\n") } +func (w *HTMLWriter) writeFootnotes(d *Document) { + fs := d.Footnotes + if len(fs.Definitions) == 0 { + return + } + w.WriteString(`
` + "\n") + w.WriteString(`

` + fs.Title + `

` + "\n") + w.WriteString(`
` + "\n") + for _, name := range fs.Order { + w.writeNodes(fs.Definitions[name]) + } + w.WriteString("
\n
\n") +} func (w *HTMLWriter) writeHeadline(h Headline) { w.WriteString(fmt.Sprintf("", h.Lvl)) w.writeNodes(h.Title...) diff --git a/org/inline.go b/org/inline.go index 004969d..2b78cd4 100644 --- a/org/inline.go +++ b/org/inline.go @@ -15,7 +15,10 @@ type Emphasis struct { Content []Node } -type FootnoteLink struct{ Name string } +type FootnoteLink struct { + Name string + Definition *FootnoteDefinition +} type RegularLink struct { Protocol string @@ -104,7 +107,7 @@ func (d *Document) parseRegularLinkOrFootnoteReference(input string, start int) func (d *Document) parseFootnoteReference(input string, start int) (int, Node) { if m := footnoteRegexp.FindStringSubmatch(input[start:]); m != nil { name, definition := m[1], m[3] - seen := false + seen, link := false, FootnoteLink{name, nil} for _, otherName := range d.Footnotes.Order { if name == otherName { seen = true @@ -114,9 +117,10 @@ func (d *Document) parseFootnoteReference(input string, start int) (int, Node) { d.Footnotes.Order = append(d.Footnotes.Order, name) } if definition != "" { - d.Footnotes.Definitions[name] = FootnoteDefinition{name, d.parseInline(definition)} + link.Definition = &FootnoteDefinition{name, d.parseInline(definition), true} + d.Footnotes.Definitions[name] = *link.Definition } - return len(m[0]), FootnoteLink{name} + return len(m[0]), link } return 0, nil } diff --git a/org/org.go b/org/org.go index 7e0f53f..866881c 100644 --- a/org/org.go +++ b/org/org.go @@ -33,14 +33,7 @@ func NewOrgWriter() *OrgWriter { func (w *OrgWriter) before(d *Document) {} func (w *OrgWriter) after(d *Document) { - fs := d.Footnotes - if len(fs.Definitions) == 0 { - return - } - w.WriteString("* " + fs.Title + "\n") - for _, name := range fs.Order { - w.writeNodes(fs.Definitions[name]) - } + w.writeFootnotes(d) } func (w *OrgWriter) emptyClone() *OrgWriter { @@ -146,6 +139,19 @@ func (w *OrgWriter) writeBlock(b Block) { w.WriteString(w.indent + "#+END_" + b.Name + "\n") } +func (w *OrgWriter) writeFootnotes(d *Document) { + fs := d.Footnotes + if len(fs.Definitions) == 0 { + return + } + w.WriteString("* " + fs.Title + "\n") + for _, name := range fs.Order { + if fnDefinition := fs.Definitions[name]; !fnDefinition.Inline { + w.writeNodes(fnDefinition) + } + } +} + func (w *OrgWriter) writeFootnoteDefinition(f FootnoteDefinition) { w.WriteString(fmt.Sprintf("[fn:%s] ", f.Name)) w.writeNodes(f.Children...) @@ -228,7 +234,12 @@ func (w *OrgWriter) writeLinebreak(l Linebreak) { } func (w *OrgWriter) writeFootnoteLink(l FootnoteLink) { - w.WriteString("[fn:" + l.Name + "]") + w.WriteString("[fn:" + l.Name) + if l.Definition != nil { + w.WriteString(":") + w.writeNodes(l.Definition.Children...) + } + w.WriteString("]") } func (w *OrgWriter) writeRegularLink(l RegularLink) { diff --git a/org/testdata/example.html b/org/testdata/example.html index 1f10157..9786b14 100644 --- a/org/testdata/example.html +++ b/org/testdata/example.html @@ -65,7 +65,7 @@

Footnotes

@@ -74,5 +74,8 @@ 1

Foobar

+
+2 +the inline footnote definition
diff --git a/org/testdata/example.org b/org/testdata/example.org index 3460855..789cdac 100644 --- a/org/testdata/example.org +++ b/org/testdata/example.org @@ -53,8 +53,7 @@ this one is cheating a little as tags are ALWAYS printed right aligned to a give ** Footnotes - normal footnote reference [fn:1] - further references to the same footnote should not [fn:1] render duplicates in the footnote list -- also inline footnotes are supported via =fn:2:inline definition=. But we won't test that because it would - cause the output to look different from the input +- inline footnotes are also supported via [fn:2:the inline footnote definition]. * Footnotes [fn:1] Foobar