From 7bdb82c53a065aab6aae8fa61530b47c6b9f3b87 Mon Sep 17 00:00:00 2001 From: moshee Date: Wed, 26 Jun 2013 15:57:51 +0000 Subject: [PATCH] new tests pass but old tests now fail... --- block.go | 2 +- html.go | 22 ++++++++------ inline.go | 2 +- inline_test.go | 80 ++++++++++++++++++++++++++++++++++++++------------ latex.go | 6 +++- markdown.go | 68 +++++++++++++++++++++++------------------- 6 files changed, 120 insertions(+), 60 deletions(-) diff --git a/block.go b/block.go index c189d0d..4cbee0c 100644 --- a/block.go +++ b/block.go @@ -459,7 +459,7 @@ func (p *parser) isEmpty(data []byte) int { var i int for i = 0; data[i] != '\n'; i++ { - if data[i] != ' ' { + if data[i] != ' ' || data[i] != '\t' { return 0 } } diff --git a/html.go b/html.go index 36efeb1..59d1e32 100644 --- a/html.go +++ b/html.go @@ -322,20 +322,24 @@ func (options *Html) TableCell(out *bytes.Buffer, text []byte, align int) { out.WriteString("") } -func (options *Html) Footnotes(out *bytes.Buffer, p *parser) { +func (options *Html) Footnotes(out *bytes.Buffer, text func() bool) { out.WriteString("
\n") options.HRule(out) - options.List(out, func() bool { - for _, ref := range p.notes { - out.WriteString("
  • \n") - out.Write(ref.title) - out.WriteString("
  • \n") - } - return true - }, LIST_TYPE_ORDERED) + options.List(out, text, LIST_TYPE_ORDERED) out.WriteString("
    \n") } +func (options *Html) FootnoteItem(out *bytes.Buffer, name, text []byte, flags int) { + if flags&LIST_ITEM_CONTAINS_BLOCK != 0 || flags&LIST_ITEM_BEGINNING_OF_LIST != 0 { + doubleSpace(out) + } + out.WriteString(`
  • `) + out.Write(text) + out.WriteString("
  • \n") +} + func (options *Html) List(out *bytes.Buffer, text func() bool, flags int) { marker := out.Len() doubleSpace(out) diff --git a/inline.go b/inline.go index c7d771a..56d38bd 100644 --- a/inline.go +++ b/inline.go @@ -193,7 +193,7 @@ func link(p *parser, out *bytes.Buffer, data []byte, offset int) int { if offset > 0 && data[offset-1] == '!' { t = linkImg } else if p.flags&EXTENSION_FOOTNOTES != 0 { - if len(data) > offset && data[offset+1] == '^' { + if len(data)-1 > offset && data[offset+1] == '^' { t = linkDeferredFootnote } } diff --git a/inline_test.go b/inline_test.go index 31e415d..d2f0bab 100644 --- a/inline_test.go +++ b/inline_test.go @@ -35,12 +35,13 @@ func doTestsInline(t *testing.T, tests []string) { func doTestsInlineParam(t *testing.T, tests []string, extensions, htmlFlags int) { // catch and report panics var candidate string - defer func() { - if err := recover(); err != nil { - panic(err) - t.Errorf("\npanic while processing [%#v] (%v)\n", candidate, err) - } - }() + /* + defer func() { + if err := recover(); err != nil { + t.Errorf("\npanic while processing [%#v] (%v)\n", candidate, err) + } + }() + */ for i := 0; i+1 < len(tests); i += 2 { input := tests[i] @@ -506,25 +507,55 @@ func TestAutoLink(t *testing.T) { func TestFootnotes(t *testing.T) { tests := []string{ "testing footnotes.[^a]\n\n[^a]: This is the note\n", - "", + `

    testing footnotes.1

    +
    + +
    + +
      +
    1. This is the note +
    2. +
    +
    +`, `testing long[^b] notes. [^b]: Paragraph 1 Paragraph 2 - + ` + "```\n\tsome code\n\t```" + ` Paragraph 3 No longer in the footnote `, - "", + `

    testing long1 notes.

    + +

    No longer in the footnote

    +
    + +
    + +
      +
    1. Paragraph 1

      + +

      Paragraph 2

      + +

      +some code +

      + +

      Paragraph 3

      +
    2. +
    +
    +`, `testing[^c] multiple[^d] notes. -[^c]: this is note c +[^c]: this is [note] c omg @@ -532,15 +563,28 @@ omg [^d]: this is note d what happens here + +[note]: /link/c + +`, + `

    testing1 multiple2 notes.

    + +

    omg

    + +

    what happens here

    +
    + +
    + +
      +
    1. this is note c +
    2. +
    3. this is note d +
    4. +
    +
    `, - "", } - for _, test := range tests { - if len(test) > 0 { - t.Errorf("Output:\n%s\n", runMarkdownInline(test, EXTENSION_FOOTNOTES, 0)) - } - } - - //doTestsInlineParam(t, tests, EXTENSION_FOOTNOTES, 0) + doTestsInlineParam(t, tests, EXTENSION_FOOTNOTES, 0) } diff --git a/latex.go b/latex.go index 169757d..1a8fa0a 100644 --- a/latex.go +++ b/latex.go @@ -159,7 +159,11 @@ func (options *Latex) TableCell(out *bytes.Buffer, text []byte, align int) { } // TODO: this -func (options *Latex) Footnotes(out *bytes.Buffer, p *parser) { +func (options *Latex) Footnotes(out *bytes.Buffer, text func() bool) { + +} + +func (options *Latex) FootnoteItem(out *bytes.Buffer, name, text []byte, flags int) { } diff --git a/markdown.go b/markdown.go index 034dabb..7d17433 100644 --- a/markdown.go +++ b/markdown.go @@ -140,7 +140,8 @@ type Renderer interface { Table(out *bytes.Buffer, header []byte, body []byte, columnData []int) TableRow(out *bytes.Buffer, text []byte) TableCell(out *bytes.Buffer, text []byte, flags int) - Footnotes(out *bytes.Buffer, p *parser) + Footnotes(out *bytes.Buffer, text func() bool) + FootnoteItem(out *bytes.Buffer, name, text []byte, flags int) // Span-level callbacks AutoLink(out *bytes.Buffer, link []byte, kind int) @@ -344,10 +345,23 @@ func secondPass(p *parser, input []byte) []byte { p.r.DocumentHeader(&output) p.block(&output, input) - // NOTE: this is a big hack because we need the parser again for the - // footnotes, so this can't really go in the public interface if p.flags&EXTENSION_FOOTNOTES != 0 && len(p.notes) > 0 { - p.r.Footnotes(&output, p) + p.r.Footnotes(&output, func() bool { + flags := LIST_ITEM_BEGINNING_OF_LIST + for _, ref := range p.notes { + var buf bytes.Buffer + if ref.hasBlock { + flags |= LIST_ITEM_CONTAINS_BLOCK + p.block(&buf, ref.title) + } else { + p.inline(&buf, ref.title) + } + p.r.FootnoteItem(&output, ref.link, buf.Bytes(), flags) + flags &^= LIST_ITEM_BEGINNING_OF_LIST | LIST_ITEM_CONTAINS_BLOCK + } + + return true + }) } p.r.DocumentFooter(&output) @@ -390,9 +404,10 @@ func secondPass(p *parser, input []byte) []byte { // References are parsed and stored in this struct. type reference struct { - link []byte - title []byte - noteId int // 0 if not a footnote ref + link []byte + title []byte + noteId int // 0 if not a footnote ref + hasBlock bool } // Check whether or not data starts with a reference link. @@ -401,7 +416,8 @@ type reference struct { // Returns the number of bytes to skip to move past it, // or zero if the first line is not a reference. func isReference(p *parser, data []byte, tabSize int) int { - println("[", string(data), "]") + if len(data) >= 5 { + } // up to 3 optional leading spaces if len(data) < 4 { return 0 @@ -434,7 +450,6 @@ func isReference(p *parser, data []byte, tabSize int) int { idEnd := i // spacer: colon (space | tab)* newline? (space | tab)* - // /:[ \t]*\n?[ \t]*/ i++ if i >= len(data) || data[i] != ':' { return 0 @@ -461,11 +476,12 @@ func isReference(p *parser, data []byte, tabSize int) int { titleOffset, titleEnd int lineEnd int raw []byte + hasBlock bool ) if p.flags&EXTENSION_FOOTNOTES != 0 && noteId > 0 { - linkOffset, linkEnd, raw = scanFootnote(p, data, i, tabSize) - lineEnd = linkEnd + linkOffset + linkOffset, linkEnd, raw, hasBlock = scanFootnote(p, data, i, tabSize) + lineEnd = linkEnd } else { linkOffset, linkEnd, titleOffset, titleEnd, lineEnd = scanLinkRef(p, data, i) } @@ -476,11 +492,12 @@ func isReference(p *parser, data []byte, tabSize int) int { // a valid ref has been found ref := &reference{ - noteId: noteId, + noteId: noteId, + hasBlock: hasBlock, } if noteId > 0 { - // reusing the link field for the id since footnotes don't have titles + // reusing the link field for the id since footnotes don't have links ref.link = data[idOffset:idEnd] // if footnote, it's not really a title, it's the contained text ref.title = raw @@ -570,7 +587,7 @@ func scanLinkRef(p *parser, data []byte, i int) (linkOffset, linkEnd, titleOffse // blockEnd is the end of the section in the input buffer, and contents is the // extracted text that was shifted over one tab. It will need to be rendered at // the end of the document. -func scanFootnote(p *parser, data []byte, i, indentSize int) (blockStart, blockEnd int, contents []byte) { +func scanFootnote(p *parser, data []byte, i, indentSize int) (blockStart, blockEnd int, contents []byte, hasBlock bool) { if i == 0 { return } @@ -584,10 +601,7 @@ func scanFootnote(p *parser, data []byte, i, indentSize int) (blockStart, blockE // find the end of the line blockEnd = i - for data[i-1] != '\n' { - if i >= len(data) { - return - } + for i < len(data) && data[i-1] != '\n' { i++ } @@ -600,14 +614,13 @@ func scanFootnote(p *parser, data []byte, i, indentSize int) (blockStart, blockE // process the following lines containsBlankLine := false - hasBlock := false gatherLines: for blockEnd < len(data) { i++ // find the end of this line - for data[i-1] != '\n' { + for i < len(data) && data[i-1] != '\n' { i++ } @@ -628,27 +641,22 @@ gatherLines: // if there were blank lines before this one, insert a new one now if containsBlankLine { - hasBlock = true raw.WriteByte('\n') containsBlankLine = false } // get rid of that first tab, write to buffer raw.Write(data[blockEnd+n : i]) + hasBlock = true blockEnd = i } - rawBytes := raw.Bytes() - println("raw: {" + string(raw.Bytes()) + "}") - buf := new(bytes.Buffer) - - if hasBlock { - p.block(buf, rawBytes) - } else { - p.inline(buf, rawBytes) + if data[blockEnd-1] != '\n' { + raw.WriteByte('\n') } - contents = buf.Bytes() + + contents = raw.Bytes() return }