diff --git a/etc/generate-fixtures b/etc/generate-fixtures index 39cfbaf..86fc480 100755 --- a/etc/generate-fixtures +++ b/etc/generate-fixtures @@ -1,6 +1,7 @@ #!/bin/bash for org_file in org/testdata/*.org; do + echo $org_file ./go-org $org_file html > org/testdata/$(basename $org_file .org).html ./go-org $org_file org > org/testdata/$(basename $org_file .org).pretty_org done diff --git a/org/document.go b/org/document.go index 8432e5e..3b5e8fa 100644 --- a/org/document.go +++ b/org/document.go @@ -14,7 +14,7 @@ type Document struct { Path string tokens []token Nodes []Node - Footnotes *Footnotes + Footnotes Footnotes StatusKeywords []string MaxEmphasisNewLines int AutoLink bool @@ -72,7 +72,7 @@ func FrontMatterHandler(fm FrontMatter, k, v string) error { func NewDocument() *Document { return &Document{ - Footnotes: &Footnotes{ + Footnotes: Footnotes{ Title: "Footnotes", Definitions: map[string]*FootnoteDefinition{}, }, @@ -222,6 +222,16 @@ func (d *Document) parseMany(i int, stop stopFn) (int, []Node) { return i - start, nodes } +func (d *Document) addFootnote(name string, definition *FootnoteDefinition) { + if definition != nil { + if _, exists := d.Footnotes.Definitions[name]; exists { + d.Log.Printf("Footnote [fn:%s] redefined! %#v", name, definition) + } + d.Footnotes.Definitions[name] = definition + } + d.Footnotes.addOrder = append(d.Footnotes.addOrder, name) +} + func tokenize(line string) token { for _, lexFn := range lexFns { if token, ok := lexFn(line); ok { diff --git a/org/footnote.go b/org/footnote.go index 860e8bc..be050fd 100644 --- a/org/footnote.go +++ b/org/footnote.go @@ -35,17 +35,10 @@ func (d *Document) parseFootnoteDefinition(i int, parentStop stopFn) (int, Node) } consumed, nodes := d.parseMany(i, stop) definition := FootnoteDefinition{name, nodes, false} - d.Footnotes.add(name, &definition) + d.addFootnote(name, &definition) return consumed, definition } -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{} diff --git a/org/html.go b/org/html.go index c628dd2..4bc048e 100644 --- a/org/html.go +++ b/org/html.go @@ -13,11 +13,10 @@ import ( type HTMLWriter struct { stringBuilder - HighlightCodeBlock func(source, lang string) string - FootnotesHeadingTitle string - htmlEscape bool - excludeTags []string - log *log.Logger + HighlightCodeBlock func(source, lang string) string + htmlEscape bool + excludeTags []string + log *log.Logger } var emphasisTags = map[string][]string{ @@ -45,8 +44,7 @@ var listItemStatuses = map[string]string{ func NewHTMLWriter() *HTMLWriter { return &HTMLWriter{ - htmlEscape: true, - FootnotesHeadingTitle: "Footnotes", + htmlEscape: true, HighlightCodeBlock: func(source, lang string) string { return fmt.Sprintf("%s\n
\n%s\n
\n", `
`, html.EscapeString(source)) }, @@ -95,7 +93,7 @@ func (w *HTMLWriter) writeNodes(ns ...Node) { continue case FootnoteDefinition: - w.writeFootnoteDefinition(n) + continue case List: w.writeList(n) @@ -191,24 +189,19 @@ func (w *HTMLWriter) writeFootnoteDefinition(f FootnoteDefinition) { } func (w *HTMLWriter) writeFootnotes(d *Document) { - fs := d.Footnotes - if len(fs.Definitions) == 0 { + if len(d.Footnotes.Definitions) == 0 { return } w.WriteString(`
` + "\n") - w.WriteString(`

` + fs.Title + `

` + "\n") + w.WriteString(`
` + "\n") w.WriteString(`
` + "\n") for _, definition := range d.Footnotes.Ordered() { - w.writeNodes(definition) + w.writeFootnoteDefinition(definition) } w.WriteString("
\n
\n") } func (w *HTMLWriter) writeHeadline(h Headline) { - title := w.nodesAsString(h.Title...) - if h.Lvl == 1 && title == w.FootnotesHeadingTitle { - return - } for _, excludeTag := range w.excludeTags { for _, tag := range h.Tags { if excludeTag == tag { @@ -230,7 +223,7 @@ func (w *HTMLWriter) writeHeadline(h Headline) { w.WriteString(fmt.Sprintf(`[%s]`, h.Priority) + "\n") } - w.WriteString(title) + w.writeNodes(h.Title...) if len(h.Tags) != 0 { tags := make([]string, len(h.Tags)) for i, tag := range h.Tags { @@ -337,7 +330,7 @@ func (w *HTMLWriter) writeDescriptiveListItem(di DescriptiveListItem) { } func (w *HTMLWriter) writeParagraph(p Paragraph) { - if isEmptyLineParagraph(p) { + if len(p.Children) == 0 { return } w.WriteString("

") diff --git a/org/inline.go b/org/inline.go index b02c1a3..7c810e0 100644 --- a/org/inline.go +++ b/org/inline.go @@ -157,7 +157,7 @@ func (d *Document) parseFootnoteReference(input string, start int) (int, Node) { link := FootnoteLink{name, nil} if definition != "" { link.Definition = &FootnoteDefinition{name, []Node{Paragraph{d.parseInline(definition)}}, true} - d.Footnotes.add(name, link.Definition) + d.addFootnote(name, link.Definition) } return len(m[0]), link } diff --git a/org/org.go b/org/org.go index 13f198d..7908831 100644 --- a/org/org.go +++ b/org/org.go @@ -3,6 +3,7 @@ package org import ( "fmt" "strings" + "unicode" "unicode/utf8" ) @@ -175,10 +176,11 @@ func (w *OrgWriter) writePropertyDrawer(d PropertyDrawer) { func (w *OrgWriter) writeFootnoteDefinition(f FootnoteDefinition) { w.WriteString(fmt.Sprintf("[fn:%s]", f.Name)) - if !(len(f.Children) >= 1 && isEmptyLineParagraph(f.Children[0])) { + content := w.nodesAsString(f.Children...) + if content != "" && !unicode.IsSpace(rune(content[0])) { w.WriteString(" ") } - w.writeNodes(f.Children...) + w.WriteString(content) } func (w *OrgWriter) writeParagraph(p Paragraph) { diff --git a/org/testdata/footnotes.html b/org/testdata/footnotes.html index 6dac97b..2613b79 100644 --- a/org/testdata/footnotes.html +++ b/org/testdata/footnotes.html @@ -17,11 +17,43 @@ further references to the same footnote should not 2.

+
  • +

    +Footnote definitions are not printed where they appear. +Rather, they are gathered and exported at the end of the document in the footnote section. 4 +

    +
  • +

    +Footnotes +

    +

    +Please note that the footnotes section is not automatically excluded from the export like in emacs. 7 +

    +

    +this is not part of 7 anymore as there are 2 blank lines in between! +

    -

    Footnotes

    +
    +4 +
    +

    +so this definition will not be at the end of this section in the exported document. +Rather, it will be somewhere down below in the footnotes section. +

    +
    +
    +
    +5 +
    +

    +another unused footnote (this definition overwrites the previous definition of fn:5) +

    +
    +
    +
    1

    @@ -83,22 +115,6 @@ and tables

    -4 -
    -

    -another unused footnote -

    -
    -
    -
    -5 -
    -

    -another unused footnote -

    -
    -
    -
    6

    @@ -108,6 +124,15 @@ This shouldn't happen when the definition line and the line after that are e

    +7 +
    +

    +There's multiple reasons for that. Among others, doing so requires i18n (to recognize the section) and silently +hides content before and after the footnotes. +

    +
    +
    +
    2

    diff --git a/org/testdata/footnotes.org b/org/testdata/footnotes.org index 0730354..ca8fcef 100644 --- a/org/testdata/footnotes.org +++ b/org/testdata/footnotes.org @@ -2,8 +2,17 @@ - normal footnote reference [fn:1] [fn:6] - further references to the same footnote should not [fn:1] render duplicates in the footnote list - inline footnotes are also supported via [fn:2:the inline footnote definition]. +- Footnote definitions are not printed where they appear. + Rather, they are gathered and exported at the end of the document in the footnote section. [fn:4] +[fn:4] so this definition will not be at the end of this section in the exported document. +Rather, it will be somewhere down below in the footnotes section. + +[fn:5] this definition will also not be exported here - not only that, it will be overwritten by a definition +of the same name later on in the document. That will log a warning but carry on nonetheless. * Footnotes +Please note that the footnotes section is not automatically excluded from the export like in emacs. [fn:7] + [fn:1] https://www.example.com - footnotes can contain *markup* - and other elements @@ -18,11 +27,18 @@ [fn:3] [[http://example.com/unused-footnote][example.com/unused-footnote]] -[fn:4] another unused footnote - -[fn:5] another unused footnote +[fn:5] another unused footnote (this definition overwrites the previous definition of =fn:5=) [fn:6] Footnotes break after two consecutive empty lines - just like paragraphs - see https://orgmode.org/worg/dev/org-syntax.html. This shouldn't happen when the definition line and the line after that are empty. + + +[fn:7] +There's multiple reasons for that. Among others, doing so requires i18n (to recognize the section) and silently +hides content before and after the footnotes. + + + +this is not part of [fn:7] anymore as there are 2 blank lines in between! diff --git a/org/testdata/footnotes.pretty_org b/org/testdata/footnotes.pretty_org index 0730354..ca8fcef 100644 --- a/org/testdata/footnotes.pretty_org +++ b/org/testdata/footnotes.pretty_org @@ -2,8 +2,17 @@ - normal footnote reference [fn:1] [fn:6] - further references to the same footnote should not [fn:1] render duplicates in the footnote list - inline footnotes are also supported via [fn:2:the inline footnote definition]. +- Footnote definitions are not printed where they appear. + Rather, they are gathered and exported at the end of the document in the footnote section. [fn:4] +[fn:4] so this definition will not be at the end of this section in the exported document. +Rather, it will be somewhere down below in the footnotes section. + +[fn:5] this definition will also not be exported here - not only that, it will be overwritten by a definition +of the same name later on in the document. That will log a warning but carry on nonetheless. * Footnotes +Please note that the footnotes section is not automatically excluded from the export like in emacs. [fn:7] + [fn:1] https://www.example.com - footnotes can contain *markup* - and other elements @@ -18,11 +27,18 @@ [fn:3] [[http://example.com/unused-footnote][example.com/unused-footnote]] -[fn:4] another unused footnote - -[fn:5] another unused footnote +[fn:5] another unused footnote (this definition overwrites the previous definition of =fn:5=) [fn:6] Footnotes break after two consecutive empty lines - just like paragraphs - see https://orgmode.org/worg/dev/org-syntax.html. This shouldn't happen when the definition line and the line after that are empty. + + +[fn:7] +There's multiple reasons for that. Among others, doing so requires i18n (to recognize the section) and silently +hides content before and after the footnotes. + + + +this is not part of [fn:7] anymore as there are 2 blank lines in between! diff --git a/org/testdata/misc.html b/org/testdata/misc.html index 9cb5566..df15f4b 100644 --- a/org/testdata/misc.html +++ b/org/testdata/misc.html @@ -359,8 +359,11 @@ When inserting an image link like -

    Footnotes

    +
    1 diff --git a/org/util.go b/org/util.go index 2ae0663..c25bf27 100644 --- a/org/util.go +++ b/org/util.go @@ -11,11 +11,6 @@ func isSecondBlankLine(d *Document, i int) bool { return false } -func isEmptyLineParagraph(n Node) bool { - p, ok := n.(Paragraph) - return ok && len(p.Children) == 0 -} - func isImageOrVideoLink(n Node) bool { if l, ok := n.(RegularLink); ok && l.Kind() == "video" || l.Kind() == "image" { return true