all repos — grayfriday @ 3420fef03359a232d74c2ac1d237ac357cfca298

blackfriday fork with a few changes

Add full info string in fenced code blocks (#449)

* Add full info string in fenced code blocks

According to common mark, the info string for a fenced code block can be any
non-whitespace string, so adjust the code to read a full string instead of
just the syntax name.

Fixes #410 in v2.

* run go fmt
Nathan Glenn garfieldnate@gmail.com
Sat, 28 Apr 2018 12:25:38 +0200
commit

3420fef03359a232d74c2ac1d237ac357cfca298

parent

6aeb241ce2c0d259208d56810fc8831a46df5660

3 files changed, 81 insertions(+), 51 deletions(-)

jump to
M block.goblock.go

@@ -17,6 +17,7 @@ import (

"bytes" "html" "regexp" + "strings" "github.com/shurcooL/sanitized_anchor_name" )

@@ -568,8 +569,8 @@ }

// isFenceLine checks if there's a fence line (e.g., ``` or ``` go) at the beginning of data, // and returns the end index if so, or 0 otherwise. It also returns the marker found. -// If syntax is not nil, it gets set to the syntax specified in the fence line. -func isFenceLine(data []byte, syntax *string, oldmarker string) (end int, marker string) { +// If info is not nil, it gets set to the syntax specified in the fence line. +func isFenceLine(data []byte, info *string, oldmarker string) (end int, marker string) { i, size := 0, 0 // skip up to three spaces

@@ -605,9 +606,9 @@ return 0, ""

} // TODO(shurcooL): It's probably a good idea to simplify the 2 code paths here - // into one, always get the syntax, and discard it if the caller doesn't care. - if syntax != nil { - syn := 0 + // into one, always get the info string, and discard it if the caller doesn't care. + if info != nil { + infoLength := 0 i = skipChar(data, i, ' ') if i >= len(data) {

@@ -617,14 +618,14 @@ }

return 0, "" } - syntaxStart := i + infoStart := i if data[i] == '{' { i++ - syntaxStart++ + infoStart++ for i < len(data) && data[i] != '}' && data[i] != '\n' { - syn++ + infoLength++ i++ }

@@ -634,31 +635,30 @@ }

// strip all whitespace at the beginning and the end // of the {} block - for syn > 0 && isspace(data[syntaxStart]) { - syntaxStart++ - syn-- + for infoLength > 0 && isspace(data[infoStart]) { + infoStart++ + infoLength-- } - for syn > 0 && isspace(data[syntaxStart+syn-1]) { - syn-- + for infoLength > 0 && isspace(data[infoStart+infoLength-1]) { + infoLength-- } - i++ + i = skipChar(data, i, ' ') } else { - for i < len(data) && !isspace(data[i]) { - syn++ + for i < len(data) && !isverticalspace(data[i]) { + infoLength++ i++ } } - *syntax = string(data[syntaxStart : syntaxStart+syn]) + *info = strings.TrimSpace(string(data[infoStart : infoStart+infoLength])) } - i = skipChar(data, i, ' ') - if i >= len(data) || data[i] != '\n' { - if i == len(data) { - return i, marker - } + if i == len(data) { + return i, marker + } + if i > len(data) || data[i] != '\n' { return 0, "" } return i + 1, marker // Take newline into account.

@@ -668,14 +668,14 @@ // fencedCodeBlock returns the end index if data contains a fenced code block at the beginning,

// or 0 otherwise. It writes to out if doRender is true, otherwise it has no side effects. // If doRender is true, a final newline is mandatory to recognize the fenced code block. func (p *Markdown) fencedCodeBlock(data []byte, doRender bool) int { - var syntax string - beg, marker := isFenceLine(data, &syntax, "") + var info string + beg, marker := isFenceLine(data, &info, "") if beg == 0 || beg >= len(data) { return 0 } var work bytes.Buffer - work.Write([]byte(syntax)) + work.Write([]byte(info)) work.WriteByte('\n') for {
M block_test.goblock_test.go

@@ -945,6 +945,9 @@ var tests = []string{

"``` go\nfunc foo() bool {\n\treturn true;\n}\n```\n", "<pre><code class=\"language-go\">func foo() bool {\n\treturn true;\n}\n</code></pre>\n", + "``` go foo bar\nfunc foo() bool {\n\treturn true;\n}\n```\n", + "<pre><code class=\"language-go\">func foo() bool {\n\treturn true;\n}\n</code></pre>\n", + "``` c\n/* special & char < > \" escaping */\n```\n", "<pre><code class=\"language-c\">/* special &amp; char &lt; &gt; &quot; escaping */\n</code></pre>\n",

@@ -1403,6 +1406,9 @@ var tests = []string{

"``` go\nfunc foo() bool {\n\treturn true;\n}\n```\n", "<pre><code class=\"language-go\">func foo() bool {\n\treturn true;\n}\n</code></pre>\n", + "``` go foo bar\nfunc foo() bool {\n\treturn true;\n}\n```\n", + "<pre><code class=\"language-go\">func foo() bool {\n\treturn true;\n}\n</code></pre>\n", + "``` c\n/* special & char < > \" escaping */\n```\n", "<pre><code class=\"language-c\">/* special &amp; char &lt; &gt; &quot; escaping */\n</code></pre>\n",

@@ -1640,11 +1646,11 @@ }

func TestIsFenceLine(t *testing.T) { tests := []struct { - data []byte - syntaxRequested bool - wantEnd int - wantMarker string - wantSyntax string + data []byte + infoRequested bool + wantEnd int + wantMarker string + wantInfo string }{ { data: []byte("```"),

@@ -1657,45 +1663,59 @@ wantEnd: 4,

wantMarker: "```", }, { - data: []byte("```\nstuff here\n"), - syntaxRequested: true, - wantEnd: 4, - wantMarker: "```", + data: []byte("```\nstuff here\n"), + infoRequested: true, + wantEnd: 4, + wantMarker: "```", }, { data: []byte("stuff here\n```\n"), wantEnd: 0, }, { - data: []byte("```"), - syntaxRequested: true, - wantEnd: 3, - wantMarker: "```", + data: []byte("```"), + infoRequested: true, + wantEnd: 3, + wantMarker: "```", }, { - data: []byte("``` go"), - syntaxRequested: true, - wantEnd: 6, - wantMarker: "```", - wantSyntax: "go", + data: []byte("``` go"), + infoRequested: true, + wantEnd: 6, + wantMarker: "```", + wantInfo: "go", + }, + { + data: []byte("``` go foo bar"), + infoRequested: true, + wantEnd: 14, + wantMarker: "```", + wantInfo: "go foo bar", + }, + { + data: []byte("``` go foo bar "), + infoRequested: true, + wantEnd: 16, + wantMarker: "```", + wantInfo: "go foo bar", }, } for _, test := range tests { - var syntax *string - if test.syntaxRequested { - syntax = new(string) + var info *string + if test.infoRequested { + info = new(string) } - end, marker := isFenceLine(test.data, syntax, "```") + end, marker := isFenceLine(test.data, info, "```") if got, want := end, test.wantEnd; got != want { t.Errorf("got end %v, want %v", got, want) } if got, want := marker, test.wantMarker; got != want { t.Errorf("got marker %q, want %q", got, want) } - if test.syntaxRequested { - if got, want := *syntax, test.wantSyntax; got != want { - t.Errorf("got syntax %q, want %q", got, want) + if test.infoRequested { + if got, want := *info, test.wantInfo; got != want { + t.Errorf("got info string %q, want %q", got, want) } } }
M markdown.gomarkdown.go

@@ -813,7 +813,17 @@ }

// Test if a character is a whitespace character. func isspace(c byte) bool { - return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v' + return ishorizontalspace(c) || isverticalspace(c) +} + +// Test if a character is a horizontal whitespace character. +func ishorizontalspace(c byte) bool { + return c == ' ' || c == '\t' +} + +// Test if a character is a vertical character. +func isverticalspace(c byte) bool { + return c == '\n' || c == '\r' || c == '\f' || c == '\v' } // Test if a character is letter.