Skip to content

Commit ad73811

Browse files
authored
Merge pull request #1362 from getfider/markdown-image-support
Added support for URL based images.
2 parents 4223e73 + c7d1fe5 commit ad73811

File tree

13 files changed

+80
-39
lines changed

13 files changed

+80
-39
lines changed

app/handlers/apiv1/invite.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func SendSampleInvite() web.HandlerFunc {
2626
action.Message = strings.Replace(action.Message, app.InvitePlaceholder, "*[the link to join will be here]*", -1)
2727
to := dto.NewRecipient(c.User().Name, c.User().Email, dto.Props{
2828
"subject": action.Subject,
29-
"message": markdown.Full(action.Message),
29+
"message": markdown.Full(action.Message, true),
3030
})
3131

3232
bus.Publish(c, &cmd.SendMail{

app/handlers/feed.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,17 @@ package handlers
33
import (
44
"encoding/xml"
55
"fmt"
6-
"github.com/getfider/fider/app/models/entity"
7-
"github.com/getfider/fider/app/pkg/env"
8-
"github.com/getfider/fider/app/pkg/i18n"
9-
"github.com/getfider/fider/app/pkg/markdown"
106
"html"
117
"net/http"
128
"strconv"
139
"strings"
1410
"time"
1511

12+
"github.com/getfider/fider/app/models/entity"
13+
"github.com/getfider/fider/app/pkg/env"
14+
"github.com/getfider/fider/app/pkg/i18n"
15+
"github.com/getfider/fider/app/pkg/markdown"
16+
1617
"github.com/getfider/fider/app/models/query"
1718
"github.com/getfider/fider/app/pkg/bus"
1819
"github.com/getfider/fider/app/pkg/web"
@@ -119,7 +120,7 @@ func generatePostContent(c *web.Context, post *entity.Post, options *generatorOp
119120
})
120121
}
121122

122-
return string(markdown.Full(title + post.Description + footer))
123+
return string(markdown.Full(title+post.Description+footer, true))
123124
}
124125

125126
func appendTags(c *web.Context, categories []*Category, post *entity.Post) ([]*Category, error) {
@@ -158,7 +159,7 @@ func GlobalFeed() web.HandlerFunc {
158159

159160
feed := &AtomFeed{
160161
Title: c.Tenant().Name,
161-
Subtitle: Content{Body: string(markdown.Full(c.Tenant().WelcomeMessage)), Type: "html"},
162+
Subtitle: Content{Body: string(markdown.Full(c.Tenant().WelcomeMessage, true)), Type: "html"},
162163
Id: web.BaseURL(c),
163164
Link: []Link{
164165
{Href: fmt.Sprintf("%s/feed/global.atom", web.BaseURL(c)), Type: "application/atom+xml", Rel: "self"},
@@ -246,7 +247,7 @@ func CommentFeed() web.HandlerFunc {
246247

247248
feed := &AtomFeed{
248249
Title: post.Title,
249-
Subtitle: Content{Body: string(markdown.Full(post.Description)), Type: "html"},
250+
Subtitle: Content{Body: string(markdown.Full(post.Description, true)), Type: "html"},
250251
Author: &Author{Name: post.User.Name},
251252
Id: fmt.Sprintf("%s/posts/%d/#comments", web.BaseURL(c), post.Number),
252253
Link: []Link{
@@ -288,7 +289,7 @@ func CommentFeed() web.HandlerFunc {
288289
Link: []Link{
289290
{Href: fmt.Sprintf("%s/posts/%d", web.BaseURL(c), post.Number), Type: "text/html", Rel: "alternate"},
290291
},
291-
Content: &Content{Type: "html", Body: string(markdown.Full(post.Response.Text))},
292+
Content: &Content{Type: "html", Body: string(markdown.Full(post.Response.Text, true))},
292293
Categories: []*Category{{Term: i18n.T(c, "enum.poststatus."+post.Status.Name())}},
293294
})
294295
}
@@ -314,7 +315,7 @@ func CommentFeed() web.HandlerFunc {
314315
}
315316
return formatTime(*comment.EditedAt)
316317
}(),
317-
Content: &Content{Type: "html", Body: string(markdown.Full(html.UnescapeString(comment.Content)))},
318+
Content: &Content{Type: "html", Body: string(markdown.Full(html.UnescapeString(comment.Content), true))},
318319
Id: fmt.Sprintf("%s/posts/%d/#comment-%d", web.BaseURL(c), post.Number, comment.ID),
319320
Link: []Link{{Href: fmt.Sprintf("%s/posts/%d/#comment-%d", web.BaseURL(c), post.Number, comment.ID), Type: "text/html", Rel: "alternate"}},
320321
})

app/pkg/markdown/markdown.go

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,28 +31,38 @@ var htmlFlags = 0 |
3131
htmlrenderer.NofollowLinks |
3232
htmlrenderer.NoreferrerLinks
3333

34-
var fullRenderer = htmlrenderer.NewRenderer(htmlrenderer.RendererOptions{
35-
Flags: htmlFlags,
36-
RenderNodeHook: func(w io.Writer, node ast.Node, entering bool) (ast.WalkStatus, bool) {
37-
switch node := node.(type) {
38-
case *ast.HTMLSpan:
39-
htmlrenderer.EscapeHTML(w, node.Literal)
40-
return ast.GoToNext, true
41-
case *ast.HTMLBlock:
42-
_, _ = io.WriteString(w, "\n")
43-
htmlrenderer.EscapeHTML(w, node.Literal)
44-
_, _ = io.WriteString(w, "\n")
45-
return ast.GoToNext, true
46-
}
47-
return ast.GoToNext, false
48-
},
49-
})
34+
func createRenderer(handleImages bool) *htmlrenderer.Renderer {
35+
return htmlrenderer.NewRenderer(htmlrenderer.RendererOptions{
36+
Flags: htmlFlags,
37+
RenderNodeHook: func(w io.Writer, node ast.Node, entering bool) (ast.WalkStatus, bool) {
38+
switch node := node.(type) {
39+
case *ast.HTMLSpan:
40+
htmlrenderer.EscapeHTML(w, node.Literal)
41+
return ast.GoToNext, true
42+
case *ast.HTMLBlock:
43+
_, _ = io.WriteString(w, "\n")
44+
htmlrenderer.EscapeHTML(w, node.Literal)
45+
_, _ = io.WriteString(w, "\n")
46+
return ast.GoToNext, true
47+
case *ast.Image:
48+
if !handleImages {
49+
// Skip images entirely when handleImages is false
50+
return ast.SkipChildren, true
51+
}
52+
}
53+
return ast.GoToNext, false
54+
},
55+
})
56+
}
5057

5158
// Full turns a markdown into HTML using all rules
52-
func Full(input string) template.HTML {
59+
func Full(input string, handleImages bool) template.HTML {
5360
// Apparently a parser cannot be reused.
5461
// https://github.com/gomarkdown/markdown/issues/229
5562
parser := mdparser.NewWithExtensions(mdExtns)
56-
output := markdown.ToHTML([]byte(input), parser, fullRenderer)
63+
64+
renderer := createRenderer(handleImages)
65+
66+
output := markdown.ToHTML([]byte(input), parser, renderer)
5767
return template.HTML(strings.TrimSpace(string(output)))
5868
}

app/pkg/markdown/markdown_test.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,24 @@ This will allow to send and receive SMS and get the IMEI No. in our app.</p>
4545
4646
<p>Thanks!</p>`,
4747
} {
48-
output := markdown.Full(input)
48+
output := markdown.Full(input, true)
49+
Expect(output).Equals(template.HTML(expected))
50+
}
51+
}
52+
53+
func TestFullMarkdownWithoutImages(t *testing.T) {
54+
RegisterT(t)
55+
56+
for input, expected := range map[string]string{
57+
"# Hello World": `<h1>Hello World</h1>`,
58+
"![](http://example.com/hello.jpg)": `<p></p>`,
59+
"![Alt text](http://example.com/hello.jpg)": `<p></p>`,
60+
"Text before ![image](http://example.com/hello.jpg) text after": `<p>Text before text after</p>`,
61+
"![Image 1](http://example.com/1.jpg)![Image 2](http://example.com/2.jpg)": `<p></p>`,
62+
"Hello **bold** text with ![image](http://example.com/hello.jpg)": `<p>Hello <strong>bold</strong> text with </p>`,
63+
"Go to http://example.com/hello.jpg": `<p>Go to <a href="http://example.com/hello.jpg" rel="nofollow noreferrer">http://example.com/hello.jpg</a></p>`,
64+
} {
65+
output := markdown.Full(input, false)
4966
Expect(output).Equals(template.HTML(expected))
5067
}
5168
}

app/pkg/tpl/funcs.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ var templateFunctions = map[string]any{
3636
return "This is overwritten later on..."
3737
},
3838
"markdown": func(input string) template.HTML {
39-
return markdown.Full(input)
39+
return markdown.Full(input, true)
4040
},
4141
"dict": func(values ...any) map[string]any {
4242
if len(values)%2 != 0 {

app/tasks/delete_post.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ func NotifyAboutDeletedPost(post *entity.Post, deleteCommentAdded bool) worker.T
7979
props := dto.Props{
8080
"title": post.Title,
8181
"siteName": tenant.Name,
82-
"content": markdown.Full(post.Response.Text),
82+
"content": markdown.Full(post.Response.Text, true),
8383
"change": linkWithText(i18n.T(c, "email.subscription.change"), baseURL, "/settings"),
8484
"logo": logoURL,
8585
}

app/tasks/invites.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515
"github.com/getfider/fider/app/pkg/worker"
1616
)
1717

18-
//SendInvites sends one email to each invited recipient
18+
// SendInvites sends one email to each invited recipient
1919
func SendInvites(subject, message string, invitations []*actions.UserInvitation) worker.Task {
2020
return describe("Send invites", func(c *worker.Context) error {
2121
to := make([]dto.Recipient, len(invitations))
@@ -32,7 +32,7 @@ func SendInvites(subject, message string, invitations []*actions.UserInvitation)
3232
url := fmt.Sprintf("%s/invite/verify?k=%s", web.BaseURL(c), invite.VerificationKey)
3333
toMessage := strings.Replace(message, app.InvitePlaceholder, url, -1)
3434
to[i] = dto.NewRecipient("", invite.Email, dto.Props{
35-
"message": markdown.Full(toMessage),
35+
"message": markdown.Full(toMessage, true),
3636
})
3737
}
3838

app/tasks/new_comment.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ func sendEmailNotifications(c *worker.Context, post *entity.Post, to []dto.Recip
298298
"messageLocaleString": messaleLocaleString,
299299
"siteName": tenant.Name,
300300
"userName": author.Name,
301-
"content": markdown.Full(comment),
301+
"content": markdown.Full(comment, false),
302302
"postLink": linkWithText(fmt.Sprintf("#%d", post.Number), baseURL, "/posts/%d/%s", post.Number, post.Slug),
303303
"view": linkWithText(i18n.T(c, "email.subscription.view"), baseURL, "/posts/%d/%s", post.Number, post.Slug),
304304
"unsubscribe": linkWithText(i18n.T(c, "email.subscription.unsubscribe"), baseURL, "/posts/%d/%s", post.Number, post.Slug),

app/tasks/new_post.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ func NotifyAboutNewPost(post *entity.Post) worker.Task {
119119
"title": post.Title,
120120
"siteName": tenant.Name,
121121
"userName": author.Name,
122-
"content": markdown.Full(contentString.SanitizeMentions()),
122+
"content": markdown.Full(contentString.SanitizeMentions(), false),
123123
"postLink": linkWithText(fmt.Sprintf("#%d", post.Number), baseURL, "/posts/%d/%s", post.Number, post.Slug),
124124
"view": linkWithText(i18n.T(c, "email.subscription.view"), baseURL, "/posts/%d/%s", post.Number, post.Slug),
125125
"change": linkWithText(i18n.T(c, "email.subscription.change"), baseURL, "/settings"),

app/tasks/status_change.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515
"github.com/getfider/fider/app/pkg/worker"
1616
)
1717

18-
//NotifyAboutStatusChange sends a notification (web and email) to subscribers
18+
// NotifyAboutStatusChange sends a notification (web and email) to subscribers
1919
func NotifyAboutStatusChange(post *entity.Post, prevStatus enum.PostStatus) worker.Task {
2020
return describe("Notify about post status change", func(c *worker.Context) error {
2121
//Don't notify if previous status is the same
@@ -72,7 +72,7 @@ func NotifyAboutStatusChange(post *entity.Post, prevStatus enum.PostStatus) work
7272
"title": post.Title,
7373
"postLink": linkWithText(fmt.Sprintf("#%d", post.Number), baseURL, "/posts/%d/%s", post.Number, post.Slug),
7474
"siteName": tenant.Name,
75-
"content": markdown.Full(post.Response.Text),
75+
"content": markdown.Full(post.Response.Text, true),
7676
"status": i18n.T(c, fmt.Sprintf("enum.poststatus.%s", post.Status.Name())),
7777
"duplicate": duplicate,
7878
"view": linkWithText(i18n.T(c, "email.subscription.view"), baseURL, "/posts/%d/%s", post.Number, post.Slug),

0 commit comments

Comments
 (0)