diff options
author | 2022-08-07 18:19:16 +0200 | |
---|---|---|
committer | 2022-08-07 18:19:16 +0200 | |
commit | 879b4abde722cb66463ca81a4cf6ac5465ef276d (patch) | |
tree | cdbd98840bca27317ad0860a194072671ed04ebe /internal | |
parent | [feature] Photoswipe gallery (#740) (diff) | |
download | gotosocial-879b4abde722cb66463ca81a4cf6ac5465ef276d.tar.xz |
[bugfix] Markdown formatting updates (#743)
* add minify dependency specifically for markdown
* rearrange markdown formatting
* update markdown tests
Diffstat (limited to 'internal')
-rw-r--r-- | internal/api/client/status/statuscreate_test.go | 2 | ||||
-rw-r--r-- | internal/text/markdown.go | 32 | ||||
-rw-r--r-- | internal/text/markdown_test.go | 43 |
3 files changed, 58 insertions, 19 deletions
diff --git a/internal/api/client/status/statuscreate_test.go b/internal/api/client/status/statuscreate_test.go index a42654a42..2a82ff8a5 100644 --- a/internal/api/client/status/statuscreate_test.go +++ b/internal/api/client/status/statuscreate_test.go @@ -44,7 +44,7 @@ type StatusCreateTestSuite struct { const ( statusWithLinksAndTags = "#test alright, should be able to post #links with fragments in them now, let's see........\n\nhttps://docs.gotosocial.org/en/latest/user_guide/posts/#links\n\n#gotosocial\n\n(tobi remember to pull the docker image challenge)" statusMarkdown = "# Title\n\n## Smaller title\n\nThis is a post written in [markdown](https://www.markdownguide.org/)\n\n<img src=\"https://d33wubrfki0l68.cloudfront.net/f1f475a6fda1c2c4be4cac04033db5c3293032b4/513a4/assets/images/markdown-mark-white.svg\"/>" - statusMarkdownExpected = "<h1>Title</h1>\n\n<h2>Smaller title</h2>\n\n<p>This is a post written in <a href=\"https://www.markdownguide.org/\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">markdown</a></p>\n\n<p><img src=\"https://d33wubrfki0l68.cloudfront.net/f1f475a6fda1c2c4be4cac04033db5c3293032b4/513a4/assets/images/markdown-mark-white.svg\" crossorigin=\"anonymous\"/></p>\n" + statusMarkdownExpected = "<h1>Title</h1><h2>Smaller title</h2><p>This is a post written in <a href=\"https://www.markdownguide.org/\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">markdown</a></p><p><img src=\"https://d33wubrfki0l68.cloudfront.net/f1f475a6fda1c2c4be4cac04033db5c3293032b4/513a4/assets/images/markdown-mark-white.svg\" crossorigin=\"anonymous\"></p>" ) // Post a new status with some custom visibility settings diff --git a/internal/text/markdown.go b/internal/text/markdown.go index a5c62f23f..8952b99d6 100644 --- a/internal/text/markdown.go +++ b/internal/text/markdown.go @@ -23,17 +23,39 @@ import ( "github.com/russross/blackfriday/v2" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" + "github.com/superseriousbusiness/gotosocial/internal/log" + "github.com/tdewolff/minify/v2" + "github.com/tdewolff/minify/v2/html" ) -func (f *formatter) FromMarkdown(ctx context.Context, md string, mentions []*gtsmodel.Mention, tags []*gtsmodel.Tag) string { - // do the markdown parsing *first* - contentBytes := blackfriday.Run([]byte(md)) +var m *minify.M +func (f *formatter) FromMarkdown(ctx context.Context, md string, mentions []*gtsmodel.Mention, tags []*gtsmodel.Tag) string { // format tags nicely - content := f.ReplaceTags(ctx, string(contentBytes), tags) + content := f.ReplaceTags(ctx, md, tags) // format mentions nicely content = f.ReplaceMentions(ctx, content, mentions) - return SanitizeHTML(content) + // parse markdown + contentBytes := blackfriday.Run([]byte(content)) + + // clean anything dangerous out of it + content = SanitizeHTML(string(contentBytes)) + + if m == nil { + m = minify.New() + m.Add("text/html", &html.Minifier{ + KeepEndTags: true, + KeepQuotes: true, + KeepWhitespace: true, + }) + } + + minified, err := m.String("text/html", content) + if err != nil { + log.Errorf("error minifying markdown text: %s", err) + } + + return minified } diff --git a/internal/text/markdown_test.go b/internal/text/markdown_test.go index 74a18a685..af4a4fef6 100644 --- a/internal/text/markdown_test.go +++ b/internal/text/markdown_test.go @@ -44,19 +44,23 @@ that was some JSON :) ` const ( - simpleMarkdown = "# Title\n\nHere's a simple text in markdown.\n\nHere's a [link](https://example.org)." - simpleMarkdownExpected = "<h1>Title</h1>\n\n<p>Here’s a simple text in markdown.</p>\n\n<p>Here’s a <a href=\"https://example.org\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">link</a>.</p>\n" - withCodeBlockExpected = "<h1>Title</h1>\n\n<p>Below is some JSON.</p>\n\n<pre><code class=\"language-json\">{\n "key": "value",\n "another_key": [\n "value1",\n "value2"\n ]\n}\n</code></pre>\n\n<p>that was some JSON :)</p>\n" - withInlineCode = "`Nobody tells you about the <code><del>SECRET CODE</del></code>, do they?`" - withInlineCodeExpected = "<p><code>Nobody tells you about the <code><del>SECRET CODE</del></code>, do they?</code></p>\n" - withInlineCode2 = "`Nobody tells you about the </code><del>SECRET CODE</del><code>, do they?`" - withInlineCode2Expected = "<p><code>Nobody tells you about the </code><del>SECRET CODE</del><code>, do they?</code></p>\n" - withHashtag = "# Title\n\nhere's a simple status that uses hashtag #Hashtag!" - withHashtagExpected = "<h1>Title</h1>\n\n<p>here’s a simple status that uses hashtag <a href=\"http://localhost:8080/tags/Hashtag\" class=\"mention hashtag\" rel=\"tag nofollow noreferrer noopener\" target=\"_blank\">#<span>Hashtag</span></a>!</p>\n" - mdWithHTML = "# Title\n\nHere's a simple text in markdown.\n\nHere's a <a href=\"https://example.org\">link</a>.\n\nHere's an image: <img src=\"https://gts.superseriousbusiness.org/assets/logo.png\" alt=\"The GoToSocial sloth logo.\" width=\"500\" height=\"600\">" - mdWithHTMLExpected = "<h1>Title</h1>\n\n<p>Here’s a simple text in markdown.</p>\n\n<p>Here’s a <a href=\"https://example.org\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">link</a>.</p>\n\n<p>Here’s an image: <img src=\"https://gts.superseriousbusiness.org/assets/logo.png\" alt=\"The GoToSocial sloth logo.\" width=\"500\" height=\"600\" crossorigin=\"anonymous\"></p>\n" - mdWithCheekyHTML = "# Title\n\nHere's a simple text in markdown.\n\nHere's a cheeky little script: <script>alert(ahhhh)</script>" - mdWithCheekyHTMLExpected = "<h1>Title</h1>\n\n<p>Here’s a simple text in markdown.</p>\n\n<p>Here’s a cheeky little script: </p>\n" + simpleMarkdown = "# Title\n\nHere's a simple text in markdown.\n\nHere's a [link](https://example.org)." + simpleMarkdownExpected = "<h1>Title</h1><p>Here’s a simple text in markdown.</p><p>Here’s a <a href=\"https://example.org\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">link</a>.</p>" + withCodeBlockExpected = "<h1>Title</h1><p>Below is some JSON.</p><pre><code class=\"language-json\">{\n "key": "value",\n "another_key": [\n "value1",\n "value2"\n ]\n}\n</code></pre><p>that was some JSON :)</p>" + withInlineCode = "`Nobody tells you about the <code><del>SECRET CODE</del></code>, do they?`" + withInlineCodeExpected = "<p><code>Nobody tells you about the <code><del>SECRET CODE</del></code>, do they?</code></p>" + withInlineCode2 = "`Nobody tells you about the </code><del>SECRET CODE</del><code>, do they?`" + withInlineCode2Expected = "<p><code>Nobody tells you about the </code><del>SECRET CODE</del><code>, do they?</code></p>" + withHashtag = "# Title\n\nhere's a simple status that uses hashtag #Hashtag!" + withHashtagExpected = "<h1>Title</h1><p>here’s a simple status that uses hashtag <a href=\"http://localhost:8080/tags/Hashtag\" class=\"mention hashtag\" rel=\"tag nofollow noreferrer noopener\" target=\"_blank\">#<span>Hashtag</span></a>!</p>" + mdWithHTML = "# Title\n\nHere's a simple text in markdown.\n\nHere's a <a href=\"https://example.org\">link</a>.\n\nHere's an image: <img src=\"https://gts.superseriousbusiness.org/assets/logo.png\" alt=\"The GoToSocial sloth logo.\" width=\"500\" height=\"600\">" + mdWithHTMLExpected = "<h1>Title</h1><p>Here’s a simple text in markdown.</p><p>Here’s a <a href=\"https://example.org\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">link</a>.</p><p>Here’s an image: <img src=\"https://gts.superseriousbusiness.org/assets/logo.png\" alt=\"The GoToSocial sloth logo.\" width=\"500\" height=\"600\" crossorigin=\"anonymous\"></p>" + mdWithCheekyHTML = "# Title\n\nHere's a simple text in markdown.\n\nHere's a cheeky little script: <script>alert(ahhhh)</script>" + mdWithCheekyHTMLExpected = "<h1>Title</h1><p>Here’s a simple text in markdown.</p><p>Here’s a cheeky little script: </p>" + mdWithHashtagInitial = "#welcome #Hashtag" + mdWithHashtagInitialExpected = "<p><a href=\"http://localhost:8080/tags/welcome\" class=\"mention hashtag\" rel=\"tag nofollow noreferrer noopener\" target=\"_blank\">#<span>welcome</span></a> <a href=\"http://localhost:8080/tags/Hashtag\" class=\"mention hashtag\" rel=\"tag nofollow noreferrer noopener\" target=\"_blank\">#<span>Hashtag</span></a></p>" + mdCodeBlockWithNewlines = "some code coming up\n\n```\n\n\n\n```\nthat was some code" + mdCodeBlockWithNewlinesExpected = "<p>some code coming up</p><pre><code>\n\n\n</code></pre><p>that was some code</p>" ) type MarkdownTestSuite struct { @@ -102,6 +106,19 @@ func (suite *MarkdownTestSuite) TestParseWithCheekyHTML() { suite.Equal(mdWithCheekyHTMLExpected, s) } +func (suite *MarkdownTestSuite) TestParseWithHashtagInitial() { + s := suite.formatter.FromMarkdown(context.Background(), mdWithHashtagInitial, nil, []*gtsmodel.Tag{ + suite.testTags["Hashtag"], + suite.testTags["welcome"], + }) + suite.Equal(mdWithHashtagInitialExpected, s) +} + +func (suite *MarkdownTestSuite) TestParseCodeBlockWithNewlines() { + s := suite.formatter.FromMarkdown(context.Background(), mdCodeBlockWithNewlines, nil, nil) + suite.Equal(mdCodeBlockWithNewlinesExpected, s) +} + func TestMarkdownTestSuite(t *testing.T) { suite.Run(t, new(MarkdownTestSuite)) } |