Skip to content
This repository has been archived by the owner on Jan 11, 2023. It is now read-only.

Commit

Permalink
Switch Markdown parser from Blackfriday to goldmark
Browse files Browse the repository at this point in the history
goldmark is CommonMark-compliant and easier to extend.
  • Loading branch information
samuelmeuli committed Apr 28, 2020
1 parent 472691f commit 6ddb1f4
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 27 deletions.
4 changes: 2 additions & 2 deletions convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func convertDataOutput(output output) template.HTML {
htmlString := fmt.Sprintf(`<img src="data:image/jpeg;base64,%s">`, *output.Data.ImageJPEG)
outputHTML = sanitizeHTML(htmlString)
case output.Data.TextMarkdown != nil:
outputHTML = renderMarkdown(output.Data.TextMarkdown)
outputHTML = renderMarkdown(strings.Join(output.Data.TextMarkdown, ""))
case output.Data.TextPlain != nil:
escapedHTML := escapeHTML(strings.Join(output.Data.TextPlain, ""))
outputHTML = "<pre>" + escapedHTML + "</pre>"
Expand Down Expand Up @@ -80,7 +80,7 @@ func convertStreamOutput(output output) template.HTML {

// convertMarkdownCell converts a Markdown cell to HTML.
func convertMarkdownCell(cell cell) template.HTML {
return renderMarkdown(cell.Source)
return renderMarkdown(strings.Join(cell.Source, ""))
}

// convertCodeCell converts a code cell to HTML with classes for syntax highlighting.
Expand Down
12 changes: 4 additions & 8 deletions convert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ func TestConvertDataOutputJPEG(t *testing.T) {

func TestConvertDataOutputMarkdown(t *testing.T) {
expected := template.HTML(`<h1>Hello World</h1>
<p>This is <strong>bold</strong> and <em>italic</em></p>
`)
actual := convertDataOutput(testMarkdownOutput)
Expand All @@ -91,9 +90,8 @@ func TestConvertDataOutputMarkdown(t *testing.T) {

func TestConvertDataOutputMarkdownCodeInjection(t *testing.T) {
expected := template.HTML(`<h1>Hello World</h1>
<p>This is <strong>bold</strong> and <em>italic</em>
</p>
<p>This is <strong>bold</strong> and <em>italic</em></p>
<!-- raw HTML omitted -->
`)
actual := convertDataOutput(testMarkdownOutputCodeInjection)
assert.Equal(t, expected, actual)
Expand Down Expand Up @@ -146,7 +144,6 @@ func TestConvertErrorOutputMissingKey(t *testing.T) {

func TestConvertMarkdownCell(t *testing.T) {
expected := template.HTML(`<h1>Hello World</h1>
<p>This is <strong>bold</strong> and <em>italic</em></p>
`)
actual := convertMarkdownCell(testMarkdownCell)
Expand All @@ -155,9 +152,8 @@ func TestConvertMarkdownCell(t *testing.T) {

func TestConvertMarkdownCellCodeInjection(t *testing.T) {
expected := template.HTML(`<h1>Hello World</h1>
<p>This is <strong>bold</strong> and <em>italic</em>
</p>
<p>This is <strong>bold</strong> and <em>italic</em></p>
<!-- raw HTML omitted -->
`)
actual := convertMarkdownCell(testMarkdownCellCodeInjection)
assert.Equal(t, expected, actual)
Expand Down
5 changes: 1 addition & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,8 @@ require (
github.com/mattn/go-isatty v0.0.12 // indirect
github.com/microcosm-cc/bluemonday v1.0.2
github.com/pkg/errors v0.9.1 // indirect
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
github.com/stretchr/testify v1.5.1
github.com/yuin/goldmark v1.1.30
golang.org/x/net v0.0.0-20200319234117-63522dbf7eec // indirect
golang.org/x/sys v0.0.0-20200317113312-5766fd39f98d // indirect
gopkg.in/russross/blackfriday.v2 v2.0.1
)

replace gopkg.in/russross/blackfriday.v2 v2.0.1 => github.com/russross/blackfriday/v2 v2.0.1
6 changes: 2 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,16 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/yuin/goldmark v1.1.30 h1:j4d4Lw3zqZelDhBksEo3BnWg9xhXRQGJPPSL6OApZjI=
github.com/yuin/goldmark v1.1.30/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3 h1:eH6Eip3UpmR+yM/qI9Ijluzb1bNv/cAU/n+6l8tRSis=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
Expand Down
22 changes: 13 additions & 9 deletions render.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,25 @@ import (
"github.com/alecthomas/chroma/lexers"
"github.com/alecthomas/chroma/styles"
"github.com/buildkite/terminal-to-html"
"gopkg.in/russross/blackfriday.v2"
"github.com/yuin/goldmark"
)

// renderMarkdown uses the Blackfriday library to convert the provided Markdown lines to HTML.
func renderMarkdown(markdownLines []string) template.HTML {
markdownString := strings.Join(markdownLines, "")
htmlString := string(blackfriday.Run([]byte(markdownString)))
return sanitizeHTML(htmlString)
// renderMarkdown uses the goldmark library to convert the provided Markdown lines to HTML.
func renderMarkdown(markdown string) template.HTML {
var htmlBuffer bytes.Buffer
if err := goldmark.Convert([]byte(markdown), &htmlBuffer); err != nil {
panic(err)
}
// goldmark does not render raw HTML or potentially-dangerous URLs, so HTML should be safe from
// code injection
return template.HTML(htmlBuffer.String()) // nolint:gosec
}

// renderSourceCode uses the Chroma library to convert the provided source code string to HTML.
// Instead of inline styles, HTML classes are used for syntax highlighting, which allows the users
// to style source code according to their needs.
func renderSourceCode(source string, languageID string) (template.HTML, error) {
sourceBuffer := new(bytes.Buffer)
htmlBuffer := new(bytes.Buffer)

// Set up lexer for programming language
var l chroma.Lexer
Expand All @@ -48,13 +52,13 @@ func renderSourceCode(source string, languageID string) (template.HTML, error) {
return "", fmt.Errorf("could not render source code (tokenization error): %d", err)
}

err = formatter.Format(sourceBuffer, styles.GitHub, iterator)
err = formatter.Format(htmlBuffer, styles.GitHub, iterator)
if err != nil {
return "", fmt.Errorf("could not render source code (formatting error): %d", err)
}

// Chroma escapes tags, so HTML should be safe from code injection
return template.HTML(sourceBuffer.String()), nil // nolint:gosec
return template.HTML(htmlBuffer.String()), nil // nolint:gosec
}

// renderMarkdown uses the `terminal-to-html` library to convert the provided Terminal output to
Expand Down

0 comments on commit 6ddb1f4

Please sign in to comment.