From d5bf4317b29947e925619e2fa23cd2c61eeefe06 Mon Sep 17 00:00:00 2001 From: Niklas Fasching Date: Sun, 2 Dec 2018 20:09:40 +0100 Subject: [PATCH] Fix footnote ordering and some other bugs --- org/document.go | 8 +++--- org/footnote.go | 29 +++++++++++++++++++--- org/html.go | 6 ++--- org/inline.go | 12 ++------- org/org.go | 6 ++--- org/testdata/example.html | 52 ++++++++++++++++++++++++++++++++++++--- org/testdata/example.org | 20 ++++++++++++++- 7 files changed, 105 insertions(+), 28 deletions(-) diff --git a/org/document.go b/org/document.go index f7d27d7..d061712 100644 --- a/org/document.go +++ b/org/document.go @@ -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) diff --git a/org/footnote.go b/org/footnote.go index 147ddcd..5bea596 100644 --- a/org/footnote.go +++ b/org/footnote.go @@ -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...) +} diff --git a/org/html.go b/org/html.go index 277af26..765b597 100644 --- a/org/html.go +++ b/org/html.go @@ -34,7 +34,7 @@ var listTags = map[string][]string{ func NewHTMLWriter() *HTMLWriter { return &HTMLWriter{ HighlightCodeBlock: func(source, lang string) string { - return fmt.Sprintf("
%s
", html.EscapeString(source))
+			return fmt.Sprintf("
%s
", html.EscapeString(source)) }, } } @@ -154,8 +154,8 @@ func (w *HTMLWriter) writeFootnotes(d *Document) { w.WriteString(`
` + "\n") w.WriteString(`

` + fs.Title + `

` + "\n") w.WriteString(`
` + "\n") - for _, name := range fs.Order { - w.writeNodes(fs.Definitions[name]) + for _, definition := range d.Footnotes.Ordered() { + w.writeNodes(definition) } w.WriteString("
\n
\n") } diff --git a/org/inline.go b/org/inline.go index 62bf0d3..f891476 100644 --- a/org/inline.go +++ b/org/inline.go @@ -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 diff --git a/org/org.go b/org/org.go index 203981c..15ae21b 100644 --- a/org/org.go +++ b/org/org.go @@ -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) } } } diff --git a/org/testdata/example.html b/org/testdata/example.html index 96d9397..d5a95b8 100644 --- a/org/testdata/example.html +++ b/org/testdata/example.html @@ -24,7 +24,7 @@
  1. and another subitem

    -
    echo with a block
    +
    echo with a block
  2. and another one with a table

    @@ -66,12 +66,12 @@

    blocks

    -
    echo a bash source block
    +
    echo a bash source block
    a source block without a language
     and a second line
    -and a third one
    +and a third one
     an example blockwith multiple lines
    @@ -90,7 +90,51 @@ Mongodb is very webscale
     
    1 -

    Foobar

    +

    https://www.example.com

    +
      +
    • footnotes can contain markup
    • +
    • and other elements

      +
        +
      • like blocks

        + +
        other non-plain
        +
        +
      • +
      • and tables

        + + + + + + + + + + + + + +
        1a
        2b
        3c
        +
      • +
      +
    • +
    +
    + +
    +4 +

    another unused footnote

    +
    +
    +5 +

    another unused footnote

    +
    +
    +6 +

    another unused footnote

    2 diff --git a/org/testdata/example.org b/org/testdata/example.org index ad29d1b..eb93aea 100644 --- a/org/testdata/example.org +++ b/org/testdata/example.org @@ -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