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 logicrelease/v1.15
parent
3186ef554c
commit
3ff0a126e1
|
@ -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]]
|
||||||
// TODO if m[4]:m[5] is not nil, then link is to a comment,
|
|
||||||
// and we should indicate that in the text somehow
|
// extract repo and org name from matched link like
|
||||||
replaceContent(node, m[0], m[1], createLink(link, id))
|
// 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,
|
||||||
|
// and we should indicate that in the text somehow
|
||||||
|
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 New Issue