mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-11-29 03:38:52 +03:00
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:
parent
3186ef554c
commit
3ff0a126e1
13 changed files with 94 additions and 37 deletions
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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}}"
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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"}}">
|
||||||
|
|
Loading…
Reference in a new issue