Skip to content

Commit ea90dd0

Browse files
committed
Editor preview support for external renderers
There is an existing PREVIEWABLE_FILE_MODES setting for this purpose, but it didn't work for anything except markdown.
1 parent 68d7d77 commit ea90dd0

File tree

10 files changed

+93
-36
lines changed

10 files changed

+93
-36
lines changed

modules/markup/renderer.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,3 +317,15 @@ func IsMarkupFile(name, markup string) bool {
317317
}
318318
return false
319319
}
320+
321+
func PreviewableExtensions() []string {
322+
extensions := []string{}
323+
324+
for _, fileMode := range setting.Repository.Editor.PreviewableFileModes {
325+
if renderer, ok := renderers[fileMode]; ok {
326+
extensions = append(extensions, renderer.Extensions()...)
327+
}
328+
}
329+
330+
return extensions
331+
}

modules/structs/miscellaneous.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ type MarkdownOption struct {
3333
//
3434
// in: body
3535
Uncyclo bool
36+
// Path for extension detection
37+
//
38+
// in: body
39+
Path string
3640
}
3741

3842
// MarkdownRender is a rendered markdown document

routers/api/v1/misc/markdown.go

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ func Markdown(ctx *context.APIContext) {
5353
switch form.Mode {
5454
case "comment":
5555
fallthrough
56+
case "preview":
57+
fallthrough
5658
case "gfm":
5759
urlPrefix := form.Context
5860
meta := map[string]string{}
@@ -64,23 +66,36 @@ func Markdown(ctx *context.APIContext) {
6466
urlPrefix = util.URLJoin(setting.AppURL, form.Context)
6567
}
6668
}
69+
70+
// "gfm" = Github Flavored Markdown - set this to render as a markdown document
71+
// "preview" = file preview - render as document based on file extension
72+
// "comment" = render as markdown
6773
if ctx.Repo != nil && ctx.Repo.Repository != nil {
68-
// "gfm" = Github Flavored Markdown - set this to render as a document
69-
if form.Mode == "gfm" {
70-
meta = ctx.Repo.Repository.ComposeDocumentMetas()
71-
} else {
74+
if form.Mode == "comment" {
7275
meta = ctx.Repo.Repository.ComposeMetas()
76+
} else {
77+
meta = ctx.Repo.Repository.ComposeDocumentMetas()
7378
}
7479
}
75-
if form.Mode == "gfm" {
80+
if form.Mode != "comment" {
7681
meta["mode"] = "document"
7782
}
7883

79-
if err := markdown.Render(&markup.RenderContext{
80-
Ctx: ctx,
81-
URLPrefix: urlPrefix,
82-
Metas: meta,
83-
IsUncyclo: form.Uncyclo,
84+
markupType := ""
85+
relativePath := ""
86+
if form.Mode == "preview" {
87+
relativePath = form.Path
88+
} else {
89+
markupType = markdown.MarkupName
90+
}
91+
92+
if err := markup.Render(&markup.RenderContext{
93+
Ctx: ctx,
94+
URLPrefix: urlPrefix,
95+
Metas: meta,
96+
IsUncyclo: form.Uncyclo,
97+
Type: markupType,
98+
RelativePath: relativePath,
8499
}, strings.NewReader(form.Text), ctx.Resp); err != nil {
85100
ctx.InternalServerError(err)
86101
return

routers/api/v1/misc/markdown_test.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func wrap(ctx *context.Context) *context.APIContext {
4949
}
5050
}
5151

52-
func TestAPI_RenderGFM(t *testing.T) {
52+
func testRenderDocument(t *testing.T, mode, path string) {
5353
setting.AppURL = AppURL
5454
markup.Init(&markup.ProcessorHelper{
5555
IsUsernameMentionable: func(ctx go_context.Context, username string) bool {
@@ -58,10 +58,11 @@ func TestAPI_RenderGFM(t *testing.T) {
5858
})
5959

6060
options := api.MarkdownOption{
61-
Mode: "gfm",
61+
Mode: mode,
6262
Text: "",
6363
Context: Repo,
6464
Uncyclo: true,
65+
Path: path,
6566
}
6667
requrl, _ := url.Parse(util.URLJoin(AppURL, "api", "v1", "markdown"))
6768
req := &http.Request{
@@ -128,6 +129,14 @@ Here are some links to the most important topics. You can find the full list of
128129
}
129130
}
130131

132+
func TestAPI_RenderGFM(t *testing.T) {
133+
testRenderDocument(t, "gfm", "")
134+
}
135+
136+
func TestAPI_RenderPreview(t *testing.T) {
137+
testRenderDocument(t, "preview", "test/test.md")
138+
}
139+
131140
var simpleCases = []string{
132141
// Guard wiki sidebar: special syntax
133142
`[[Guardfile-DSL / Configuring-Guard|Guardfile-DSL---Configuring-Guard]]`,

routers/web/misc/markdown.go

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ func Markdown(ctx *context.Context) {
5454
switch form.Mode {
5555
case "comment":
5656
fallthrough
57+
case "preview":
58+
fallthrough
5759
case "gfm":
5860
urlPrefix := form.Context
5961
meta := map[string]string{}
@@ -65,23 +67,36 @@ func Markdown(ctx *context.Context) {
6567
urlPrefix = util.URLJoin(setting.AppURL, form.Context)
6668
}
6769
}
70+
71+
// "gfm" = Github Flavored Markdown - set this to render as a markdown document
72+
// "preview" = file preview - render as document based on file extension
73+
// "comment" = render as markdown
6874
if ctx.Repo != nil && ctx.Repo.Repository != nil {
69-
// "gfm" = Github Flavored Markdown - set this to render as a document
70-
if form.Mode == "gfm" {
71-
meta = ctx.Repo.Repository.ComposeDocumentMetas()
72-
} else {
75+
if form.Mode == "comment" {
7376
meta = ctx.Repo.Repository.ComposeMetas()
77+
} else {
78+
meta = ctx.Repo.Repository.ComposeDocumentMetas()
7479
}
7580
}
76-
if form.Mode == "gfm" {
81+
if form.Mode != "comment" {
7782
meta["mode"] = "document"
7883
}
7984

80-
if err := markdown.Render(&markup.RenderContext{
81-
Ctx: ctx,
82-
URLPrefix: urlPrefix,
83-
Metas: meta,
84-
IsUncyclo: form.Uncyclo,
85+
markupType := ""
86+
relativePath := ""
87+
if form.Mode == "preview" {
88+
relativePath = form.Path
89+
} else {
90+
markupType = markdown.MarkupName
91+
}
92+
93+
if err := markup.Render(&markup.RenderContext{
94+
Ctx: ctx,
95+
URLPrefix: urlPrefix,
96+
Metas: meta,
97+
IsUncyclo: form.Uncyclo,
98+
Type: markupType,
99+
RelativePath: relativePath,
85100
}, strings.NewReader(form.Text), ctx.Resp); err != nil {
86101
ctx.Error(http.StatusInternalServerError, err.Error())
87102
return

routers/web/repo/editor.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"code.gitea.io/gitea/modules/git"
2121
"code.gitea.io/gitea/modules/json"
2222
"code.gitea.io/gitea/modules/log"
23+
"code.gitea.io/gitea/modules/markup"
2324
"code.gitea.io/gitea/modules/setting"
2425
"code.gitea.io/gitea/modules/typesniffer"
2526
"code.gitea.io/gitea/modules/upload"
@@ -155,9 +156,8 @@ func editFile(ctx *context.Context, isNewFile bool) {
155156
}
156157
ctx.Data["new_branch_name"] = GetUniquePatchBranchName(ctx)
157158
ctx.Data["last_commit"] = ctx.Repo.CommitID
158-
ctx.Data["MarkdownFileExts"] = strings.Join(setting.Markdown.FileExtensions, ",")
159+
ctx.Data["PreviewableExtensions"] = strings.Join(markup.PreviewableExtensions(), ",")
159160
ctx.Data["LineWrapExtensions"] = strings.Join(setting.Repository.Editor.LineWrapExtensions, ",")
160-
ctx.Data["PreviewableFileModes"] = strings.Join(setting.Repository.Editor.PreviewableFileModes, ",")
161161
ctx.Data["Editorconfig"] = GetEditorConfig(ctx, treePath)
162162

163163
ctx.HTML(http.StatusOK, tplEditFile)
@@ -207,9 +207,8 @@ func editFilePost(ctx *context.Context, form forms.EditRepoFileForm, isNewFile b
207207
ctx.Data["commit_choice"] = form.CommitChoice
208208
ctx.Data["new_branch_name"] = form.NewBranchName
209209
ctx.Data["last_commit"] = ctx.Repo.CommitID
210-
ctx.Data["MarkdownFileExts"] = strings.Join(setting.Markdown.FileExtensions, ",")
210+
ctx.Data["PreviewableExtensions"] = strings.Join(markup.PreviewableExtensions(), ",")
211211
ctx.Data["LineWrapExtensions"] = strings.Join(setting.Repository.Editor.LineWrapExtensions, ",")
212-
ctx.Data["PreviewableFileModes"] = strings.Join(setting.Repository.Editor.PreviewableFileModes, ",")
213212
ctx.Data["Editorconfig"] = GetEditorConfig(ctx, form.TreePath)
214213

215214
if ctx.HasError() {

templates/repo/editor/edit.tmpl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,15 @@
3131
<div class="ui top attached tabular menu" data-write="write" data-preview="preview" data-diff="diff">
3232
<a class="active item" data-tab="write">{{svg "octicon-code"}} {{if .IsNewFile}}{{.locale.Tr "repo.editor.new_file"}}{{else}}{{.locale.Tr "repo.editor.edit_file"}}{{end}}</a>
3333
{{if not .IsNewFile}}
34-
<a class="item" data-tab="preview" data-url="{{.Repository.Link}}/markdown" data-context="{{.RepoLink}}/src/{{.BranchNameSubURL}}" data-preview-file-modes="{{.PreviewableFileModes}}" data-markdown-mode="gfm">{{svg "octicon-eye"}} {{.locale.Tr "preview"}}</a>
34+
<a class="item" data-tab="preview" data-url="{{.Repository.Link}}/markdown" data-context="{{.RepoLink}}/src/{{.BranchNameSubURL}}" data-markup-mode="preview">{{svg "octicon-eye"}} {{.locale.Tr "preview"}}</a>
3535
<a class="item" data-tab="diff" data-url="{{.RepoLink}}/_preview/{{.BranchName | PathEscapeSegments}}/{{.TreePath | PathEscapeSegments}}" data-context="{{.BranchLink}}">{{svg "octicon-diff"}} {{.locale.Tr "repo.editor.preview_changes"}}</a>
3636
{{end}}
3737
</div>
3838
<div class="ui bottom attached active tab segment" data-tab="write">
3939
<textarea id="edit_area" name="content" class="gt-hidden" data-id="repo-{{.Repository.Name}}-{{.TreePath}}"
4040
data-url="{{.Repository.Link}}/markdown"
4141
data-context="{{.RepoLink}}"
42-
data-markdown-file-exts="{{.MarkdownFileExts}}"
42+
data-previewable-extensions="{{.PreviewableExtensions}}"
4343
data-line-wrap-extensions="{{.LineWrapExtensions}}">
4444
{{.FileContent}}</textarea>
4545
<div class="editor-loading is-loading"></div>

templates/swagger/v1_json.tmpl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17681,6 +17681,10 @@
1768117681
"description": "Mode to render\n\nin: body",
1768217682
"type": "string"
1768317683
},
17684+
"Path": {
17685+
"description": "Path for extension detection\n\nin: body",
17686+
"type": "string"
17687+
},
1768417688
"Text": {
1768517689
"description": "Text markdown to render\n\nin: body",
1768617690
"type": "string"

web_src/js/features/codeeditor.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,16 +130,16 @@ function getFileBasedOptions(filename, lineWrapExts) {
130130
};
131131
}
132132

133-
export async function createCodeEditor(textarea, filenameInput, previewFileModes) {
133+
export async function createCodeEditor(textarea, filenameInput) {
134134
const filename = basename(filenameInput.value);
135135
const previewLink = document.querySelector('a[data-tab=preview]');
136-
const markdownExts = (textarea.getAttribute('data-markdown-file-exts') || '').split(',');
136+
const previewableExts = (textarea.getAttribute('data-previewable-extensions') || '').split(',');
137137
const lineWrapExts = (textarea.getAttribute('data-line-wrap-extensions') || '').split(',');
138-
const isMarkdown = markdownExts.includes(extname(filename));
138+
const previewable = previewableExts.includes(extname(filename));
139139
const editorConfig = getEditorconfig(filenameInput);
140140

141141
if (previewLink) {
142-
if (isMarkdown && (previewFileModes || []).includes('markdown')) {
142+
if (previewable) {
143143
const newUrl = (previewLink.getAttribute('data-url') || '').replace(/(.*)\/.*/i, `$1/markdown`);
144144
previewLink.setAttribute('data-url', newUrl);
145145
previewLink.style.display = '';

web_src/js/features/repo-editor.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,16 @@ import {createCodeEditor} from './codeeditor.js';
55
import {hideElem, showElem} from '../utils/dom.js';
66

77
const {csrfToken} = window.config;
8-
let previewFileModes;
98

109
function initEditPreviewTab($form) {
1110
const $tabMenu = $form.find('.tabular.menu');
1211
$tabMenu.find('.item').tab();
1312
const $previewTab = $tabMenu.find(`.item[data-tab="${$tabMenu.data('preview')}"]`);
1413
if ($previewTab.length) {
15-
previewFileModes = $previewTab.data('preview-file-modes').split(',');
1614
$previewTab.on('click', function () {
1715
const $this = $(this);
1816
let context = `${$this.data('context')}/`;
19-
const mode = $this.data('markdown-mode') || 'comment';
17+
const mode = $this.data('markup-mode') || 'comment';
2018
const treePathEl = $form.find('input#tree_path');
2119
if (treePathEl.length > 0) {
2220
context += treePathEl.val();
@@ -27,6 +25,7 @@ function initEditPreviewTab($form) {
2725
mode,
2826
context,
2927
text: $form.find(`.tab[data-tab="${$tabMenu.data('write')}"] textarea`).val(),
28+
path: treePathEl.val(),
3029
}, (data) => {
3130
const $previewPanel = $form.find(`.tab[data-tab="${$tabMenu.data('preview')}"]`);
3231
$previewPanel.html(data);
@@ -147,7 +146,7 @@ export function initRepoEditor() {
147146
if (!$editArea.length) return;
148147

149148
(async () => {
150-
const editor = await createCodeEditor($editArea[0], $editFilename[0], previewFileModes);
149+
const editor = await createCodeEditor($editArea[0], $editFilename[0]);
151150

152151
// Using events from https://github.com/codedance/jquery.AreYouSure#advanced-usage
153152
// to enable or disable the commit button

0 commit comments

Comments
 (0)