From c2ff2a472435c9735b8fef78c3797e54b99c73ad Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Mon, 3 Apr 2023 11:12:47 +0800 Subject: [PATCH 01/16] Try to catch more broken translations (#23867) Result: #23866 Gitea should drop the ``` ` ``` as string quoter, it is not recognized by Crowdin and it causes problem for translators. --- build/backport-locales.go | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/build/backport-locales.go b/build/backport-locales.go index a717b37367dc4..054b623d698e8 100644 --- a/build/backport-locales.go +++ b/build/backport-locales.go @@ -62,6 +62,7 @@ func main() { // use old en-US as the base, and copy the new translations to the old locales enUsOld := inisOld["options/locale/locale_en-US.ini"] + brokenWarned := map[string]bool{} for path, iniOld := range inisOld { if iniOld == enUsOld { continue @@ -77,11 +78,14 @@ func main() { if secNew.HasKey(keyEnUs.Name()) { oldStr := secOld.Key(keyEnUs.Name()).String() newStr := secNew.Key(keyEnUs.Name()).String() - if oldStr != "" && strings.Count(oldStr, "%") != strings.Count(newStr, "%") { - fmt.Printf("WARNING: locale %s [%s]%s has different number of arguments, skipping\n", path, secEnUS.Name(), keyEnUs.Name()) - fmt.Printf("\told: %s\n", oldStr) - fmt.Printf("\tnew: %s\n", newStr) - fmt.Println("---- ") + broken := oldStr != "" && strings.Count(oldStr, "%") != strings.Count(newStr, "%") + broken = broken || strings.Contains(oldStr, "\n") || strings.Contains(oldStr, "\n") + if broken { + brokenWarned[secOld.Name()+"."+keyEnUs.Name()] = true + fmt.Println("----") + fmt.Printf("WARNING: skip broken locale: %s , [%s] %s\n", path, secEnUS.Name(), keyEnUs.Name()) + fmt.Printf("\told: %s\n", strings.ReplaceAll(oldStr, "\n", "\\n")) + fmt.Printf("\tnew: %s\n", strings.ReplaceAll(newStr, "\n", "\\n")) continue } secOld.Key(keyEnUs.Name()).SetValue(newStr) @@ -90,4 +94,25 @@ func main() { } mustNoErr(iniOld.SaveTo(path)) } + + fmt.Println("========") + + for path, iniNew := range inisNew { + for _, sec := range iniNew.Sections() { + for _, key := range sec.Keys() { + str := sec.Key(key.Name()).String() + broken := strings.Contains(str, "\n") + broken = broken || strings.HasPrefix(str, "`") != strings.HasSuffix(str, "`") + broken = broken || strings.HasPrefix(str, "\"`") + broken = broken || strings.HasPrefix(str, "`\"") + broken = broken || strings.Count(str, `"`)%2 == 1 + broken = broken || strings.Count(str, "`")%2 == 1 + if broken && !brokenWarned[sec.Name()+"."+key.Name()] { + fmt.Printf("WARNING: found broken locale: %s , [%s] %s\n", path, sec.Name(), key.Name()) + fmt.Printf("\tstr: %s\n", strings.ReplaceAll(str, "\n", "\\n")) + fmt.Println("----") + } + } + } + } } From 977ef215fab05c79bd3fcd9bf3679976a0210015 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Mon, 3 Apr 2023 12:05:37 +0800 Subject: [PATCH 02/16] Rename actions unit to `repo.actions` and add docs for it (#23733) I neglected that the `NameKey` of `Unit` is not only for translation, but also configuration. So it should be `repo.actions` to maintain consistency. ## :warning: BREAKING :warning: If users already use `actions.actions` in `DISABLED_REPO_UNITS` or `DEFAULT_REPO_UNITS`, it will be treated as an invalid unit key. --- custom/conf/app.example.ini | 4 ++-- docs/content/doc/administration/config-cheat-sheet.en-us.md | 4 ++-- models/unit/unit.go | 2 +- options/locale/locale_en-US.ini | 1 + 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index 2a840d5ef1fc7..0543c85d50daa 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -947,10 +947,10 @@ ROUTER = console ;USE_COMPAT_SSH_URI = false ;; ;; Close issues as long as a commit on any branch marks it as fixed -;; Comma separated list of globally disabled repo units. Allowed values: repo.issues, repo.ext_issues, repo.pulls, repo.wiki, repo.ext_wiki, repo.projects, repo.packages +;; Comma separated list of globally disabled repo units. Allowed values: repo.issues, repo.ext_issues, repo.pulls, repo.wiki, repo.ext_wiki, repo.projects, repo.packages, repo.actions. ;DISABLED_REPO_UNITS = ;; -;; Comma separated list of default new repo units. Allowed values: repo.code, repo.releases, repo.issues, repo.pulls, repo.wiki, repo.projects, repo.packages. +;; Comma separated list of default new repo units. Allowed values: repo.code, repo.releases, repo.issues, repo.pulls, repo.wiki, repo.projects, repo.packages, repo.actions. ;; Note: Code and Releases can currently not be deactivated. If you specify default repo units you should still list them for future compatibility. ;; External wiki and issue tracker can't be enabled by default as it requires additional settings. ;; Disabled repo units will not be added to new repositories regardless if it is in the default list. diff --git a/docs/content/doc/administration/config-cheat-sheet.en-us.md b/docs/content/doc/administration/config-cheat-sheet.en-us.md index f8082bd3784f2..67618d05b675e 100644 --- a/docs/content/doc/administration/config-cheat-sheet.en-us.md +++ b/docs/content/doc/administration/config-cheat-sheet.en-us.md @@ -103,8 +103,8 @@ In addition there is _`StaticRootPath`_ which can be set as a built-in at build - `DEFAULT_CLOSE_ISSUES_VIA_COMMITS_IN_ANY_BRANCH`: **false**: Close an issue if a commit on a non default branch marks it as closed. - `ENABLE_PUSH_CREATE_USER`: **false**: Allow users to push local repositories to Gitea and have them automatically created for a user. - `ENABLE_PUSH_CREATE_ORG`: **false**: Allow users to push local repositories to Gitea and have them automatically created for an org. -- `DISABLED_REPO_UNITS`: **_empty_**: Comma separated list of globally disabled repo units. Allowed values: \[repo.issues, repo.ext_issues, repo.pulls, repo.wiki, repo.ext_wiki, repo.projects\] -- `DEFAULT_REPO_UNITS`: **repo.code,repo.releases,repo.issues,repo.pulls,repo.wiki,repo.projects,repo.packages**: Comma separated list of default new repo units. Allowed values: \[repo.code, repo.releases, repo.issues, repo.pulls, repo.wiki, repo.projects\]. Note: Code and Releases can currently not be deactivated. If you specify default repo units you should still list them for future compatibility. External wiki and issue tracker can't be enabled by default as it requires additional settings. Disabled repo units will not be added to new repositories regardless if it is in the default list. +- `DISABLED_REPO_UNITS`: **_empty_**: Comma separated list of globally disabled repo units. Allowed values: \[repo.issues, repo.ext_issues, repo.pulls, repo.wiki, repo.ext_wiki, repo.projects, repo.packages, repo.actions\] +- `DEFAULT_REPO_UNITS`: **repo.code,repo.releases,repo.issues,repo.pulls,repo.wiki,repo.projects,repo.packages**: Comma separated list of default new repo units. Allowed values: \[repo.code, repo.releases, repo.issues, repo.pulls, repo.wiki, repo.projects, repo.packages, repo.actions\]. Note: Code and Releases can currently not be deactivated. If you specify default repo units you should still list them for future compatibility. External wiki and issue tracker can't be enabled by default as it requires additional settings. Disabled repo units will not be added to new repositories regardless if it is in the default list. - `DEFAULT_FORK_REPO_UNITS`: **repo.code,repo.pulls**: Comma separated list of default forked repo units. The set of allowed values and rules is the same as `DEFAULT_REPO_UNITS`. - `PREFIX_ARCHIVE_FILES`: **true**: Prefix archive files by placing them in a directory named after the repository. - `DISABLE_MIGRATIONS`: **false**: Disable migrating feature. diff --git a/models/unit/unit.go b/models/unit/unit.go index a2a9079dc25c7..883f443cbe653 100644 --- a/models/unit/unit.go +++ b/models/unit/unit.go @@ -312,7 +312,7 @@ var ( UnitActions = Unit{ TypeActions, - "actions.actions", + "repo.actions", "/actions", "actions.unit.desc", 7, diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 347f5e43120bd..b7180d7967119 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -1057,6 +1057,7 @@ issues = Issues pulls = Pull Requests project_board = Projects packages = Packages +actions = Actions labels = Labels org_labels_desc = Organization level labels that can be used with all repositories under this organization org_labels_desc_manage = manage From ca905b82df7f1d2a823d8df4448d485e5902876d Mon Sep 17 00:00:00 2001 From: Hester Gong Date: Mon, 3 Apr 2023 16:02:57 +0800 Subject: [PATCH 03/16] Append `(comment)` when a link points at a comment rather than the whole issue (#23734) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Close #23671 For the feature mentioned above, this PR append ' (comment)' to the rendered html if it is a hashcomment. After the PR, type in the following ``` pull request from other repo: http://localhost:3000/testOrg/testOrgRepo/pulls/2 pull request from this repo: http://localhost:3000/aaa/testA/pulls/2 issue comment from this repo: http://localhost:3000/aaa/testA/issues/1#issuecomment-18 http://localhost:3000/aaa/testA/pulls/2#issue-9 issue comment from other repo: http://localhost:3000/testOrg/testOrgRepo/pulls/2#issuecomment-24 http://localhost:3000/testOrg/testOrgRepo/pulls/2#issue ``` Gives: 截屏2023-03-27 13 53 06 Other than the above feature, this PR also includes two other changes: 1 Right now, the render of links from file changed tab in pull request might not be very proper, for example, if type in the following. (not sure if this is an issue or design, if not an issue, I will revert the changes). example on [try.gitea.io](https://try.gitea.io/HesterG/testrepo/pulls/1) ``` https://try.gitea.io/HesterG/testrepo/pulls/1/files#issuecomment-162725 https://try.gitea.io/HesterG/testrepo/pulls/1/files ``` it will render the following 截屏2023-03-24 15 41 37 In this PR, skip processing the link into a ref issue if it is a link from files changed tab in pull request After: type in following ``` hash comment on files changed tab: http://localhost:3000/testOrg/testOrgRepo/pulls/2/files#issuecomment-24 files changed link: http://localhost:3000/testOrg/testOrgRepo/pulls/2/files ``` Gives 截屏2023-03-27 22 09 02 2 Right now, after editing the comment area, there will not be tippys attached to `ref-issue`; and no tippy attached on preview as well. example: https://user-images.githubusercontent.com/17645053/227850540-5ae34e2d-b1d7-4d0d-9726-7701bf825d1f.mov In this PR, in frontend, make sure tippy is added after editing the comment, and to the comment on preview tab After: https://user-images.githubusercontent.com/17645053/227853777-06f56b4c-1148-467c-b6f7-f79418e67504.mov --- modules/context/context.go | 4 +- modules/markup/html.go | 44 ++++++++++++++++--- modules/markup/html_internal_test.go | 8 +++- modules/translation/translation.go | 4 ++ options/locale/locale_en-US.ini | 1 + .../js/features/comp/MarkupContentPreview.js | 3 ++ web_src/js/features/contextpopup.js | 5 ++- web_src/js/features/repo-legacy.js | 3 ++ 8 files changed, 61 insertions(+), 11 deletions(-) diff --git a/modules/context/context.go b/modules/context/context.go index 5876e23cc40a2..1eff1459a14af 100644 --- a/modules/context/context.go +++ b/modules/context/context.go @@ -628,7 +628,9 @@ func (ctx *Context) Value(key interface{}) interface{} { if key == git.RepositoryContextKey && ctx.Repo != nil { return ctx.Repo.GitRepo } - + if key == translation.ContextKey && ctx.Locale != nil { + return ctx.Locale + } return ctx.Req.Context().Value(key) } diff --git a/modules/markup/html.go b/modules/markup/html.go index 76fc54cf465eb..11888b8536353 100644 --- a/modules/markup/html.go +++ b/modules/markup/html.go @@ -22,6 +22,7 @@ import ( "code.gitea.io/gitea/modules/regexplru" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/templates/vars" + "code.gitea.io/gitea/modules/translation" "code.gitea.io/gitea/modules/util" "golang.org/x/net/html" @@ -97,14 +98,30 @@ var issueFullPattern *regexp.Regexp // Once for to prevent races var issueFullPatternOnce sync.Once +// regexp for full links to hash comment in pull request files changed tab +var filesChangedFullPattern *regexp.Regexp + +// Once for to prevent races +var filesChangedFullPatternOnce sync.Once + func getIssueFullPattern() *regexp.Regexp { issueFullPatternOnce.Do(func() { + // example: https://domain/org/repo/pulls/27#hash issueFullPattern = regexp.MustCompile(regexp.QuoteMeta(setting.AppURL) + `[\w_.-]+/[\w_.-]+/(?:issues|pulls)/((?:\w{1,10}-)?[1-9][0-9]*)([\?|#](\S+)?)?\b`) }) return issueFullPattern } +func getFilesChangedFullPattern() *regexp.Regexp { + filesChangedFullPatternOnce.Do(func() { + // example: https://domain/org/repo/pulls/27/files#hash + filesChangedFullPattern = regexp.MustCompile(regexp.QuoteMeta(setting.AppURL) + + `[\w_.-]+/[\w_.-]+/pulls/((?:\w{1,10}-)?[1-9][0-9]*)/files([\?|#](\S+)?)?\b`) + }) + return filesChangedFullPattern +} + // CustomLinkURLSchemes allows for additional schemes to be detected when parsing links within text func CustomLinkURLSchemes(schemes []string) { schemes = append(schemes, "http", "https") @@ -793,15 +810,30 @@ func fullIssuePatternProcessor(ctx *RenderContext, node *html.Node) { if ctx.Metas == nil { return } - next := node.NextSibling for node != nil && node != next { m := getIssueFullPattern().FindStringSubmatchIndex(node.Data) if m == nil { return } + + mDiffView := getFilesChangedFullPattern().FindStringSubmatchIndex(node.Data) + // leave it as it is if the link is from "Files Changed" tab in PR Diff View https://domain/org/repo/pulls/27/files + if mDiffView != nil { + return + } + link := node.Data[m[0]:m[1]] - id := "#" + node.Data[m[2]:m[3]] + text := "#" + node.Data[m[2]:m[3]] + // if m[4] and m[5] is not -1, then link is to a comment + // indicate that in the text by appending (comment) + if m[4] != -1 && m[5] != -1 { + if locale, ok := ctx.Ctx.Value(translation.ContextKey).(translation.Locale); ok { + text += " " + locale.Tr("repo.from_comment") + } else { + text += " (comment)" + } + } // extract repo and org name from matched link like // http://localhost:3000/gituser/myrepo/issues/1 @@ -810,12 +842,10 @@ func fullIssuePatternProcessor(ctx *RenderContext, node *html.Node) { 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, "ref-issue")) + replaceContent(node, m[0], m[1], createLink(link, text, "ref-issue")) } else { - orgRepoID := matchOrg + "/" + matchRepo + id - replaceContent(node, m[0], m[1], createLink(link, orgRepoID, "ref-issue")) + text = matchOrg + "/" + matchRepo + text + replaceContent(node, m[0], m[1], createLink(link, text, "ref-issue")) } node = node.NextSibling.NextSibling } diff --git a/modules/markup/html_internal_test.go b/modules/markup/html_internal_test.go index a048f1f527889..7e04b03531d87 100644 --- a/modules/markup/html_internal_test.go +++ b/modules/markup/html_internal_test.go @@ -330,13 +330,17 @@ func TestRender_FullIssueURLs(t *testing.T) { test("Look here http://localhost:3000/person/repo/issues/4", `Look here person/repo#4`) test("http://localhost:3000/person/repo/issues/4#issuecomment-1234", - `person/repo#4`) + `person/repo#4 (comment)`) test("http://localhost:3000/gogits/gogs/issues/4", `#4`) test("http://localhost:3000/gogits/gogs/issues/4 test", `#4 test`) test("http://localhost:3000/gogits/gogs/issues/4?a=1&b=2#comment-123 test", - `#4 test`) + `#4 (comment) test`) + test("http://localhost:3000/testOrg/testOrgRepo/pulls/2/files#issuecomment-24", + "http://localhost:3000/testOrg/testOrgRepo/pulls/2/files#issuecomment-24") + test("http://localhost:3000/testOrg/testOrgRepo/pulls/2/files", + "http://localhost:3000/testOrg/testOrgRepo/pulls/2/files") } func TestRegExp_sha1CurrentPattern(t *testing.T) { diff --git a/modules/translation/translation.go b/modules/translation/translation.go index 5a1009bfa3d80..3165390c3238c 100644 --- a/modules/translation/translation.go +++ b/modules/translation/translation.go @@ -18,6 +18,10 @@ import ( "golang.org/x/text/language" ) +type contextKey struct{} + +var ContextKey interface{} = &contextKey{} + // Locale represents an interface to translation type Locale interface { Language() string diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index b7180d7967119..5834703556c29 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -1104,6 +1104,7 @@ download_file = Download file normal_view = Normal View line = line lines = lines +from_comment = (comment) editor.add_file = Add File editor.new_file = New File diff --git a/web_src/js/features/comp/MarkupContentPreview.js b/web_src/js/features/comp/MarkupContentPreview.js index 61fd699b29714..a32bf301843c8 100644 --- a/web_src/js/features/comp/MarkupContentPreview.js +++ b/web_src/js/features/comp/MarkupContentPreview.js @@ -1,5 +1,6 @@ import $ from 'jquery'; import {initMarkupContent} from '../../markup/content.js'; +import {attachRefIssueContextPopup} from '../contextpopup.js'; const {csrfToken} = window.config; @@ -16,6 +17,8 @@ export function initCompMarkupContentPreviewTab($form) { }, (data) => { const $previewPanel = $form.find(`.tab[data-tab="${$tabMenu.data('preview')}"]`); $previewPanel.html(data); + const refIssues = $previewPanel.find('p .ref-issue'); + attachRefIssueContextPopup(refIssues); initMarkupContent(); }); }); diff --git a/web_src/js/features/contextpopup.js b/web_src/js/features/contextpopup.js index c685d93db04a3..7b37035547a13 100644 --- a/web_src/js/features/contextpopup.js +++ b/web_src/js/features/contextpopup.js @@ -6,8 +6,11 @@ import {createTippy} from '../modules/tippy.js'; export function initContextPopups() { const refIssues = $('.ref-issue'); - if (!refIssues.length) return; + attachRefIssueContextPopup(refIssues); +} +export function attachRefIssueContextPopup(refIssues) { + if (!refIssues.length) return; refIssues.each(function () { if ($(this).hasClass('ref-external-issue')) { return; diff --git a/web_src/js/features/repo-legacy.js b/web_src/js/features/repo-legacy.js index f7fc1aa4eb92d..3689c342721c7 100644 --- a/web_src/js/features/repo-legacy.js +++ b/web_src/js/features/repo-legacy.js @@ -26,6 +26,7 @@ import {initCompReactionSelector} from './comp/ReactionSelector.js'; import {initRepoSettingBranches} from './repo-settings.js'; import {initRepoPullRequestMergeForm} from './repo-issue-pr-form.js'; import {hideElem, showElem} from '../utils/dom.js'; +import {attachRefIssueContextPopup} from './contextpopup.js'; const {csrfToken} = window.config; @@ -439,6 +440,8 @@ async function onEditContent(event) { } else { $renderContent.html(data.content); $rawContent.text($textarea.val()); + const refIssues = $renderContent.find('p .ref-issue'); + attachRefIssueContextPopup(refIssues); } const $content = $segment; if (!$content.find('.dropzone-attachments').length) { From d67e40684f43b0eb744cad26e0265002f033dbc3 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Mon, 3 Apr 2023 16:42:38 +0800 Subject: [PATCH 04/16] Improve LoadUnitConfig to handle invalid or duplicate units (#23736) The old code just parses an invalid key to `TypeInvalid` and uses it as normal, and duplicate keys will be kept. So this PR will ignore invalid key and log warning and also deduplicate valid units. --- models/unit/unit.go | 39 ++++++++++++++++------------ models/unit/unit_test.go | 53 ++++++++++++++++++++++++++++++++++++++ routers/api/v1/org/team.go | 2 +- 3 files changed, 77 insertions(+), 17 deletions(-) create mode 100644 models/unit/unit_test.go diff --git a/models/unit/unit.go b/models/unit/unit.go index 883f443cbe653..3d5a8842cd638 100644 --- a/models/unit/unit.go +++ b/models/unit/unit.go @@ -151,7 +151,11 @@ func validateDefaultRepoUnits(defaultUnits, settingDefaultUnits []Type) []Type { // LoadUnitConfig load units from settings func LoadUnitConfig() { - DisabledRepoUnits = FindUnitTypes(setting.Repository.DisabledRepoUnits...) + var invalidKeys []string + DisabledRepoUnits, invalidKeys = FindUnitTypes(setting.Repository.DisabledRepoUnits...) + if len(invalidKeys) > 0 { + log.Warn("Invalid keys in disabled repo units: %s", strings.Join(invalidKeys, ", ")) + } // Check that must units are not disabled for i, disabledU := range DisabledRepoUnits { if !disabledU.CanDisable() { @@ -160,9 +164,15 @@ func LoadUnitConfig() { } } - setDefaultRepoUnits := FindUnitTypes(setting.Repository.DefaultRepoUnits...) + setDefaultRepoUnits, invalidKeys := FindUnitTypes(setting.Repository.DefaultRepoUnits...) + if len(invalidKeys) > 0 { + log.Warn("Invalid keys in default repo units: %s", strings.Join(invalidKeys, ", ")) + } DefaultRepoUnits = validateDefaultRepoUnits(DefaultRepoUnits, setDefaultRepoUnits) - setDefaultForkRepoUnits := FindUnitTypes(setting.Repository.DefaultForkRepoUnits...) + setDefaultForkRepoUnits, invalidKeys := FindUnitTypes(setting.Repository.DefaultForkRepoUnits...) + if len(invalidKeys) > 0 { + log.Warn("Invalid keys in default fork repo units: %s", strings.Join(invalidKeys, ", ")) + } DefaultForkRepoUnits = validateDefaultRepoUnits(DefaultForkRepoUnits, setDefaultForkRepoUnits) } @@ -334,22 +344,19 @@ var ( } ) -// FindUnitTypes give the unit key names and return unit -func FindUnitTypes(nameKeys ...string) (res []Type) { +// FindUnitTypes give the unit key names and return valid unique units and invalid keys +func FindUnitTypes(nameKeys ...string) (res []Type, invalidKeys []string) { + m := map[Type]struct{}{} for _, key := range nameKeys { - var found bool - for t, u := range Units { - if strings.EqualFold(key, u.NameKey) { - res = append(res, t) - found = true - break - } - } - if !found { - res = append(res, TypeInvalid) + t := TypeFromKey(key) + if t == TypeInvalid { + invalidKeys = append(invalidKeys, key) + } else if _, ok := m[t]; !ok { + res = append(res, t) + m[t] = struct{}{} } } - return res + return res, invalidKeys } // TypeFromKey give the unit key name and return unit diff --git a/models/unit/unit_test.go b/models/unit/unit_test.go new file mode 100644 index 0000000000000..50d781719771d --- /dev/null +++ b/models/unit/unit_test.go @@ -0,0 +1,53 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package unit + +import ( + "testing" + + "code.gitea.io/gitea/modules/setting" + + "github.com/stretchr/testify/assert" +) + +func TestLoadUnitConfig(t *testing.T) { + defer func(disabledRepoUnits, defaultRepoUnits, defaultForkRepoUnits []Type) { + DisabledRepoUnits = disabledRepoUnits + DefaultRepoUnits = defaultRepoUnits + DefaultForkRepoUnits = defaultForkRepoUnits + }(DisabledRepoUnits, DefaultRepoUnits, DefaultForkRepoUnits) + defer func(disabledRepoUnits, defaultRepoUnits, defaultForkRepoUnits []string) { + setting.Repository.DisabledRepoUnits = disabledRepoUnits + setting.Repository.DefaultRepoUnits = defaultRepoUnits + setting.Repository.DefaultForkRepoUnits = defaultForkRepoUnits + }(setting.Repository.DisabledRepoUnits, setting.Repository.DefaultRepoUnits, setting.Repository.DefaultForkRepoUnits) + + t.Run("regular", func(t *testing.T) { + setting.Repository.DisabledRepoUnits = []string{"repo.issues"} + setting.Repository.DefaultRepoUnits = []string{"repo.code", "repo.releases", "repo.issues", "repo.pulls"} + setting.Repository.DefaultForkRepoUnits = []string{"repo.releases"} + LoadUnitConfig() + assert.Equal(t, []Type{TypeIssues}, DisabledRepoUnits) + assert.Equal(t, []Type{TypeCode, TypeReleases, TypePullRequests}, DefaultRepoUnits) + assert.Equal(t, []Type{TypeCode, TypeReleases}, DefaultForkRepoUnits) + }) + t.Run("invalid", func(t *testing.T) { + setting.Repository.DisabledRepoUnits = []string{"repo.issues", "invalid.1"} + setting.Repository.DefaultRepoUnits = []string{"repo.code", "invalid.2", "repo.releases", "repo.issues", "repo.pulls"} + setting.Repository.DefaultForkRepoUnits = []string{"invalid.3", "repo.releases"} + LoadUnitConfig() + assert.Equal(t, []Type{TypeIssues}, DisabledRepoUnits) + assert.Equal(t, []Type{TypeCode, TypeReleases, TypePullRequests}, DefaultRepoUnits) + assert.Equal(t, []Type{TypeCode, TypeReleases}, DefaultForkRepoUnits) + }) + t.Run("duplicate", func(t *testing.T) { + setting.Repository.DisabledRepoUnits = []string{"repo.issues", "repo.issues"} + setting.Repository.DefaultRepoUnits = []string{"repo.code", "repo.releases", "repo.issues", "repo.pulls", "repo.code"} + setting.Repository.DefaultForkRepoUnits = []string{"repo.releases", "repo.releases"} + LoadUnitConfig() + assert.Equal(t, []Type{TypeIssues}, DisabledRepoUnits) + assert.Equal(t, []Type{TypeCode, TypeReleases, TypePullRequests}, DefaultRepoUnits) + assert.Equal(t, []Type{TypeCode, TypeReleases}, DefaultForkRepoUnits) + }) +} diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go index 0c6926759a768..597f846206043 100644 --- a/routers/api/v1/org/team.go +++ b/routers/api/v1/org/team.go @@ -135,7 +135,7 @@ func GetTeam(ctx *context.APIContext) { } func attachTeamUnits(team *organization.Team, units []string) { - unitTypes := unit_model.FindUnitTypes(units...) + unitTypes, _ := unit_model.FindUnitTypes(units...) team.Units = make([]*organization.TeamUnit, 0, len(units)) for _, tp := range unitTypes { team.Units = append(team.Units, &organization.TeamUnit{ From 5cc0801de90d16b4d528e62de11c9b525be5d122 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Mon, 3 Apr 2023 18:06:57 +0800 Subject: [PATCH 05/16] Introduce GitHub markdown editor, keep EasyMDE as fallback (#23876) The first step of the plan * #23290 Thanks to @silverwind for the first try in #15394 . Close #10729 and a lot of related issues. The EasyMDE is not removed, now it works as a fallback, users can switch between these two editors. Editor list: * Issue / PR comment * Issue / PR comment edit * Issue / PR comment quote reply * PR diff view, inline comment * PR diff view, inline comment edit * PR diff view, inline comment quote reply * Release editor * Wiki editor Some editors have attached dropzone Screenshots:
![image](https://user-images.githubusercontent.com/2114189/229363558-7e44dcd4-fb6d-48a0-92f8-bd12f57bb0a0.png) ![image](https://user-images.githubusercontent.com/2114189/229363566-781489c8-5306-4347-9714-d71af5d5b0b1.png) ![image](https://user-images.githubusercontent.com/2114189/229363771-1717bf5c-0f2a-4fc2-ba84-4f5b2a343a11.png) ![image](https://user-images.githubusercontent.com/2114189/229363793-ad362d0f-a045-47bd-8f9d-05a9a842bb39.png)
--------- Co-authored-by: silverwind --- package-lock.json | 6 + package.json | 1 + routers/web/devtest/devtest.go | 35 ++ routers/web/misc/markup.go | 18 - routers/web/org/setting.go | 1 - routers/web/repo/commit.go | 1 - routers/web/repo/compare.go | 1 - routers/web/repo/editor.go | 2 - routers/web/repo/issue.go | 2 - routers/web/repo/issue_label.go | 1 - routers/web/repo/pull.go | 2 - routers/web/repo/release.go | 4 - routers/web/web.go | 7 + templates/base/head_script.tmpl | 24 +- templates/devtest/gitea-ui.tmpl | 12 + templates/devtest/list.tmpl | 5 + templates/repo/diff/box.tmpl | 21 +- templates/repo/diff/comment_form.tmpl | 22 +- templates/repo/diff/new_review.tmpl | 9 +- templates/repo/issue/comment_tab.tmpl | 28 +- templates/repo/issue/fields/textarea.tmpl | 2 +- .../repo/issue/labels/edit_delete_label.tmpl | 2 +- templates/repo/issue/labels/label_new.tmpl | 2 +- templates/repo/issue/view_content.tmpl | 25 +- templates/repo/release/new.tmpl | 21 +- templates/repo/wiki/new.tmpl | 21 +- templates/shared/combomarkdowneditor.tmpl | 47 +++ web_src/css/editor-markdown.css | 25 ++ web_src/css/editor.css | 1 - web_src/css/index.css | 1 + web_src/css/repository.css | 4 - web_src/css/review.css | 5 + .../js/features/comp/ComboMarkdownEditor.js | 277 +++++++++++++++ web_src/js/features/comp/EasyMDE.js | 181 ---------- web_src/js/features/comp/ImagePaste.js | 47 +-- .../js/features/comp/MarkupContentPreview.js | 25 -- web_src/js/features/contextpopup.js | 13 +- web_src/js/features/repo-diff.js | 2 +- web_src/js/features/repo-issue.js | 74 +--- web_src/js/features/repo-legacy.js | 331 ++++++++---------- web_src/js/features/repo-release.js | 17 +- web_src/js/features/repo-wiki.js | 220 +++--------- web_src/js/features/tribute.js | 33 +- web_src/js/index.js | 3 - web_src/js/utils.js | 5 - web_src/js/utils.test.js | 6 +- 46 files changed, 761 insertions(+), 831 deletions(-) create mode 100644 routers/web/devtest/devtest.go create mode 100644 templates/devtest/gitea-ui.tmpl create mode 100644 templates/devtest/list.tmpl create mode 100644 templates/shared/combomarkdowneditor.tmpl create mode 100644 web_src/css/editor-markdown.css create mode 100644 web_src/js/features/comp/ComboMarkdownEditor.js delete mode 100644 web_src/js/features/comp/EasyMDE.js delete mode 100644 web_src/js/features/comp/MarkupContentPreview.js diff --git a/package-lock.json b/package-lock.json index 9d0c83f65641b..b9d998a69d2a8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@citation-js/plugin-csl": "0.6.7", "@citation-js/plugin-software-formats": "0.6.1", "@claviska/jquery-minicolors": "2.3.6", + "@github/markdown-toolbar-element": "2.1.1", "@mcaptcha/vanilla-glue": "0.1.0-alpha-3", "@primer/octicons": "18.3.0", "@vue/compiler-sfc": "3.2.47", @@ -838,6 +839,11 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@github/markdown-toolbar-element": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@github/markdown-toolbar-element/-/markdown-toolbar-element-2.1.1.tgz", + "integrity": "sha512-J++rpd5H9baztabJQB82h26jtueOeBRSTqetk9Cri+Lj/s28ndu6Tovn0uHQaOKtBWDobFunk9b5pP5vcqt7cA==" + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.8", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", diff --git a/package.json b/package.json index 8ac5c312f6b11..3ccf0c0840baa 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "@citation-js/plugin-csl": "0.6.7", "@citation-js/plugin-software-formats": "0.6.1", "@claviska/jquery-minicolors": "2.3.6", + "@github/markdown-toolbar-element": "2.1.1", "@mcaptcha/vanilla-glue": "0.1.0-alpha-3", "@primer/octicons": "18.3.0", "@vue/compiler-sfc": "3.2.47", diff --git a/routers/web/devtest/devtest.go b/routers/web/devtest/devtest.go new file mode 100644 index 0000000000000..eb77d0b927b6b --- /dev/null +++ b/routers/web/devtest/devtest.go @@ -0,0 +1,35 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package devtest + +import ( + "net/http" + "path" + "strings" + + "code.gitea.io/gitea/modules/base" + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/templates" +) + +// List all devtest templates, they will be used for e2e tests for the UI components +func List(ctx *context.Context) { + templateNames := templates.GetTemplateAssetNames() + var subNames []string + const prefix = "templates/devtest/" + for _, tmplName := range templateNames { + if strings.HasPrefix(tmplName, prefix) { + subName := strings.TrimSuffix(strings.TrimPrefix(tmplName, prefix), ".tmpl") + if subName != "list" { + subNames = append(subNames, subName) + } + } + } + ctx.Data["SubNames"] = subNames + ctx.HTML(http.StatusOK, "devtest/list") +} + +func Tmpl(ctx *context.Context) { + ctx.HTML(http.StatusOK, base.TplName("devtest"+path.Clean("/"+ctx.Params("sub")))) +} diff --git a/routers/web/misc/markup.go b/routers/web/misc/markup.go index f678316f4429f..169037894530c 100644 --- a/routers/web/misc/markup.go +++ b/routers/web/misc/markup.go @@ -15,24 +15,6 @@ import ( // 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() { diff --git a/routers/web/org/setting.go b/routers/web/org/setting.go index 654e9000fa1b5..7d84c101d8a60 100644 --- a/routers/web/org/setting.go +++ b/routers/web/org/setting.go @@ -246,7 +246,6 @@ func Labels(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.labels") ctx.Data["PageIsOrgSettings"] = true ctx.Data["PageIsOrgSettingsLabels"] = true - ctx.Data["RequireTribute"] = true ctx.Data["LabelTemplates"] = repo_module.LabelTemplates ctx.HTML(http.StatusOK, tplSettingsLabels) } diff --git a/routers/web/repo/commit.go b/routers/web/repo/commit.go index 843b1d8dfd01d..7439c2411b908 100644 --- a/routers/web/repo/commit.go +++ b/routers/web/repo/commit.go @@ -253,7 +253,6 @@ func FileHistory(ctx *context.Context) { // Diff show different from current commit to previous commit func Diff(ctx *context.Context) { ctx.Data["PageIsDiff"] = true - ctx.Data["RequireTribute"] = true userName := ctx.Repo.Owner.Name repoName := ctx.Repo.Repository.Name diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go index d7e7bac7b7815..c49eb762d8a66 100644 --- a/routers/web/repo/compare.go +++ b/routers/web/repo/compare.go @@ -781,7 +781,6 @@ func CompareDiff(ctx *context.Context) { ctx.Data["IsRepoToolbarCommits"] = true ctx.Data["IsDiffCompare"] = true - ctx.Data["RequireTribute"] = true templateErrs := setTemplateIfExists(ctx, pullRequestTemplateKey, pullRequestTemplateCandidates) if len(templateErrs) > 0 { diff --git a/routers/web/repo/editor.go b/routers/web/repo/editor.go index 2b66be22aeb96..f65e1ad3d81b1 100644 --- a/routers/web/repo/editor.go +++ b/routers/web/repo/editor.go @@ -538,7 +538,6 @@ func DeleteFilePost(ctx *context.Context) { // UploadFile render upload file page func UploadFile(ctx *context.Context) { ctx.Data["PageIsUpload"] = true - ctx.Data["RequireTribute"] = true upload.AddUploadContext(ctx, "repo") canCommit := renderCommitRights(ctx) treePath := cleanUploadFileName(ctx.Repo.TreePath) @@ -573,7 +572,6 @@ func UploadFile(ctx *context.Context) { func UploadFilePost(ctx *context.Context) { form := web.GetForm(ctx).(*forms.UploadRepoFileForm) ctx.Data["PageIsUpload"] = true - ctx.Data["RequireTribute"] = true upload.AddUploadContext(ctx, "repo") canCommit := renderCommitRights(ctx) diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index 612222598f2fa..e4f1172dd966c 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -849,7 +849,6 @@ func NewIssue(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.issues.new") ctx.Data["PageIsIssueList"] = true ctx.Data["NewIssueChooseTemplate"] = ctx.HasIssueTemplatesOrContactLinks() - ctx.Data["RequireTribute"] = true ctx.Data["PullRequestWorkInProgressPrefixes"] = setting.Repository.PullRequest.WorkInProgressPrefixes title := ctx.FormString("title") ctx.Data["TitleQuery"] = title @@ -1295,7 +1294,6 @@ func ViewIssue(ctx *context.Context) { ctx.Data["IssueType"] = "all" } - ctx.Data["RequireTribute"] = true ctx.Data["IsProjectsEnabled"] = ctx.Repo.CanRead(unit.TypeProjects) ctx.Data["IsAttachmentEnabled"] = setting.Attachment.Enabled upload.AddUploadContext(ctx, "comment") diff --git a/routers/web/repo/issue_label.go b/routers/web/repo/issue_label.go index 31bf85fedb29a..3123359a65e6f 100644 --- a/routers/web/repo/issue_label.go +++ b/routers/web/repo/issue_label.go @@ -28,7 +28,6 @@ func Labels(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.labels") ctx.Data["PageIsIssueList"] = true ctx.Data["PageIsLabels"] = true - ctx.Data["RequireTribute"] = true ctx.Data["LabelTemplates"] = repo_module.LabelTemplates ctx.HTML(http.StatusOK, tplLabels) } diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index 4f99687738247..c37d52640f491 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -791,7 +791,6 @@ func ViewPullFiles(ctx *context.Context) { setCompareContext(ctx, baseCommit, commit, ctx.Repo.Owner.Name, ctx.Repo.Repository.Name) - ctx.Data["RequireTribute"] = true if ctx.Data["Assignees"], err = repo_model.GetRepoAssignees(ctx, ctx.Repo.Repository); err != nil { ctx.ServerError("GetAssignees", err) return @@ -1160,7 +1159,6 @@ func CompareAndPullRequestPost(ctx *context.Context) { ctx.Data["PageIsComparePull"] = true ctx.Data["IsDiffCompare"] = true ctx.Data["IsRepoToolbarCommits"] = true - ctx.Data["RequireTribute"] = true ctx.Data["PullRequestWorkInProgressPrefixes"] = setting.Repository.PullRequest.WorkInProgressPrefixes ctx.Data["IsAttachmentEnabled"] = setting.Attachment.Enabled upload.AddUploadContext(ctx, "comment") diff --git a/routers/web/repo/release.go b/routers/web/repo/release.go index 3ffadd34ace7b..b8c5f67f45a7e 100644 --- a/routers/web/repo/release.go +++ b/routers/web/repo/release.go @@ -308,7 +308,6 @@ func LatestRelease(ctx *context.Context) { func NewRelease(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.release.new_release") ctx.Data["PageIsReleaseList"] = true - ctx.Data["RequireTribute"] = true ctx.Data["tag_target"] = ctx.Repo.Repository.DefaultBranch if tagName := ctx.FormString("tag"); len(tagName) > 0 { rel, err := repo_model.GetRelease(ctx.Repo.Repository.ID, tagName) @@ -351,7 +350,6 @@ func NewReleasePost(ctx *context.Context) { form := web.GetForm(ctx).(*forms.NewReleaseForm) ctx.Data["Title"] = ctx.Tr("repo.release.new_release") ctx.Data["PageIsReleaseList"] = true - ctx.Data["RequireTribute"] = true if ctx.HasError() { ctx.HTML(http.StatusOK, tplReleaseNew) @@ -469,7 +467,6 @@ func EditRelease(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.release.edit_release") ctx.Data["PageIsReleaseList"] = true ctx.Data["PageIsEditRelease"] = true - ctx.Data["RequireTribute"] = true ctx.Data["IsAttachmentEnabled"] = setting.Attachment.Enabled upload.AddUploadContext(ctx, "release") @@ -514,7 +511,6 @@ func EditReleasePost(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.release.edit_release") ctx.Data["PageIsReleaseList"] = true ctx.Data["PageIsEditRelease"] = true - ctx.Data["RequireTribute"] = true tagName := ctx.Params("*") rel, err := repo_model.GetRelease(ctx.Repo.Repository.ID, tagName) diff --git a/routers/web/web.go b/routers/web/web.go index 4bd2f76c571f1..6b62ff6f83722 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -27,6 +27,7 @@ import ( "code.gitea.io/gitea/modules/web/routing" "code.gitea.io/gitea/routers/web/admin" "code.gitea.io/gitea/routers/web/auth" + "code.gitea.io/gitea/routers/web/devtest" "code.gitea.io/gitea/routers/web/events" "code.gitea.io/gitea/routers/web/explore" "code.gitea.io/gitea/routers/web/feed" @@ -1491,6 +1492,12 @@ func RegisterRoutes(m *web.Route) { if setting.API.EnableSwagger { m.Get("/swagger.v1.json", SwaggerV1Json) } + + if !setting.IsProd { + m.Any("/devtest", devtest.List) + m.Any("/devtest/{sub}", devtest.Tmpl) + } + m.NotFound(func(w http.ResponseWriter, req *http.Request) { ctx := context.GetContext(req) ctx.NotFound("", nil) diff --git a/templates/base/head_script.tmpl b/templates/base/head_script.tmpl index 62fb10d89fa96..670d146b56a04 100644 --- a/templates/base/head_script.tmpl +++ b/templates/base/head_script.tmpl @@ -15,23 +15,19 @@ If you introduce mistakes in it, Gitea JavaScript code wouldn't run correctly. useServiceWorker: {{UseServiceWorker}}, csrfToken: '{{.CsrfToken}}', pageData: {{.PageData}}, - requireTribute: {{.RequireTribute}}, notificationSettings: {{NotificationSettings}}, {{/*a map provided by NewFuncMap in helper.go*/}} enableTimeTracking: {{EnableTimetracking}}, - {{if .RequireTribute}} + {{if or .Participants .Assignees .MentionableTeams}} tributeValues: Array.from(new Map([ - {{range .Participants}} - ['{{.Name}}', {key: '{{.Name}} {{.FullName}}', value: '{{.Name}}', - name: '{{.Name}}', fullname: '{{.FullName}}', avatar: '{{.AvatarLink $.Context}}'}], - {{end}} - {{range .Assignees}} - ['{{.Name}}', {key: '{{.Name}} {{.FullName}}', value: '{{.Name}}', - name: '{{.Name}}', fullname: '{{.FullName}}', avatar: '{{.AvatarLink $.Context}}'}], - {{end}} - {{range .MentionableTeams}} - ['{{$.MentionableTeamsOrg}}/{{.Name}}', {key: '{{$.MentionableTeamsOrg}}/{{.Name}}', value: '{{$.MentionableTeamsOrg}}/{{.Name}}', - name: '{{$.MentionableTeamsOrg}}/{{.Name}}', avatar: '{{$.MentionableTeamsOrgAvatar}}'}], - {{end}} + {{- range .Participants -}} + ['{{.Name}}', {key: '{{.Name}} {{.FullName}}', value: '{{.Name}}', name: '{{.Name}}', fullname: '{{.FullName}}', avatar: '{{.AvatarLink $.Context}}'}], + {{- end -}} + {{- range .Assignees -}} + ['{{.Name}}', {key: '{{.Name}} {{.FullName}}', value: '{{.Name}}', name: '{{.Name}}', fullname: '{{.FullName}}', avatar: '{{.AvatarLink $.Context}}'}], + {{- end -}} + {{- range .MentionableTeams -}} + ['{{$.MentionableTeamsOrg}}/{{.Name}}', {key: '{{$.MentionableTeamsOrg}}/{{.Name}}', value: '{{$.MentionableTeamsOrg}}/{{.Name}}', name: '{{$.MentionableTeamsOrg}}/{{.Name}}', avatar: '{{$.MentionableTeamsOrgAvatar}}'}], + {{- end -}} ]).values()), {{end}} mermaidMaxSourceCharacters: {{MermaidMaxSourceCharacters}}, diff --git a/templates/devtest/gitea-ui.tmpl b/templates/devtest/gitea-ui.tmpl new file mode 100644 index 0000000000000..c5ab863d00d04 --- /dev/null +++ b/templates/devtest/gitea-ui.tmpl @@ -0,0 +1,12 @@ +{{template "base/head" .}} +
+
+ + +
+
+ text with tooltip +
+ {{template "shared/combomarkdowneditor" .}} +
+{{template "base/footer" .}} diff --git a/templates/devtest/list.tmpl b/templates/devtest/list.tmpl new file mode 100644 index 0000000000000..3a519c328ee93 --- /dev/null +++ b/templates/devtest/list.tmpl @@ -0,0 +1,5 @@ +
    + {{range .SubNames}} +
  • {{.}}
  • + {{end}} +
diff --git a/templates/repo/diff/box.tmpl b/templates/repo/diff/box.tmpl index 36e669276eff9..21ea63cc0a466 100644 --- a/templates/repo/diff/box.tmpl +++ b/templates/repo/diff/box.tmpl @@ -198,24 +198,21 @@ {{if not $.Repository.IsArchived}} -
+ {{end}} {{template "repo/issue/view_content/reference_issue_dialog" .}} diff --git a/templates/repo/diff/comment_form.tmpl b/templates/repo/diff/comment_form.tmpl index 394a392bb9b88..109f1679672d3 100644 --- a/templates/repo/diff/comment_form.tmpl +++ b/templates/repo/diff/comment_form.tmpl @@ -9,18 +9,16 @@ - -
-
- -
-
- {{.locale.Tr "loading"}} -
-
+ + {{template "shared/combomarkdowneditor" (dict + "locale" $.root.locale + "MarkdownPreviewUrl" (print $.root.Repository.Link "/markup") + "MarkdownPreviewContext" $.root.RepoLink + "TextareaName" "content" + "TextareaPlaceholder" ($.locale.Tr "repo.diff.comment.placeholder") + "DropzoneParentContainer" "form" + )}} +