mirror of https://github.com/go-gitea/gitea
Editor preview support for external renderers (#23333)
Remove `[repository.editor] PREVIEWABLE_FILE_MODES` setting that seemed like it was intended to support this but did not work. Instead, whenever viewing a file shows a preview, also have a Preview tab in the file editor. Add new `/markup` web and API endpoints with `comment`, `gfm`, `markdown` and new `file` mode that uses a file path to determine the renderer. Remove `/markdown` web endpoint but keep the API for backwards and GitHub compatibility. ## ⚠️ BREAKING ⚠️ The `[repository.editor] PREVIEWABLE_FILE_MODES` setting was removed. This setting served no practical purpose and was not working correctly. Instead a preview tab is always shown in the file editor when supported. --------- Co-authored-by: zeripath <art27@cantab.net> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>pull/23653/head^2
parent
9e04627aca
commit
84daddc2fa
@ -0,0 +1,92 @@ |
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package common |
||||
|
||||
import ( |
||||
"fmt" |
||||
"net/http" |
||||
"strings" |
||||
|
||||
"code.gitea.io/gitea/modules/context" |
||||
"code.gitea.io/gitea/modules/markup" |
||||
"code.gitea.io/gitea/modules/markup/markdown" |
||||
"code.gitea.io/gitea/modules/setting" |
||||
"code.gitea.io/gitea/modules/util" |
||||
|
||||
"mvdan.cc/xurls/v2" |
||||
) |
||||
|
||||
// RenderMarkup renders markup text for the /markup and /markdown endpoints
|
||||
func RenderMarkup(ctx *context.Context, mode, text, urlPrefix, filePath string, wiki bool) { |
||||
markupType := "" |
||||
relativePath := "" |
||||
|
||||
if len(text) == 0 { |
||||
_, _ = ctx.Write([]byte("")) |
||||
return |
||||
} |
||||
|
||||
switch mode { |
||||
case "markdown": |
||||
// Raw markdown
|
||||
if err := markdown.RenderRaw(&markup.RenderContext{ |
||||
Ctx: ctx, |
||||
URLPrefix: urlPrefix, |
||||
}, strings.NewReader(text), ctx.Resp); err != nil { |
||||
ctx.Error(http.StatusInternalServerError, err.Error()) |
||||
} |
||||
return |
||||
case "comment": |
||||
// Comment as markdown
|
||||
markupType = markdown.MarkupName |
||||
case "gfm": |
||||
// Github Flavored Markdown as document
|
||||
markupType = markdown.MarkupName |
||||
case "file": |
||||
// File as document based on file extension
|
||||
markupType = "" |
||||
relativePath = filePath |
||||
default: |
||||
ctx.Error(http.StatusUnprocessableEntity, fmt.Sprintf("Unknown mode: %s", mode)) |
||||
return |
||||
} |
||||
|
||||
if !strings.HasPrefix(setting.AppSubURL+"/", urlPrefix) { |
||||
// check if urlPrefix is already set to a URL
|
||||
linkRegex, _ := xurls.StrictMatchingScheme("https?://") |
||||
m := linkRegex.FindStringIndex(urlPrefix) |
||||
if m == nil { |
||||
urlPrefix = util.URLJoin(setting.AppURL, urlPrefix) |
||||
} |
||||
} |
||||
|
||||
meta := map[string]string{} |
||||
if ctx.Repo != nil && ctx.Repo.Repository != nil { |
||||
if mode == "comment" { |
||||
meta = ctx.Repo.Repository.ComposeMetas() |
||||
} else { |
||||
meta = ctx.Repo.Repository.ComposeDocumentMetas() |
||||
} |
||||
} |
||||
if mode != "comment" { |
||||
meta["mode"] = "document" |
||||
} |
||||
|
||||
if err := markup.Render(&markup.RenderContext{ |
||||
Ctx: ctx, |
||||
URLPrefix: urlPrefix, |
||||
Metas: meta, |
||||
IsWiki: wiki, |
||||
Type: markupType, |
||||
RelativePath: relativePath, |
||||
}, strings.NewReader(text), ctx.Resp); err != nil { |
||||
if markup.IsErrUnsupportedRenderExtension(err) { |
||||
ctx.Error(http.StatusUnprocessableEntity, err.Error()) |
||||
} else { |
||||
ctx.Error(http.StatusInternalServerError, err.Error()) |
||||
} |
||||
return |
||||
} |
||||
} |
@ -1,98 +0,0 @@ |
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package misc |
||||
|
||||
import ( |
||||
"net/http" |
||||
"strings" |
||||
|
||||
"code.gitea.io/gitea/modules/context" |
||||
"code.gitea.io/gitea/modules/markup" |
||||
"code.gitea.io/gitea/modules/markup/markdown" |
||||
"code.gitea.io/gitea/modules/setting" |
||||
api "code.gitea.io/gitea/modules/structs" |
||||
"code.gitea.io/gitea/modules/util" |
||||
"code.gitea.io/gitea/modules/web" |
||||
|
||||
"mvdan.cc/xurls/v2" |
||||
) |
||||
|
||||
// Markdown render markdown document to HTML
|
||||
func Markdown(ctx *context.Context) { |
||||
// swagger:operation POST /markdown miscellaneous renderMarkdown
|
||||
// ---
|
||||
// summary: Render a markdown document as HTML
|
||||
// parameters:
|
||||
// - name: body
|
||||
// in: body
|
||||
// schema:
|
||||
// "$ref": "#/definitions/MarkdownOption"
|
||||
// consumes:
|
||||
// - application/json
|
||||
// produces:
|
||||
// - text/html
|
||||
// responses:
|
||||
// "200":
|
||||
// "$ref": "#/responses/MarkdownRender"
|
||||
// "422":
|
||||
// "$ref": "#/responses/validationError"
|
||||
|
||||
form := web.GetForm(ctx).(*api.MarkdownOption) |
||||
|
||||
if ctx.HasAPIError() { |
||||
ctx.Error(http.StatusUnprocessableEntity, "", ctx.GetErrMsg()) |
||||
return |
||||
} |
||||
|
||||
if len(form.Text) == 0 { |
||||
_, _ = ctx.Write([]byte("")) |
||||
return |
||||
} |
||||
|
||||
switch form.Mode { |
||||
case "comment": |
||||
fallthrough |
||||
case "gfm": |
||||
urlPrefix := form.Context |
||||
meta := map[string]string{} |
||||
if !strings.HasPrefix(setting.AppSubURL+"/", urlPrefix) { |
||||
// check if urlPrefix is already set to a URL
|
||||
linkRegex, _ := xurls.StrictMatchingScheme("https?://") |
||||
m := linkRegex.FindStringIndex(urlPrefix) |
||||
if m == nil { |
||||
urlPrefix = util.URLJoin(setting.AppURL, form.Context) |
||||
} |
||||
} |
||||
if ctx.Repo != nil && ctx.Repo.Repository != nil { |
||||
// "gfm" = Github Flavored Markdown - set this to render as a document
|
||||
if form.Mode == "gfm" { |
||||
meta = ctx.Repo.Repository.ComposeDocumentMetas() |
||||
} else { |
||||
meta = ctx.Repo.Repository.ComposeMetas() |
||||
} |
||||
} |
||||
if form.Mode == "gfm" { |
||||
meta["mode"] = "document" |
||||
} |
||||
|
||||
if err := markdown.Render(&markup.RenderContext{ |
||||
Ctx: ctx, |
||||
URLPrefix: urlPrefix, |
||||
Metas: meta, |
||||
IsWiki: form.Wiki, |
||||
}, strings.NewReader(form.Text), ctx.Resp); err != nil { |
||||
ctx.Error(http.StatusInternalServerError, err.Error()) |
||||
return |
||||
} |
||||
default: |
||||
if err := markdown.RenderRaw(&markup.RenderContext{ |
||||
Ctx: ctx, |
||||
URLPrefix: form.Context, |
||||
}, strings.NewReader(form.Text), ctx.Resp); err != nil { |
||||
ctx.Error(http.StatusInternalServerError, err.Error()) |
||||
return |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,44 @@ |
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package misc |
||||
|
||||
import ( |
||||
"net/http" |
||||
|
||||
"code.gitea.io/gitea/modules/context" |
||||
api "code.gitea.io/gitea/modules/structs" |
||||
"code.gitea.io/gitea/modules/web" |
||||
"code.gitea.io/gitea/routers/common" |
||||
) |
||||
|
||||
// Markup render markup document to HTML
|
||||
func Markup(ctx *context.Context) { |
||||
// swagger:operation POST /markup miscellaneous renderMarkup
|
||||
// ---
|
||||
// summary: Render a markup document as HTML
|
||||
// parameters:
|
||||
// - name: body
|
||||
// in: body
|
||||
// schema:
|
||||
// "$ref": "#/definitions/MarkupOption"
|
||||
// consumes:
|
||||
// - application/json
|
||||
// produces:
|
||||
// - text/html
|
||||
// responses:
|
||||
// "200":
|
||||
// "$ref": "#/responses/MarkupRender"
|
||||
// "422":
|
||||
// "$ref": "#/responses/validationError"
|
||||
|
||||
form := web.GetForm(ctx).(*api.MarkupOption) |
||||
|
||||
if ctx.HasAPIError() { |
||||
ctx.Error(http.StatusUnprocessableEntity, "", ctx.GetErrMsg()) |
||||
return |
||||
} |
||||
|
||||
common.RenderMarkup(ctx, form.Mode, form.Text, form.Context, form.FilePath, form.Wiki) |
||||
} |
Loading…
Reference in new issue