From 32e99d00415c6e86a9536d9b824dcdf0b119270d Mon Sep 17 00:00:00 2001 From: Matt Baer Date: Mon, 4 Feb 2019 17:50:37 +0100 Subject: [PATCH] Fix hashes in code blocks rendered as hashtags Previously, our hashtag parser would indiscriminately replace hashtag-like text with hashtag HTML -- including in places it shouldn't have, like inside code blocks. Along with the v1.7.0 changes to writeas/saturday, this fixes that and closes #6. As a bonus, strings of #spaceless#hashtags#in#a#row are now rendered correctly. --- app.go | 2 +- feed.go | 2 +- postrender.go | 35 +++++++++++++++-------------------- posts.go | 2 +- read.go | 4 ++-- 5 files changed, 20 insertions(+), 25 deletions(-) diff --git a/app.go b/app.go index dd86700..7ea5b04 100644 --- a/app.go +++ b/app.go @@ -142,7 +142,7 @@ func handleTemplatedPage(app *app, w http.ResponseWriter, r *http.Request, t *te if err != nil { return err } - p.Content = template.HTML(applyMarkdown([]byte(c))) + p.Content = template.HTML(applyMarkdown([]byte(c), "")) p.PlainContent = shortPostDescription(stripmd.Strip(c)) if updated != nil { p.Updated = updated.Format("January 2, 2006") diff --git a/feed.go b/feed.go index 61b1dac..89043d3 100644 --- a/feed.go +++ b/feed.go @@ -93,7 +93,7 @@ func ViewFeed(app *app, w http.ResponseWriter, req *http.Request) error { Title: title, Link: &Link{Href: permalink}, Description: "", - Content: applyMarkdown([]byte(p.Content)), + Content: applyMarkdown([]byte(p.Content), ""), Author: &Author{author, ""}, Created: p.Created, Updated: p.Updated, diff --git a/postrender.go b/postrender.go index 06b74a1..0aa9a01 100644 --- a/postrender.go +++ b/postrender.go @@ -11,7 +11,6 @@ package writefreely import ( - "bytes" "fmt" "github.com/microcosm-cc/bluemonday" stripmd "github.com/writeas/go-strip-markdown" @@ -31,7 +30,7 @@ var ( endBlockReg = regexp.MustCompile("\n") youtubeReg = regexp.MustCompile("(https?://www.youtube.com/embed/[a-zA-Z0-9\\-_]+)(\\?[^\t\n\f\r \"']+)?") titleElementReg = regexp.MustCompile("") - hashtagReg = regexp.MustCompile(`(?m)(^| )#([\p{L}\p{M}\d]+)`) + hashtagReg = regexp.MustCompile(`{{\[\[\|\|([^|]+)\|\|\]\]}}`) markeddownReg = regexp.MustCompile("

(.+)

") ) @@ -40,22 +39,10 @@ func (p *Post) formatContent(c *Collection, isOwner bool) { if !isSingleUser { baseURL = "/" + c.Alias + "/" } - newCon := hashtagReg.ReplaceAllFunc([]byte(p.Content), func(b []byte) []byte { - // Ensure we only replace "hashtags" that have already been extracted. - // `hashtagReg` catches everything, including any hash on the end of a - // URL, so we rely on p.Tags as the final word on whether or not to link - // a tag. - for _, t := range p.Tags { - if strings.TrimSpace(string(b)) == "#"+t { - return bytes.Replace(b, []byte("#"+t), []byte("#"+t+""), -1) - } - } - return b - }) p.HTMLTitle = template.HTML(applyBasicMarkdown([]byte(p.Title.String))) - p.HTMLContent = template.HTML(applyMarkdown([]byte(newCon))) - if exc := strings.Index(string(newCon), ""); exc > -1 { - p.HTMLExcerpt = template.HTML(applyMarkdown([]byte(newCon[:exc]))) + p.HTMLContent = template.HTML(applyMarkdown([]byte(p.Content), baseURL)) + if exc := strings.Index(string(p.Content), ""); exc > -1 { + p.HTMLExcerpt = template.HTML(applyMarkdown([]byte(p.Content[:exc]), baseURL)) } } @@ -63,11 +50,11 @@ func (p *PublicPost) formatContent(isOwner bool) { p.Post.formatContent(&p.Collection.Collection, isOwner) } -func applyMarkdown(data []byte) string { - return applyMarkdownSpecial(data, false) +func applyMarkdown(data []byte, baseURL string) string { + return applyMarkdownSpecial(data, false, baseURL) } -func applyMarkdownSpecial(data []byte, skipNoFollow bool) string { +func applyMarkdownSpecial(data []byte, skipNoFollow bool, baseURL string) string { mdExtensions := 0 | blackfriday.EXTENSION_TABLES | blackfriday.EXTENSION_FENCED_CODE | @@ -79,8 +66,16 @@ func applyMarkdownSpecial(data []byte, skipNoFollow bool) string { blackfriday.HTML_USE_SMARTYPANTS | blackfriday.HTML_SMARTYPANTS_DASHES + if baseURL != "" { + htmlFlags |= blackfriday.HTML_HASHTAGS + } + // Generate Markdown md := blackfriday.Markdown([]byte(data), blackfriday.HtmlRenderer(htmlFlags, "", ""), mdExtensions) + if baseURL != "" { + // Replace special text generated by Markdown parser + md = []byte(hashtagReg.ReplaceAll(md, []byte("#$1"))) + } // Strip out bad HTML policy := getSanitizationPolicy() policy.RequireNoFollowOnLinks(!skipNoFollow) diff --git a/posts.go b/posts.go index a8d8c40..6ae923d 100644 --- a/posts.go +++ b/posts.go @@ -368,7 +368,7 @@ func handleViewPost(app *app, w http.ResponseWriter, r *http.Request) error { Direction: d, } if !isRaw { - post.HTMLContent = template.HTML(applyMarkdown([]byte(content))) + post.HTMLContent = template.HTML(applyMarkdown([]byte(content), "")) } } diff --git a/read.go b/read.go index c1731cd..5098935 100644 --- a/read.go +++ b/read.go @@ -95,7 +95,7 @@ func (db *datastore) FetchPublicPosts() (interface{}, error) { } p.extractData() - p.HTMLContent = template.HTML(applyMarkdown([]byte(p.Content))) + p.HTMLContent = template.HTML(applyMarkdown([]byte(p.Content), "")) fp := p.processPost() if isCollectionPost { fp.Collection = &CollectionObj{Collection: *c} @@ -283,7 +283,7 @@ func viewLocalTimelineFeed(app *app, w http.ResponseWriter, req *http.Request) e Title: title, Link: &Link{Href: permalink}, Description: "", - Content: applyMarkdown([]byte(p.Content)), + Content: applyMarkdown([]byte(p.Content), ""), Author: &Author{author, ""}, Created: p.Created, Updated: p.Updated,