markdown.go (2228B)
1 // GoToSocial 2 // Copyright (C) GoToSocial Authors admin@gotosocial.org 3 // SPDX-License-Identifier: AGPL-3.0-or-later 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package text 19 20 import ( 21 "bytes" 22 "context" 23 24 "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" 25 "github.com/superseriousbusiness/gotosocial/internal/log" 26 "github.com/yuin/goldmark" 27 "github.com/yuin/goldmark/extension" 28 "github.com/yuin/goldmark/renderer/html" 29 ) 30 31 func (f *formatter) FromMarkdown(ctx context.Context, pmf gtsmodel.ParseMentionFunc, authorID string, statusID string, markdownText string) *FormatResult { 32 result := &FormatResult{ 33 Mentions: []*gtsmodel.Mention{}, 34 Tags: []*gtsmodel.Tag{}, 35 Emojis: []*gtsmodel.Emoji{}, 36 } 37 38 // parse markdown text into html, using custom renderer to add hashtag/mention links 39 md := goldmark.New( 40 goldmark.WithRendererOptions( 41 html.WithXHTML(), 42 html.WithHardWraps(), 43 html.WithUnsafe(), // allows raw HTML 44 ), 45 goldmark.WithExtensions( 46 &customRenderer{f, ctx, pmf, authorID, statusID, false, result}, 47 extension.Linkify, // turns URLs into links 48 extension.Strikethrough, 49 ), 50 ) 51 52 var htmlContentBytes bytes.Buffer 53 err := md.Convert([]byte(markdownText), &htmlContentBytes) 54 if err != nil { 55 log.Errorf(ctx, "error formatting markdown to HTML: %s", err) 56 } 57 result.HTML = htmlContentBytes.String() 58 59 // clean anything dangerous out of the HTML 60 result.HTML = SanitizeHTML(result.HTML) 61 62 // shrink ray 63 result.HTML, err = m.String("text/html", result.HTML) 64 if err != nil { 65 log.Errorf(ctx, "error minifying HTML: %s", err) 66 } 67 68 return result 69 }