Fix footnote ordering and some other bugs
This commit is contained in:
parent
b1f9bfc9e9
commit
d5bf4317b2
7 changed files with 105 additions and 28 deletions
|
@ -10,7 +10,7 @@ import (
|
||||||
type Document struct {
|
type Document struct {
|
||||||
tokens []token
|
tokens []token
|
||||||
Nodes []Node
|
Nodes []Node
|
||||||
Footnotes Footnotes
|
Footnotes *Footnotes
|
||||||
StatusKeywords []string
|
StatusKeywords []string
|
||||||
MaxEmphasisNewLines int
|
MaxEmphasisNewLines int
|
||||||
BufferSettings map[string]string
|
BufferSettings map[string]string
|
||||||
|
@ -52,10 +52,10 @@ var nilToken = token{"nil", -1, "", nil}
|
||||||
|
|
||||||
func NewDocument() *Document {
|
func NewDocument() *Document {
|
||||||
return &Document{
|
return &Document{
|
||||||
Footnotes: Footnotes{
|
Footnotes: &Footnotes{
|
||||||
ExcludeHeading: true,
|
ExcludeHeading: true,
|
||||||
Title: "Footnotes",
|
Title: "Footnotes",
|
||||||
Definitions: map[string]FootnoteDefinition{},
|
Definitions: map[string]*FootnoteDefinition{},
|
||||||
},
|
},
|
||||||
MaxEmphasisNewLines: 1,
|
MaxEmphasisNewLines: 1,
|
||||||
BufferSettings: map[string]string{},
|
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) {
|
func (d *Document) parseMany(i int, stop stopFn) (int, []Node) {
|
||||||
start, nodes := i, []Node{}
|
start, nodes := i, []Node{}
|
||||||
for i < len(d.tokens) {
|
for i < len(d.tokens) && !stop(d, i) {
|
||||||
consumed, node := d.parseOne(i, stop)
|
consumed, node := d.parseOne(i, stop)
|
||||||
i += consumed
|
i += consumed
|
||||||
nodes = append(nodes, node)
|
nodes = append(nodes, node)
|
||||||
|
|
|
@ -7,8 +7,8 @@ import (
|
||||||
type Footnotes struct {
|
type Footnotes struct {
|
||||||
ExcludeHeading bool
|
ExcludeHeading bool
|
||||||
Title string
|
Title string
|
||||||
Definitions map[string]FootnoteDefinition
|
Definitions map[string]*FootnoteDefinition
|
||||||
Order []string
|
addOrder []string
|
||||||
}
|
}
|
||||||
|
|
||||||
type FootnoteDefinition struct {
|
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"
|
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, false}
|
d.Footnotes.add(name, &FootnoteDefinition{name, nodes, false})
|
||||||
return consumed, nil
|
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...)
|
||||||
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ var listTags = map[string][]string{
|
||||||
func NewHTMLWriter() *HTMLWriter {
|
func NewHTMLWriter() *HTMLWriter {
|
||||||
return &HTMLWriter{
|
return &HTMLWriter{
|
||||||
HighlightCodeBlock: func(source, lang string) string {
|
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(`<div id="footnotes">` + "\n")
|
||||||
w.WriteString(`<h1 class="footnotes-title">` + fs.Title + `</h1>` + "\n")
|
w.WriteString(`<h1 class="footnotes-title">` + fs.Title + `</h1>` + "\n")
|
||||||
w.WriteString(`<div class="footnote-definitions">` + "\n")
|
w.WriteString(`<div class="footnote-definitions">` + "\n")
|
||||||
for _, name := range fs.Order {
|
for _, definition := range d.Footnotes.Ordered() {
|
||||||
w.writeNodes(fs.Definitions[name])
|
w.writeNodes(definition)
|
||||||
}
|
}
|
||||||
w.WriteString("</div>\n</div>\n")
|
w.WriteString("</div>\n</div>\n")
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,19 +114,11 @@ 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, link := false, FootnoteLink{name, nil}
|
link := FootnoteLink{name, nil}
|
||||||
for _, otherName := range d.Footnotes.Order {
|
|
||||||
if name == otherName {
|
|
||||||
seen = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !seen {
|
|
||||||
d.Footnotes.Order = append(d.Footnotes.Order, name)
|
|
||||||
}
|
|
||||||
if definition != "" {
|
if definition != "" {
|
||||||
link.Definition = &FootnoteDefinition{name, d.parseInline(definition), true}
|
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 len(m[0]), link
|
||||||
}
|
}
|
||||||
return 0, nil
|
return 0, nil
|
||||||
|
|
|
@ -145,9 +145,9 @@ func (w *OrgWriter) writeFootnotes(d *Document) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.WriteString("* " + fs.Title + "\n")
|
w.WriteString("* " + fs.Title + "\n")
|
||||||
for _, name := range fs.Order {
|
for _, definition := range fs.Ordered() {
|
||||||
if fnDefinition := fs.Definitions[name]; !fnDefinition.Inline {
|
if !definition.Inline {
|
||||||
w.writeNodes(fnDefinition)
|
w.writeNodes(definition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
52
org/testdata/example.html
vendored
52
org/testdata/example.html
vendored
|
@ -24,7 +24,7 @@
|
||||||
<ol>
|
<ol>
|
||||||
<li><p>and another subitem</p>
|
<li><p>and another subitem</p>
|
||||||
<code class="src src-sh">
|
<code class="src src-sh">
|
||||||
<pre>echo with a block<pre>
|
<pre>echo with a block</pre>
|
||||||
</code>
|
</code>
|
||||||
</li>
|
</li>
|
||||||
<li><p>and another one with a table</p>
|
<li><p>and another one with a table</p>
|
||||||
|
@ -66,12 +66,12 @@
|
||||||
</ul>
|
</ul>
|
||||||
<h2>blocks</h2>
|
<h2>blocks</h2>
|
||||||
<code class="src src-bash">
|
<code class="src src-bash">
|
||||||
<pre>echo a bash source block<pre>
|
<pre>echo a bash source block</pre>
|
||||||
</code>
|
</code>
|
||||||
<code class="src src-text">
|
<code class="src src-text">
|
||||||
<pre>a source block without a language
|
<pre>a source block without a language
|
||||||
and a second line
|
and a second line
|
||||||
and a third one<pre>
|
and a third one</pre>
|
||||||
</code>
|
</code>
|
||||||
<pre class="example">
|
<pre class="example">
|
||||||
an example blockwith multiple lines
|
an example blockwith multiple lines
|
||||||
|
@ -90,7 +90,51 @@ Mongodb is very webscale
|
||||||
<div class="footnote-definitions">
|
<div class="footnote-definitions">
|
||||||
<div class="footnote-definition">
|
<div class="footnote-definition">
|
||||||
<sup id="footnote-1">1</sup>
|
<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>
|
||||||
<div class="footnote-definition">
|
<div class="footnote-definition">
|
||||||
<sup id="footnote-2">2</sup>
|
<sup id="footnote-2">2</sup>
|
||||||
|
|
20
org/testdata/example.org
vendored
20
org/testdata/example.org
vendored
|
@ -76,4 +76,22 @@ Mongodb is very webscale
|
||||||
- inline footnotes are also supported via [fn:2:the inline footnote definition].
|
- inline footnotes are also supported via [fn:2:the inline footnote definition].
|
||||||
|
|
||||||
* Footnotes
|
* 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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue