Add lossless inline-definition-footnote rendering for the OrgWriter
This commit is contained in:
parent
fc982125c9
commit
a570fc736f
6 changed files with 49 additions and 29 deletions
|
@ -14,6 +14,7 @@ type Footnotes struct {
|
||||||
type FootnoteDefinition struct {
|
type FootnoteDefinition struct {
|
||||||
Name string
|
Name string
|
||||||
Children []Node
|
Children []Node
|
||||||
|
Inline bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var footnoteDefinitionRegexp = regexp.MustCompile(`^\[fn:([\w-]+)\]\s+(.+)`)
|
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"
|
d.tokens[i].kind == "headline" || d.tokens[i].kind == "footnoteDefinition"
|
||||||
}
|
}
|
||||||
consumed, nodes := d.parseMany(i, stop)
|
consumed, nodes := d.parseMany(i, stop)
|
||||||
d.Footnotes.Definitions[name] = FootnoteDefinition{name, nodes}
|
d.Footnotes.Definitions[name] = FootnoteDefinition{name, nodes, false}
|
||||||
return consumed, nil
|
return consumed, nil
|
||||||
}
|
}
|
||||||
|
|
26
org/html.go
26
org/html.go
|
@ -44,19 +44,8 @@ func (w *HTMLWriter) emptyClone() *HTMLWriter {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *HTMLWriter) before(d *Document) {}
|
func (w *HTMLWriter) before(d *Document) {}
|
||||||
|
|
||||||
func (w *HTMLWriter) after(d *Document) {
|
func (w *HTMLWriter) after(d *Document) {
|
||||||
fs := d.Footnotes
|
w.writeFootnotes(d)
|
||||||
if len(fs.Definitions) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.WriteString(`<div id="footnotes">` + "\n")
|
|
||||||
w.WriteString(`<h1 class="footnotes-title">` + fs.Title + `</h1>` + "\n")
|
|
||||||
w.WriteString(`<div class="footnote-definitions">` + "\n")
|
|
||||||
for _, name := range fs.Order {
|
|
||||||
w.writeNodes(fs.Definitions[name])
|
|
||||||
}
|
|
||||||
w.WriteString("</div>\n</div>\n")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *HTMLWriter) writeNodes(ns ...Node) {
|
func (w *HTMLWriter) writeNodes(ns ...Node) {
|
||||||
|
@ -141,6 +130,19 @@ func (w *HTMLWriter) writeFootnoteDefinition(f FootnoteDefinition) {
|
||||||
w.WriteString("</div>\n")
|
w.WriteString("</div>\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *HTMLWriter) writeFootnotes(d *Document) {
|
||||||
|
fs := d.Footnotes
|
||||||
|
if len(fs.Definitions) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.WriteString(`<div id="footnotes">` + "\n")
|
||||||
|
w.WriteString(`<h1 class="footnotes-title">` + fs.Title + `</h1>` + "\n")
|
||||||
|
w.WriteString(`<div class="footnote-definitions">` + "\n")
|
||||||
|
for _, name := range fs.Order {
|
||||||
|
w.writeNodes(fs.Definitions[name])
|
||||||
|
}
|
||||||
|
w.WriteString("</div>\n</div>\n")
|
||||||
|
}
|
||||||
func (w *HTMLWriter) writeHeadline(h Headline) {
|
func (w *HTMLWriter) writeHeadline(h Headline) {
|
||||||
w.WriteString(fmt.Sprintf("<h%d>", h.Lvl))
|
w.WriteString(fmt.Sprintf("<h%d>", h.Lvl))
|
||||||
w.writeNodes(h.Title...)
|
w.writeNodes(h.Title...)
|
||||||
|
|
|
@ -15,7 +15,10 @@ type Emphasis struct {
|
||||||
Content []Node
|
Content []Node
|
||||||
}
|
}
|
||||||
|
|
||||||
type FootnoteLink struct{ Name string }
|
type FootnoteLink struct {
|
||||||
|
Name string
|
||||||
|
Definition *FootnoteDefinition
|
||||||
|
}
|
||||||
|
|
||||||
type RegularLink struct {
|
type RegularLink struct {
|
||||||
Protocol string
|
Protocol string
|
||||||
|
@ -104,7 +107,7 @@ func (d *Document) parseRegularLinkOrFootnoteReference(input string, start int)
|
||||||
func (d *Document) parseFootnoteReference(input string, start int) (int, Node) {
|
func (d *Document) parseFootnoteReference(input string, start int) (int, Node) {
|
||||||
if m := footnoteRegexp.FindStringSubmatch(input[start:]); m != nil {
|
if m := footnoteRegexp.FindStringSubmatch(input[start:]); m != nil {
|
||||||
name, definition := m[1], m[3]
|
name, definition := m[1], m[3]
|
||||||
seen := false
|
seen, link := false, FootnoteLink{name, nil}
|
||||||
for _, otherName := range d.Footnotes.Order {
|
for _, otherName := range d.Footnotes.Order {
|
||||||
if name == otherName {
|
if name == otherName {
|
||||||
seen = true
|
seen = true
|
||||||
|
@ -114,9 +117,10 @@ func (d *Document) parseFootnoteReference(input string, start int) (int, Node) {
|
||||||
d.Footnotes.Order = append(d.Footnotes.Order, name)
|
d.Footnotes.Order = append(d.Footnotes.Order, name)
|
||||||
}
|
}
|
||||||
if definition != "" {
|
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
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
29
org/org.go
29
org/org.go
|
@ -33,14 +33,7 @@ func NewOrgWriter() *OrgWriter {
|
||||||
|
|
||||||
func (w *OrgWriter) before(d *Document) {}
|
func (w *OrgWriter) before(d *Document) {}
|
||||||
func (w *OrgWriter) after(d *Document) {
|
func (w *OrgWriter) after(d *Document) {
|
||||||
fs := d.Footnotes
|
w.writeFootnotes(d)
|
||||||
if len(fs.Definitions) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.WriteString("* " + fs.Title + "\n")
|
|
||||||
for _, name := range fs.Order {
|
|
||||||
w.writeNodes(fs.Definitions[name])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *OrgWriter) emptyClone() *OrgWriter {
|
func (w *OrgWriter) emptyClone() *OrgWriter {
|
||||||
|
@ -146,6 +139,19 @@ func (w *OrgWriter) writeBlock(b Block) {
|
||||||
w.WriteString(w.indent + "#+END_" + b.Name + "\n")
|
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) {
|
func (w *OrgWriter) writeFootnoteDefinition(f FootnoteDefinition) {
|
||||||
w.WriteString(fmt.Sprintf("[fn:%s] ", f.Name))
|
w.WriteString(fmt.Sprintf("[fn:%s] ", f.Name))
|
||||||
w.writeNodes(f.Children...)
|
w.writeNodes(f.Children...)
|
||||||
|
@ -228,7 +234,12 @@ func (w *OrgWriter) writeLinebreak(l Linebreak) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *OrgWriter) writeFootnoteLink(l FootnoteLink) {
|
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) {
|
func (w *OrgWriter) writeRegularLink(l RegularLink) {
|
||||||
|
|
5
org/testdata/example.html
vendored
5
org/testdata/example.html
vendored
|
@ -65,7 +65,7 @@
|
||||||
<ul>
|
<ul>
|
||||||
<li>normal footnote reference <sup class="footnote-reference"><a href="#footnote-1">1</a></sup></li>
|
<li>normal footnote reference <sup class="footnote-reference"><a href="#footnote-1">1</a></sup></li>
|
||||||
<li>further references to the same footnote should not <sup class="footnote-reference"><a href="#footnote-1">1</a></sup> render duplicates in the footnote list</li>
|
<li>further references to the same footnote should not <sup class="footnote-reference"><a href="#footnote-1">1</a></sup> render duplicates in the footnote list</li>
|
||||||
<li>also inline footnotes are supported via <code class="verbatim">fn:2:inline definition</code>. But we won't test that because it would cause the output to look different from the input </li>
|
<li>inline footnotes are also supported via <sup class="footnote-reference"><a href="#footnote-2">2</a></sup>. </li>
|
||||||
</ul>
|
</ul>
|
||||||
<div id="footnotes">
|
<div id="footnotes">
|
||||||
<h1 class="footnotes-title">Footnotes</h1>
|
<h1 class="footnotes-title">Footnotes</h1>
|
||||||
|
@ -74,5 +74,8 @@
|
||||||
<sup id="footnote-1">1</sup>
|
<sup id="footnote-1">1</sup>
|
||||||
<p>Foobar</p>
|
<p>Foobar</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="footnote-definition">
|
||||||
|
<sup id="footnote-2">2</sup>
|
||||||
|
the inline footnote definition</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
3
org/testdata/example.org
vendored
3
org/testdata/example.org
vendored
|
@ -53,8 +53,7 @@ this one is cheating a little as tags are ALWAYS printed right aligned to a give
|
||||||
** Footnotes
|
** Footnotes
|
||||||
- normal footnote reference [fn:1]
|
- normal footnote reference [fn:1]
|
||||||
- further references to the same footnote should not [fn:1] render duplicates in the footnote list
|
- 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
|
- inline footnotes are also supported via [fn:2:the inline footnote definition].
|
||||||
cause the output to look different from the input
|
|
||||||
|
|
||||||
* Footnotes
|
* Footnotes
|
||||||
[fn:1] Foobar
|
[fn:1] Foobar
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue