code.gitea.io/gitea@v1.22.3/routers/common/markup.go (about) 1 // Copyright 2014 The Gogs Authors. All rights reserved. 2 // Copyright 2023 The Gitea Authors. All rights reserved. 3 // SPDX-License-Identifier: MIT 4 5 package common 6 7 import ( 8 "fmt" 9 "net/http" 10 "path" 11 "strings" 12 13 "code.gitea.io/gitea/modules/httplib" 14 "code.gitea.io/gitea/modules/markup" 15 "code.gitea.io/gitea/modules/markup/markdown" 16 "code.gitea.io/gitea/modules/setting" 17 "code.gitea.io/gitea/services/context" 18 ) 19 20 // RenderMarkup renders markup text for the /markup and /markdown endpoints 21 func RenderMarkup(ctx *context.Base, repo *context.Repository, mode, text, urlPathContext, filePath string, wiki bool) { 22 // urlPathContext format is "/subpath/{user}/{repo}/src/{branch, commit, tag}/{identifier/path}/{file/dir}" 23 // filePath is the path of the file to render if the end user is trying to preview a repo file (mode == "file") 24 // filePath will be used as RenderContext.RelativePath 25 26 // for example, when previewing file "/gitea/owner/repo/src/branch/features/feat-123/doc/CHANGE.md", then filePath is "doc/CHANGE.md" 27 // and the urlPathContext is "/gitea/owner/repo/src/branch/features/feat-123/doc" 28 29 var markupType, relativePath string 30 31 links := markup.Links{AbsolutePrefix: true} 32 if urlPathContext != "" { 33 links.Base = fmt.Sprintf("%s%s", httplib.GuessCurrentHostURL(ctx), urlPathContext) 34 } 35 36 switch mode { 37 case "markdown": 38 // Raw markdown 39 if err := markdown.RenderRaw(&markup.RenderContext{ 40 Ctx: ctx, 41 Links: links, 42 }, strings.NewReader(text), ctx.Resp); err != nil { 43 ctx.Error(http.StatusInternalServerError, err.Error()) 44 } 45 return 46 case "comment": 47 // Issue & comment content 48 markupType = markdown.MarkupName 49 case "gfm": 50 // GitHub Flavored Markdown 51 markupType = markdown.MarkupName 52 case "file": 53 markupType = "" // render the repo file content by its extension 54 relativePath = filePath 55 default: 56 ctx.Error(http.StatusUnprocessableEntity, fmt.Sprintf("Unknown mode: %s", mode)) 57 return 58 } 59 60 fields := strings.SplitN(strings.TrimPrefix(urlPathContext, setting.AppSubURL+"/"), "/", 5) 61 if len(fields) == 5 && fields[2] == "src" && (fields[3] == "branch" || fields[3] == "commit" || fields[3] == "tag") { 62 // absolute base prefix is something like "https://host/subpath/{user}/{repo}" 63 absoluteBasePrefix := fmt.Sprintf("%s%s/%s", httplib.GuessCurrentAppURL(ctx), fields[0], fields[1]) 64 65 fileDir := path.Dir(filePath) // it is "doc" if filePath is "doc/CHANGE.md" 66 refPath := strings.Join(fields[3:], "/") // it is "branch/features/feat-12/doc" 67 refPath = strings.TrimSuffix(refPath, "/"+fileDir) // now we get the correct branch path: "branch/features/feat-12" 68 69 links = markup.Links{AbsolutePrefix: true, Base: absoluteBasePrefix, BranchPath: refPath, TreePath: fileDir} 70 } 71 72 meta := map[string]string{} 73 if repo != nil && repo.Repository != nil { 74 if mode == "comment" { 75 meta = repo.Repository.ComposeMetas(ctx) 76 } else { 77 meta = repo.Repository.ComposeDocumentMetas(ctx) 78 } 79 } 80 if mode != "comment" { 81 meta["mode"] = "document" 82 } 83 84 if err := markup.Render(&markup.RenderContext{ 85 Ctx: ctx, 86 Links: links, 87 Metas: meta, 88 IsWiki: wiki, 89 Type: markupType, 90 RelativePath: relativePath, 91 }, strings.NewReader(text), ctx.Resp); err != nil { 92 if markup.IsErrUnsupportedRenderExtension(err) { 93 ctx.Error(http.StatusUnprocessableEntity, err.Error()) 94 } else { 95 ctx.Error(http.StatusInternalServerError, err.Error()) 96 } 97 return 98 } 99 }