Improve issue autolinks (#6273)

* Improve issue autolinks

Update autolinks to match what github does here:

Issue in same repo: #1
Issue in different repo: org/repo#1

Fixes #6264

* Use setting.AppURL when parsing URL

Using setting.AppURL here is a more reliable way of parsing the current
URL and what other functions in this file seem to use.

* Make ComposeMetas always return a valid context

* Add per repository markdown renderers for better context

* Update for use of context metas

Now that we include the user and repo name inside context metas, update
various code and tests for this new logic
This commit is contained in:
mrsdizzie 2019-04-12 01:53:34 -04:00 committed by Lauris BH
parent 3186ef554c
commit 3ff0a126e1
13 changed files with 94 additions and 37 deletions

View file

@ -469,19 +469,19 @@ func (repo *Repository) mustOwnerName(e Engine) string {
return repo.OwnerName return repo.OwnerName
} }
// ComposeMetas composes a map of metas for rendering external issue tracker URL. // ComposeMetas composes a map of metas for properly rendering issue links and external issue trackers.
func (repo *Repository) ComposeMetas() map[string]string { func (repo *Repository) ComposeMetas() map[string]string {
unit, err := repo.GetUnit(UnitTypeExternalTracker)
if err != nil {
return nil
}
if repo.ExternalMetas == nil { if repo.ExternalMetas == nil {
repo.ExternalMetas = map[string]string{ repo.ExternalMetas = map[string]string{
"format": unit.ExternalTrackerConfig().ExternalTrackerFormat,
"user": repo.MustOwner().Name, "user": repo.MustOwner().Name,
"repo": repo.Name, "repo": repo.Name,
} }
unit, err := repo.GetUnit(UnitTypeExternalTracker)
if err != nil {
return repo.ExternalMetas
}
repo.ExternalMetas["format"] = unit.ExternalTrackerConfig().ExternalTrackerFormat
switch unit.ExternalTrackerConfig().ExternalTrackerStyle { switch unit.ExternalTrackerConfig().ExternalTrackerStyle {
case markup.IssueNameStyleAlphanumeric: case markup.IssueNameStyleAlphanumeric:
repo.ExternalMetas["style"] = markup.IssueNameStyleAlphanumeric repo.ExternalMetas["style"] = markup.IssueNameStyleAlphanumeric

View file

@ -20,7 +20,10 @@ func TestRepo(t *testing.T) {
repo.Owner = &User{Name: "testOwner"} repo.Owner = &User{Name: "testOwner"}
repo.Units = nil repo.Units = nil
assert.Nil(t, repo.ComposeMetas())
metas := repo.ComposeMetas()
assert.Equal(t, "testRepo", metas["repo"])
assert.Equal(t, "testOwner", metas["user"])
externalTracker := RepoUnit{ externalTracker := RepoUnit{
Type: UnitTypeExternalTracker, Type: UnitTypeExternalTracker,

View file

@ -551,20 +551,37 @@ func shortLinkProcessorFull(ctx *postProcessCtx, node *html.Node, noLink bool) {
} }
func fullIssuePatternProcessor(ctx *postProcessCtx, node *html.Node) { func fullIssuePatternProcessor(ctx *postProcessCtx, node *html.Node) {
if ctx.metas == nil {
return
}
m := getIssueFullPattern().FindStringSubmatchIndex(node.Data) m := getIssueFullPattern().FindStringSubmatchIndex(node.Data)
if m == nil { if m == nil {
return return
} }
link := node.Data[m[0]:m[1]] link := node.Data[m[0]:m[1]]
id := "#" + node.Data[m[2]:m[3]] id := "#" + node.Data[m[2]:m[3]]
// extract repo and org name from matched link like
// http://localhost:3000/gituser/myrepo/issues/1
linkParts := strings.Split(path.Clean(link), "/")
matchOrg := linkParts[len(linkParts)-4]
matchRepo := linkParts[len(linkParts)-3]
if matchOrg == ctx.metas["user"] && matchRepo == ctx.metas["repo"] {
// TODO if m[4]:m[5] is not nil, then link is to a comment, // TODO if m[4]:m[5] is not nil, then link is to a comment,
// and we should indicate that in the text somehow // and we should indicate that in the text somehow
replaceContent(node, m[0], m[1], createLink(link, id)) replaceContent(node, m[0], m[1], createLink(link, id))
} else {
orgRepoID := matchOrg + "/" + matchRepo + id
replaceContent(node, m[0], m[1], createLink(link, orgRepoID))
}
} }
func issueIndexPatternProcessor(ctx *postProcessCtx, node *html.Node) { func issueIndexPatternProcessor(ctx *postProcessCtx, node *html.Node) {
prefix := cutoutVerbosePrefix(ctx.urlPrefix) if ctx.metas == nil {
return
}
// default to numeric pattern, unless alphanumeric is requested. // default to numeric pattern, unless alphanumeric is requested.
pattern := issueNumericPattern pattern := issueNumericPattern
if ctx.metas["style"] == IssueNameStyleAlphanumeric { if ctx.metas["style"] == IssueNameStyleAlphanumeric {
@ -575,11 +592,10 @@ func issueIndexPatternProcessor(ctx *postProcessCtx, node *html.Node) {
if match == nil { if match == nil {
return return
} }
id := node.Data[match[2]:match[3]] id := node.Data[match[2]:match[3]]
var link *html.Node var link *html.Node
if ctx.metas == nil { if _, ok := ctx.metas["format"]; ok {
link = createLink(util.URLJoin(prefix, "issues", id[1:]), id)
} else {
// Support for external issue tracker // Support for external issue tracker
if ctx.metas["style"] == IssueNameStyleAlphanumeric { if ctx.metas["style"] == IssueNameStyleAlphanumeric {
ctx.metas["index"] = id ctx.metas["index"] = id
@ -587,6 +603,8 @@ func issueIndexPatternProcessor(ctx *postProcessCtx, node *html.Node) {
ctx.metas["index"] = id[1:] ctx.metas["index"] = id[1:]
} }
link = createLink(com.Expand(ctx.metas["format"], ctx.metas), id) link = createLink(com.Expand(ctx.metas["format"], ctx.metas), id)
} else {
link = createLink(util.URLJoin(setting.AppURL, ctx.metas["user"], ctx.metas["repo"], "issues", id[1:]), id)
} }
replaceContent(node, match[2], match[3], link) replaceContent(node, match[2], match[3], link)
} }

View file

@ -53,6 +53,12 @@ var alphanumericMetas = map[string]string{
"style": IssueNameStyleAlphanumeric, "style": IssueNameStyleAlphanumeric,
} }
// these values should match the Repo const above
var localMetas = map[string]string{
"user": "gogits",
"repo": "gogs",
}
func TestRender_IssueIndexPattern(t *testing.T) { func TestRender_IssueIndexPattern(t *testing.T) {
// numeric: render inputs without valid mentions // numeric: render inputs without valid mentions
test := func(s string) { test := func(s string) {
@ -91,7 +97,7 @@ func TestRender_IssueIndexPattern2(t *testing.T) {
links[i] = numericIssueLink(util.URLJoin(setting.AppSubURL, "issues"), index) links[i] = numericIssueLink(util.URLJoin(setting.AppSubURL, "issues"), index)
} }
expectedNil := fmt.Sprintf(expectedFmt, links...) expectedNil := fmt.Sprintf(expectedFmt, links...)
testRenderIssueIndexPattern(t, s, expectedNil, nil) testRenderIssueIndexPattern(t, s, expectedNil, &postProcessCtx{metas: localMetas})
for i, index := range indices { for i, index := range indices {
links[i] = numericIssueLink("https://someurl.com/someUser/someRepo/", index) links[i] = numericIssueLink("https://someurl.com/someUser/someRepo/", index)
@ -171,6 +177,7 @@ func testRenderIssueIndexPattern(t *testing.T, input, expected string, ctx *post
if ctx.urlPrefix == "" { if ctx.urlPrefix == "" {
ctx.urlPrefix = AppSubURL ctx.urlPrefix = AppSubURL
} }
res, err := ctx.postProcess([]byte(input)) res, err := ctx.postProcess([]byte(input))
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, expected, string(res)) assert.Equal(t, expected, string(res))
@ -181,10 +188,10 @@ func TestRender_AutoLink(t *testing.T) {
setting.AppSubURL = AppSubURL setting.AppSubURL = AppSubURL
test := func(input, expected string) { test := func(input, expected string) {
buffer, err := PostProcess([]byte(input), setting.AppSubURL, nil, false) buffer, err := PostProcess([]byte(input), setting.AppSubURL, localMetas, false)
assert.Equal(t, err, nil) assert.Equal(t, err, nil)
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer))) assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer)))
buffer, err = PostProcess([]byte(input), setting.AppSubURL, nil, true) buffer, err = PostProcess([]byte(input), setting.AppSubURL, localMetas, true)
assert.Equal(t, err, nil) assert.Equal(t, err, nil)
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer))) assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer)))
} }
@ -214,6 +221,7 @@ func TestRender_FullIssueURLs(t *testing.T) {
if ctx.urlPrefix == "" { if ctx.urlPrefix == "" {
ctx.urlPrefix = AppSubURL ctx.urlPrefix = AppSubURL
} }
ctx.metas = localMetas
result, err := ctx.postProcess([]byte(input)) result, err := ctx.postProcess([]byte(input))
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, expected, string(result)) assert.Equal(t, expected, string(result))
@ -221,9 +229,11 @@ func TestRender_FullIssueURLs(t *testing.T) {
test("Here is a link https://git.osgeo.org/gogs/postgis/postgis/pulls/6", test("Here is a link https://git.osgeo.org/gogs/postgis/postgis/pulls/6",
"Here is a link https://git.osgeo.org/gogs/postgis/postgis/pulls/6") "Here is a link https://git.osgeo.org/gogs/postgis/postgis/pulls/6")
test("Look here http://localhost:3000/person/repo/issues/4", test("Look here http://localhost:3000/person/repo/issues/4",
`Look here <a href="http://localhost:3000/person/repo/issues/4">#4</a>`) `Look here <a href="http://localhost:3000/person/repo/issues/4">person/repo#4</a>`)
test("http://localhost:3000/person/repo/issues/4#issuecomment-1234", test("http://localhost:3000/person/repo/issues/4#issuecomment-1234",
`<a href="http://localhost:3000/person/repo/issues/4#issuecomment-1234">#4</a>`) `<a href="http://localhost:3000/person/repo/issues/4#issuecomment-1234">person/repo#4</a>`)
test("http://localhost:3000/gogits/gogs/issues/4",
`<a href="http://localhost:3000/gogits/gogs/issues/4">#4</a>`)
} }
func TestRegExp_issueNumericPattern(t *testing.T) { func TestRegExp_issueNumericPattern(t *testing.T) {

View file

@ -19,6 +19,12 @@ const AppURL = "http://localhost:3000/"
const Repo = "gogits/gogs" const Repo = "gogits/gogs"
const AppSubURL = AppURL + Repo + "/" const AppSubURL = AppURL + Repo + "/"
// these values should match the Repo const above
var localMetas = map[string]string{
"user": "gogits",
"repo": "gogs",
}
func TestRender_StandardLinks(t *testing.T) { func TestRender_StandardLinks(t *testing.T) {
setting.AppURL = AppURL setting.AppURL = AppURL
setting.AppSubURL = AppSubURL setting.AppSubURL = AppSubURL
@ -100,7 +106,8 @@ func testAnswers(baseURLContent, baseURLImages string) []string {
<p>Ideas and codes</p> <p>Ideas and codes</p>
<ul> <ul>
<li>Bezier widget (by <a href="` + AppURL + `r-lyeh" rel="nofollow">@r-lyeh</a>) <a href="http://localhost:3000/ocornut/imgui/issues/786" rel="nofollow">#786</a></li> <li>Bezier widget (by <a href="` + AppURL + `r-lyeh" rel="nofollow">@r-lyeh</a>) <a href="http://localhost:3000/ocornut/imgui/issues/786" rel="nofollow">ocornut/imgui#786</a></li>
<li>Bezier widget (by <a href="` + AppURL + `r-lyeh" rel="nofollow">@r-lyeh</a>) <a href="http://localhost:3000/gogits/gogs/issues/786" rel="nofollow">#786</a></li>
<li>Node graph editors <a href="https://github.com/ocornut/imgui/issues/306" rel="nofollow">https://github.com/ocornut/imgui/issues/306</a></li> <li>Node graph editors <a href="https://github.com/ocornut/imgui/issues/306" rel="nofollow">https://github.com/ocornut/imgui/issues/306</a></li>
<li><a href="` + baseURLContent + `/memory_editor_example" rel="nofollow">Memory Editor</a></li> <li><a href="` + baseURLContent + `/memory_editor_example" rel="nofollow">Memory Editor</a></li>
<li><a href="` + baseURLContent + `/plot_var_example" rel="nofollow">Plot var helper</a></li> <li><a href="` + baseURLContent + `/plot_var_example" rel="nofollow">Plot var helper</a></li>
@ -188,6 +195,7 @@ var sameCases = []string{
Ideas and codes Ideas and codes
- Bezier widget (by @r-lyeh) ` + AppURL + `ocornut/imgui/issues/786 - Bezier widget (by @r-lyeh) ` + AppURL + `ocornut/imgui/issues/786
- Bezier widget (by @r-lyeh) ` + AppURL + `gogits/gogs/issues/786
- Node graph editors https://github.com/ocornut/imgui/issues/306 - Node graph editors https://github.com/ocornut/imgui/issues/306
- [[Memory Editor|memory_editor_example]] - [[Memory Editor|memory_editor_example]]
- [[Plot var helper|plot_var_example]]`, - [[Plot var helper|plot_var_example]]`,
@ -243,7 +251,7 @@ func TestTotal_RenderWiki(t *testing.T) {
answers := testAnswers(util.URLJoin(AppSubURL, "wiki/"), util.URLJoin(AppSubURL, "wiki", "raw/")) answers := testAnswers(util.URLJoin(AppSubURL, "wiki/"), util.URLJoin(AppSubURL, "wiki", "raw/"))
for i := 0; i < len(sameCases); i++ { for i := 0; i < len(sameCases); i++ {
line := RenderWiki([]byte(sameCases[i]), AppSubURL, nil) line := RenderWiki([]byte(sameCases[i]), AppSubURL, localMetas)
assert.Equal(t, answers[i], line) assert.Equal(t, answers[i], line)
} }
@ -270,7 +278,7 @@ func TestTotal_RenderString(t *testing.T) {
answers := testAnswers(util.URLJoin(AppSubURL, "src", "master/"), util.URLJoin(AppSubURL, "raw", "master/")) answers := testAnswers(util.URLJoin(AppSubURL, "src", "master/"), util.URLJoin(AppSubURL, "raw", "master/"))
for i := 0; i < len(sameCases); i++ { for i := 0; i < len(sameCases); i++ {
line := RenderString(sameCases[i], util.URLJoin(AppSubURL, "src", "master/"), nil) line := RenderString(sameCases[i], util.URLJoin(AppSubURL, "src", "master/"), localMetas)
assert.Equal(t, answers[i], line) assert.Equal(t, answers[i], line)
} }

View file

@ -584,6 +584,8 @@ func RegisterRoutes(m *macaron.Macaron) {
Patch(reqToken(), reqRepoWriter(models.UnitTypeIssues, models.UnitTypePullRequests), bind(api.EditLabelOption{}), repo.EditLabel). Patch(reqToken(), reqRepoWriter(models.UnitTypeIssues, models.UnitTypePullRequests), bind(api.EditLabelOption{}), repo.EditLabel).
Delete(reqToken(), reqRepoWriter(models.UnitTypeIssues, models.UnitTypePullRequests), repo.DeleteLabel) Delete(reqToken(), reqRepoWriter(models.UnitTypeIssues, models.UnitTypePullRequests), repo.DeleteLabel)
}) })
m.Post("/markdown", bind(api.MarkdownOption{}), misc.Markdown)
m.Post("/markdown/raw", misc.MarkdownRaw)
m.Group("/milestones", func() { m.Group("/milestones", func() {
m.Combo("").Get(repo.ListMilestones). m.Combo("").Get(repo.ListMilestones).
Post(reqToken(), reqRepoWriter(models.UnitTypeIssues, models.UnitTypePullRequests), bind(api.CreateMilestoneOption{}), repo.CreateMilestone) Post(reqToken(), reqRepoWriter(models.UnitTypeIssues, models.UnitTypePullRequests), bind(api.CreateMilestoneOption{}), repo.CreateMilestone)

View file

@ -5,12 +5,16 @@
package misc package misc
import ( import (
"strings"
api "code.gitea.io/sdk/gitea" api "code.gitea.io/sdk/gitea"
"code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/markup/markdown" "code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/util"
"mvdan.cc/xurls/v2"
) )
// Markdown render markdown document to HTML // Markdown render markdown document to HTML
@ -45,11 +49,23 @@ func Markdown(ctx *context.APIContext, form api.MarkdownOption) {
switch form.Mode { switch form.Mode {
case "gfm": case "gfm":
md := []byte(form.Text) md := []byte(form.Text)
context := util.URLJoin(setting.AppURL, form.Context) urlPrefix := form.Context
var 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 {
meta = ctx.Repo.Repository.ComposeMetas()
}
if form.Wiki { if form.Wiki {
ctx.Write([]byte(markdown.RenderWiki(md, context, nil))) ctx.Write([]byte(markdown.RenderWiki(md, urlPrefix, meta)))
} else { } else {
ctx.Write(markdown.Render(md, context, nil)) ctx.Write(markdown.Render(md, urlPrefix, meta))
} }
default: default:
ctx.Write(markdown.RenderRaw([]byte(form.Text), "", false)) ctx.Write(markdown.RenderRaw([]byte(form.Text), "", false))

View file

@ -202,7 +202,7 @@
<div class="ui comment form"> <div class="ui comment form">
<div class="ui top attached tabular menu"> <div class="ui top attached tabular menu">
<a class="active write item">{{$.i18n.Tr "write"}}</a> <a class="active write item">{{$.i18n.Tr "write"}}</a>
<a class="preview item" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{$.RepoLink}}">{{$.i18n.Tr "preview"}}</a> <a class="preview item" data-url="{{$.Repository.APIURL}}/markdown" data-context="{{$.RepoLink}}">{{$.i18n.Tr "preview"}}</a>
</div> </div>
<div class="ui bottom attached active write tab segment"> <div class="ui bottom attached active write tab segment">
<textarea tabindex="1" name="content"></textarea> <textarea tabindex="1" name="content"></textarea>

View file

@ -12,7 +12,7 @@
<input type="hidden" name="diff_base_cid"> <input type="hidden" name="diff_base_cid">
<div class="ui top attached tabular menu" {{if not $.hidden}}onload="assingMenuAttributes(this)" {{end}}data-write="write" data-preview="preview"> <div class="ui top attached tabular menu" {{if not $.hidden}}onload="assingMenuAttributes(this)" {{end}}data-write="write" data-preview="preview">
<a class="active item" data-tab="write">{{$.root.i18n.Tr "write"}}</a> <a class="active item" data-tab="write">{{$.root.i18n.Tr "write"}}</a>
<a class="item" data-tab="preview" data-url="{{$.root.AppSubUrl}}/api/v1/markdown" data-context="{{$.root.RepoLink}}">{{$.root.i18n.Tr "preview"}}</a> <a class="item" data-tab="preview" data-url="{{$.root.Repository.APIURL}}/markdown" data-context="{{$.root.RepoLink}}">{{$.root.i18n.Tr "preview"}}</a>
</div> </div>
<div class="ui bottom attached active tab segment" data-tab="write"> <div class="ui bottom attached active tab segment" data-tab="write">
<div class="field"> <div class="field">

View file

@ -30,13 +30,13 @@
<div class="ui top attached tabular menu" data-write="write" data-preview="preview" data-diff="diff"> <div class="ui top attached tabular menu" data-write="write" data-preview="preview" data-diff="diff">
<a class="active item" data-tab="write"><i class="octicon octicon-code"></i> {{if .IsNewFile}}{{.i18n.Tr "repo.editor.new_file"}}{{else}}{{.i18n.Tr "repo.editor.edit_file"}}{{end}}</a> <a class="active item" data-tab="write"><i class="octicon octicon-code"></i> {{if .IsNewFile}}{{.i18n.Tr "repo.editor.new_file"}}{{else}}{{.i18n.Tr "repo.editor.edit_file"}}{{end}}</a>
{{if not .IsNewFile}} {{if not .IsNewFile}}
<a class="item" data-tab="preview" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{.RepoLink}}/src/{{.BranchNameSubURL | EscapePound}}" data-preview-file-modes="{{.PreviewableFileModes}}"><i class="octicon octicon-eye"></i> {{.i18n.Tr "preview"}}</a> <a class="item" data-tab="preview" data-url="{{.Repository.APIURL}}/markdown" data-context="{{.RepoLink}}/src/{{.BranchNameSubURL | EscapePound}}" data-preview-file-modes="{{.PreviewableFileModes}}"><i class="octicon octicon-eye"></i> {{.i18n.Tr "preview"}}</a>
<a class="item" data-tab="diff" data-url="{{.RepoLink}}/_preview/{{.BranchName | EscapePound}}/{{.TreePath | EscapePound}}" data-context="{{.BranchLink}}"><i class="octicon octicon-diff"></i> {{.i18n.Tr "repo.editor.preview_changes"}}</a> <a class="item" data-tab="diff" data-url="{{.RepoLink}}/_preview/{{.BranchName | EscapePound}}/{{.TreePath | EscapePound}}" data-context="{{.BranchLink}}"><i class="octicon octicon-diff"></i> {{.i18n.Tr "repo.editor.preview_changes"}}</a>
{{end}} {{end}}
</div> </div>
<div class="ui bottom attached active tab segment" data-tab="write"> <div class="ui bottom attached active tab segment" data-tab="write">
<textarea id="edit_area" name="content" data-id="repo-{{.Repository.Name}}-{{.TreePath}}" <textarea id="edit_area" name="content" data-id="repo-{{.Repository.Name}}-{{.TreePath}}"
data-url="{{AppSubUrl}}/api/v1/markdown" data-url="{{.Repository.APIURL}}/markdown"
data-context="{{.RepoLink}}" data-context="{{.RepoLink}}"
data-markdown-file-exts="{{.MarkdownFileExts}}" data-markdown-file-exts="{{.MarkdownFileExts}}"
data-line-wrap-extensions="{{.LineWrapExtensions}}" data-line-wrap-extensions="{{.LineWrapExtensions}}"

View file

@ -1,10 +1,10 @@
<div class="field"> <div class="field">
<div class="ui top attached tabular menu" data-write="write" data-preview="preview"> <div class="ui top attached tabular menu" data-write="write" data-preview="preview">
<a class="active item" data-tab="write">{{.i18n.Tr "write"}}</a> <a class="active item" data-tab="write">{{.i18n.Tr "write"}}</a>
<a class="item" data-tab="preview" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{.RepoLink}}">{{.i18n.Tr "preview"}}</a> <a class="item" data-tab="preview" data-url="{{.Repository.APIURL}}/markdown" data-context="{{.RepoLink}}">{{.i18n.Tr "preview"}}</a>
</div> </div>
<div class="ui bottom attached active tab segment" data-tab="write"> <div class="ui bottom attached active tab segment" data-tab="write">
<textarea id="content" class="edit_area js-quick-submit" name="content" tabindex="4" data-id="issue-{{.RepoName}}" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{.Repo.RepoLink}}"> <textarea id="content" class="edit_area js-quick-submit" name="content" tabindex="4" data-id="issue-{{.RepoName}}" data-url="{{.Repository.APIURL}}/markdown" data-context="{{.Repo.RepoLink}}">
{{if .BodyQuery}}{{.BodyQuery}}{{else if .IssueTemplate}}{{.IssueTemplate}}{{else if .PullRequestTemplate}}{{.PullRequestTemplate}}{{else}}{{.content}}{{end}}</textarea> {{if .BodyQuery}}{{.BodyQuery}}{{else if .IssueTemplate}}{{.IssueTemplate}}{{else if .PullRequestTemplate}}{{.PullRequestTemplate}}{{else}}{{.content}}{{end}}</textarea>
</div> </div>
<div class="ui bottom attached tab segment markdown" data-tab="preview"> <div class="ui bottom attached tab segment markdown" data-tab="preview">

View file

@ -156,7 +156,7 @@
<div class="ui comment form"> <div class="ui comment form">
<div class="ui top attached tabular menu"> <div class="ui top attached tabular menu">
<a class="active write item">{{$.i18n.Tr "write"}}</a> <a class="active write item">{{$.i18n.Tr "write"}}</a>
<a class="preview item" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{$.RepoLink}}">{{$.i18n.Tr "preview"}}</a> <a class="preview item" data-url="{{$.Repository.APIURL}}/markdown" data-context="{{$.RepoLink}}">{{$.i18n.Tr "preview"}}</a>
</div> </div>
<div class="ui bottom attached active write tab segment"> <div class="ui bottom attached active write tab segment">
<textarea tabindex="1" name="content"></textarea> <textarea tabindex="1" name="content"></textarea>

View file

@ -17,7 +17,7 @@
<input name="title" value="{{.title}}" autofocus required> <input name="title" value="{{.title}}" autofocus required>
</div> </div>
<div class="field"> <div class="field">
<textarea class="js-quick-submit" id="edit_area" name="content" data-id="wiki-{{.title}}" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{.RepoLink}}/wiki" required>{{if .PageIsWikiEdit}}{{.content}}{{else}}{{.i18n.Tr "repo.wiki.welcome"}}{{end}}</textarea> <textarea class="js-quick-submit" id="edit_area" name="content" data-id="wiki-{{.title}}" data-url="{{.Repository.APIURL}}/markdown" data-context="{{.RepoLink}}/wiki" required>{{if .PageIsWikiEdit}}{{.content}}{{else}}{{.i18n.Tr "repo.wiki.welcome"}}{{end}}</textarea>
</div> </div>
<div class="field"> <div class="field">
<input name="message" placeholder="{{.i18n.Tr "repo.wiki.default_commit_message"}}"> <input name="message" placeholder="{{.i18n.Tr "repo.wiki.default_commit_message"}}">