diff --git a/block.go b/block.go index 8681e63..7ff1142 100644 --- a/block.go +++ b/block.go @@ -86,7 +86,7 @@ func (p *parser) block(out *bytes.Buffer, data []byte) { // } // ``` if p.flags&EXTENSION_FENCED_CODE != 0 { - if i := p.fencedCode(out, data); i > 0 { + if i := p.fencedCode(out, data, true); i > 0 { data = data[i:] continue } @@ -584,7 +584,7 @@ func (p *parser) isFencedCode(data []byte, syntax **string, oldmarker string) (s return } -func (p *parser) fencedCode(out *bytes.Buffer, data []byte) int { +func (p *parser) fencedCode(out *bytes.Buffer, data []byte, doRender bool) int { var lang *string beg, marker := p.isFencedCode(data, &lang, "") if beg == 0 || beg >= len(data) { @@ -616,7 +616,9 @@ func (p *parser) fencedCode(out *bytes.Buffer, data []byte) int { } // verbatim copy to the working buffer - work.Write(data[beg:end]) + if doRender { + work.Write(data[beg:end]) + } beg = end } @@ -625,7 +627,9 @@ func (p *parser) fencedCode(out *bytes.Buffer, data []byte) int { syntax = *lang } - p.r.BlockCode(out, work.Bytes(), syntax) + if doRender { + p.r.BlockCode(out, work.Bytes(), syntax) + } return beg } diff --git a/block_test.go b/block_test.go index ae4e1cc..9321a41 100644 --- a/block_test.go +++ b/block_test.go @@ -31,7 +31,7 @@ func doTestsBlock(t *testing.T, tests []string, extensions int) { var candidate string defer func() { if err := recover(); err != nil { - t.Errorf("\npanic while processing [%#v]\n", candidate) + t.Errorf("\npanic while processing [%#v]: %s\n", candidate, err) } }() @@ -642,6 +642,15 @@ func TestFencedCodeBlock(t *testing.T) { " ``` oz\nleading spaces\n ```\n", "
``` oz\n
\n\nleading spaces\n ```
\n", + + "Bla bla\n\n``` oz\ncode blocks breakup paragraphs\n```\n\nBla Bla\n", + "Bla bla
\n\ncode blocks breakup paragraphs\n
\n\nBla Bla
\n", + + "Some text before a fenced code block\n``` oz\ncode blocks breakup paragraphs\n```\nAnd some text after a fenced code block", + "Some text before a fenced code block
\n\ncode blocks breakup paragraphs\n
\n\nAnd some text after a fenced code block
\n", + + "`", + "`
\n", } doTestsBlock(t, tests, EXTENSION_FENCED_CODE) } diff --git a/markdown.go b/markdown.go index 1b170e4..606b53b 100644 --- a/markdown.go +++ b/markdown.go @@ -305,6 +305,7 @@ func Markdown(input []byte, renderer Renderer, extensions int) []byte { // - expand tabs // - normalize newlines // - copy everything else +// - add missing newlines before fenced code blocks func firstPass(p *parser, input []byte) []byte { var out bytes.Buffer tabSize := TAB_SIZE_DEFAULT @@ -312,6 +313,8 @@ func firstPass(p *parser, input []byte) []byte { tabSize = TAB_SIZE_EIGHT } beg, end := 0, 0 + lastLineWasBlank := false + lastFencedCodeBlockEnd := 0 for beg < len(input) { // iterate over lines if end = isReference(p, input[beg:], tabSize); end > 0 { beg += end @@ -321,6 +324,17 @@ func firstPass(p *parser, input []byte) []byte { end++ } + if p.flags&EXTENSION_FENCED_CODE != 0 { + // when last line was none blank and a fenced code block comes after + if !lastLineWasBlank && beg >= lastFencedCodeBlockEnd { + if i := p.fencedCode(&out, append(input[beg:], '\n'), false); i > 0 { + out.WriteByte('\n') // need to inject additional linebreak + lastFencedCodeBlockEnd = beg + i + } + } + lastLineWasBlank = end == beg + } + // add the line body if present if end > beg { expandTabs(&out, input[beg:end], tabSize) diff --git a/upskirtref_test.go b/upskirtref_test.go index 8205e48..42a0bdd 100644 --- a/upskirtref_test.go +++ b/upskirtref_test.go @@ -50,18 +50,21 @@ func doTestsReference(t *testing.T, files []string, flag int) { } expected := string(expectedBytes) + // fmt.Fprintf(os.Stderr, "processing %s ...", filename) actual := string(runMarkdownReference(input, flag)) if actual != expected { t.Errorf("\n [%#v]\nExpected[%#v]\nActual [%#v]", basename+".text", expected, actual) } + // fmt.Fprintf(os.Stderr, " ok\n") // now test every prefix of every input to check for // bounds checking if !testing.Short() { - start := 0 - for end := start + 1; end <= len(input); end++ { + start, max := 0, len(input) + for end := start + 1; end <= max; end++ { candidate = input[start:end] + // fmt.Fprintf(os.Stderr, " %s %d:%d/%d\n", filename, start, end, max) _ = runMarkdownReference(candidate, flag) } }