Fix footnote ordering and some other bugs

This commit is contained in:
Niklas Fasching 2018-12-02 20:09:40 +01:00
parent b1f9bfc9e9
commit d5bf4317b2
7 changed files with 105 additions and 28 deletions

View file

@ -10,7 +10,7 @@ import (
type Document struct {
tokens []token
Nodes []Node
Footnotes Footnotes
Footnotes *Footnotes
StatusKeywords []string
MaxEmphasisNewLines int
BufferSettings map[string]string
@ -52,10 +52,10 @@ var nilToken = token{"nil", -1, "", nil}
func NewDocument() *Document {
return &Document{
Footnotes: Footnotes{
Footnotes: &Footnotes{
ExcludeHeading: true,
Title: "Footnotes",
Definitions: map[string]FootnoteDefinition{},
Definitions: map[string]*FootnoteDefinition{},
},
MaxEmphasisNewLines: 1,
BufferSettings: map[string]string{},
@ -132,7 +132,7 @@ func (d *Document) parseOne(i int, stop stopFn) (consumed int, node Node) {
func (d *Document) parseMany(i int, stop stopFn) (int, []Node) {
start, nodes := i, []Node{}
for i < len(d.tokens) {
for i < len(d.tokens) && !stop(d, i) {
consumed, node := d.parseOne(i, stop)
i += consumed
nodes = append(nodes, node)

View file

@ -7,8 +7,8 @@ import (
type Footnotes struct {
ExcludeHeading bool
Title string
Definitions map[string]FootnoteDefinition
Order []string
Definitions map[string]*FootnoteDefinition
addOrder []string
}
type FootnoteDefinition struct {
@ -34,6 +34,29 @@ 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, false}
d.Footnotes.add(name, &FootnoteDefinition{name, nodes, false})
return consumed, nil
}
func (fs *Footnotes) add(name string, definition *FootnoteDefinition) {
if definition != nil {
fs.Definitions[name] = definition
}
fs.addOrder = append(fs.addOrder, name)
}
func (fs *Footnotes) Ordered() []FootnoteDefinition {
m := map[string]bool{}
definitions, inlineDefinitions := []FootnoteDefinition{}, []FootnoteDefinition{}
for _, name := range fs.addOrder {
if isDuplicate := m[name]; !isDuplicate {
m[name] = true
if definition := *fs.Definitions[name]; definition.Inline {
inlineDefinitions = append(inlineDefinitions, definition)
} else {
definitions = append(definitions, definition)
}
}
}
return append(definitions, inlineDefinitions...)
}

View file

@ -34,7 +34,7 @@ var listTags = map[string][]string{
func NewHTMLWriter() *HTMLWriter {
return &HTMLWriter{
HighlightCodeBlock: func(source, lang string) string {
return fmt.Sprintf("<pre>%s<pre>", html.EscapeString(source))
return fmt.Sprintf("<pre>%s</pre>", html.EscapeString(source))
},
}
}
@ -154,8 +154,8 @@ func (w *HTMLWriter) writeFootnotes(d *Document) {
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])
for _, definition := range d.Footnotes.Ordered() {
w.writeNodes(definition)
}
w.WriteString("</div>\n</div>\n")
}

View file

@ -114,19 +114,11 @@ 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, link := false, FootnoteLink{name, nil}
for _, otherName := range d.Footnotes.Order {
if name == otherName {
seen = true
}
}
if !seen {
d.Footnotes.Order = append(d.Footnotes.Order, name)
}
link := FootnoteLink{name, nil}
if definition != "" {
link.Definition = &FootnoteDefinition{name, d.parseInline(definition), true}
d.Footnotes.Definitions[name] = *link.Definition
}
d.Footnotes.add(name, link.Definition)
return len(m[0]), link
}
return 0, nil

View file

@ -145,9 +145,9 @@ func (w *OrgWriter) writeFootnotes(d *Document) {
return
}
w.WriteString("* " + fs.Title + "\n")
for _, name := range fs.Order {
if fnDefinition := fs.Definitions[name]; !fnDefinition.Inline {
w.writeNodes(fnDefinition)
for _, definition := range fs.Ordered() {
if !definition.Inline {
w.writeNodes(definition)
}
}
}

View file

@ -24,7 +24,7 @@
<ol>
<li><p>and another subitem</p>
<code class="src src-sh">
<pre>echo with a block<pre>
<pre>echo with a block</pre>
</code>
</li>
<li><p>and another one with a table</p>
@ -66,12 +66,12 @@
</ul>
<h2>blocks</h2>
<code class="src src-bash">
<pre>echo a bash source block<pre>
<pre>echo a bash source block</pre>
</code>
<code class="src src-text">
<pre>a source block without a language
and a second line
and a third one<pre>
and a third one</pre>
</code>
<pre class="example">
an example blockwith multiple lines
@ -90,7 +90,51 @@ Mongodb is very webscale
<div class="footnote-definitions">
<div class="footnote-definition">
<sup id="footnote-1">1</sup>
<p>Foobar</p>
<p><a href="https://www.example.com">https://www.example.com</a></p>
<ul>
<li>footnotes can contain <strong>markup</strong></li>
<li><p>and other elements</p>
<ul>
<li><p>like blocks</p>
<code class="src src-text">
<pre>other non-plain</pre>
</code>
</li>
<li><p>and tables</p>
<table><tbody>
<tr>
<td>1</td><td>a</td>
</tr>
<tr>
<td>2</td><td>b</td>
</tr>
<tr>
<td>3</td><td>c</td>
</tr>
</tbody>
</table>
</li>
</ul>
</li>
</ul>
</div>
<div class="footnote-definition">
<sup id="footnote-3">3</sup>
<p><a href="http://example.com/unused-footnote">example.com/unused-footnote</a> </p>
</div>
<div class="footnote-definition">
<sup id="footnote-4">4</sup>
<p>another unused footnote </p>
</div>
<div class="footnote-definition">
<sup id="footnote-5">5</sup>
<p>another unused footnote </p>
</div>
<div class="footnote-definition">
<sup id="footnote-6">6</sup>
<p>another unused footnote</p>
</div>
<div class="footnote-definition">
<sup id="footnote-2">2</sup>

View file

@ -76,4 +76,22 @@ Mongodb is very webscale
- inline footnotes are also supported via [fn:2:the inline footnote definition].
* Footnotes
[fn:1] Foobar
[fn:1] https://www.example.com
- footnotes can contain *markup*
- and other elements
- like blocks
#+BEGIN_SRC
other non-plain
#+END_SRC
- and tables
| 1 | a |
| 2 | b |
| 3 | c |
[fn:3] [[http://example.com/unused-footnote][example.com/unused-footnote]]
[fn:4] another unused footnote
[fn:5] another unused footnote
[fn:6] another unused footnote