summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
Diffstat (limited to 'internal')
-rw-r--r--internal/text/markdown.go17
-rw-r--r--internal/text/markdown_test.go9
-rw-r--r--internal/text/sanitize.go17
3 files changed, 38 insertions, 5 deletions
diff --git a/internal/text/markdown.go b/internal/text/markdown.go
index e4b633e75..8486d6935 100644
--- a/internal/text/markdown.go
+++ b/internal/text/markdown.go
@@ -24,6 +24,7 @@ import (
"strings"
"code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
+ "code.superseriousbusiness.org/gotosocial/internal/id"
"code.superseriousbusiness.org/gotosocial/internal/log"
"code.superseriousbusiness.org/gotosocial/internal/regexes"
"codeberg.org/gruf/go-byteutil"
@@ -118,6 +119,18 @@ func (f *Formatter) fromMarkdown(
}
}
+ // Inject a footnote ID prefix to avoid
+ // footnote ID clashes. StatusID isn't
+ // always set (eg., when parsing instance
+ // description markdown), so take a random
+ // ULID if it's not.
+ var footnoteIDPrefix string
+ if statusID != "" {
+ footnoteIDPrefix = statusID + "-"
+ } else {
+ footnoteIDPrefix = id.NewULID() + "-"
+ }
+
// Instantiate goldmark parser for
// markdown, using custom renderer
// to add hashtag/mention links.
@@ -141,7 +154,9 @@ func (f *Formatter) fromMarkdown(
extension.NewLinkify(
extension.WithLinkifyURLRegexp(regexes.URLLike),
),
- extension.Footnote,
+ extension.NewFootnote(
+ extension.WithFootnoteIDPrefix(footnoteIDPrefix),
+ ),
extension.Strikethrough,
),
)
diff --git a/internal/text/markdown_test.go b/internal/text/markdown_test.go
index 347ca2928..14578398d 100644
--- a/internal/text/markdown_test.go
+++ b/internal/text/markdown_test.go
@@ -61,7 +61,9 @@ const (
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>"
mdWithFootnote = "fox mulder,fbi.[^1]\n\n[^1]: federated bureau of investigation"
- mdWithFootnoteExpected = "<p>fox mulder,fbi.<sup id=\"fnref:1\"><a class=\"footnote-ref\">1</a></sup></p><div><hr><ol><li id=\"fn:1\"><p>federated bureau of investigation <a class=\"footnote-backref\">↩︎</a></p></li></ol></div>"
+ mdWithFootnoteExpected = "<p>fox mulder,fbi.<sup id=\"dummy_status_ID-fnref:1\"><a href=\"#dummy_status_ID-fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1</a></sup></p><div><hr><ol><li id=\"dummy_status_ID-fn:1\"><p>federated bureau of investigation <a href=\"#dummy_status_ID-fnref:1\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p></li></ol></div>"
+ mdWithAttemptedRelative = "hello this is a cheeky relative link: <a href=\"../sneaky.html\">click it!</a>"
+ mdWithAttemptedRelativeExpected = "<p>hello this is a cheeky relative link: click it!</p>"
mdWithBlockQuote = "get ready, there's a block quote coming:\n\n>line1\n>line2\n>\n>line3\n\n"
mdWithBlockQuoteExpected = "<p>get ready, there's a block quote coming:</p><blockquote><p>line1<br>line2</p><p>line3</p></blockquote>"
mdHashtagAndCodeBlock = "#Hashtag\n\n```\n#Hashtag\n```"
@@ -156,6 +158,11 @@ func (suite *MarkdownTestSuite) TestParseWithFootnote() {
suite.Equal(mdWithFootnoteExpected, formatted.HTML)
}
+func (suite *MarkdownTestSuite) TestParseWithAttemptedRelative() {
+ formatted := suite.FromMarkdown(mdWithAttemptedRelative)
+ suite.Equal(mdWithAttemptedRelativeExpected, formatted.HTML)
+}
+
func (suite *MarkdownTestSuite) TestParseWithBlockquote() {
formatted := suite.FromMarkdown(mdWithBlockQuote)
suite.Equal(mdWithBlockQuoteExpected, formatted.HTML)
diff --git a/internal/text/sanitize.go b/internal/text/sanitize.go
index 29e1df1d8..87f039f31 100644
--- a/internal/text/sanitize.go
+++ b/internal/text/sanitize.go
@@ -124,17 +124,28 @@ var regular *bluemonday.Policy = func() *bluemonday.Policy {
*/
// Permit hyperlinks.
- p.AllowAttrs("class", "href", "rel").OnElements("a")
+ p.AllowAttrs("class", "rel").OnElements("a")
+
+ // Permit footnote roles on anchor elements.
+ p.AllowAttrs("role").Matching(regexp.MustCompile("^doc-noteref$")).OnElements("a")
+ p.AllowAttrs("role").Matching(regexp.MustCompile("^doc-backlink$")).OnElements("a")
// URLs must be parseable by net/url.Parse().
p.RequireParseableURLs(true)
- // Most common URL schemes only.
+ // Relative URLs are OK as we
+ // need fragments for footnotes.
+ p.AllowRelativeURLs(true)
+
+ // However *only* allow common schemes, and also
+ // relative URLs beginning with "#", ie., fragments.
+ // We don't want URL's like "../../peepee.html".
p.AllowURLSchemes("mailto", "http", "https")
+ p.AllowAttrs("href").Matching(regexp.MustCompile("^(?:#|mailto|https://|http://).+$")).OnElements("a")
// Force rel="noreferrer".
// See: https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel/noreferrer
- p.RequireNoReferrerOnLinks(true)
+ p.RequireNoReferrerOnFullyQualifiedLinks(true)
// Add rel="nofollow" on all fully qualified (not relative) links.
// See: https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel#nofollow