summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
Diffstat (limited to 'internal')
-rw-r--r--internal/api/client/status/statuscreate_test.go2
-rw-r--r--internal/text/markdown.go32
-rw-r--r--internal/text/markdown_test.go43
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 &#34;key&#34;: &#34;value&#34;,\n &#34;another_key&#34;: [\n &#34;value1&#34;,\n &#34;value2&#34;\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 &lt;code&gt;&lt;del&gt;SECRET CODE&lt;/del&gt;&lt;/code&gt;, 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 &lt;/code&gt;&lt;del&gt;SECRET CODE&lt;/del&gt;&lt;code&gt;, 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 &#34;key&#34;: &#34;value&#34;,\n &#34;another_key&#34;: [\n &#34;value1&#34;,\n &#34;value2&#34;\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 &lt;code>&lt;del>SECRET CODE&lt;/del>&lt;/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 &lt;/code>&lt;del>SECRET CODE&lt;/del>&lt;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))
}