1
1
mirror of https://github.com/go-gitea/gitea synced 2025-07-22 18:28:37 +00:00

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:

<details>


![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)

</details>

---------

Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
wxiaoguang
2023-04-03 18:06:57 +08:00
committed by GitHub
parent d67e40684f
commit 5cc0801de9
46 changed files with 763 additions and 833 deletions

View File

@@ -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}},

View File

@@ -0,0 +1,12 @@
{{template "base/head" .}}
<div class="page-content devtest">
<div>
<gitea-origin-url data-url="test/url"></gitea-origin-url>
<gitea-origin-url data-url="/test/url"></gitea-origin-url>
</div>
<div>
<span data-tooltip-content="test tooltip">text with tooltip</span>
</div>
{{template "shared/combomarkdowneditor" .}}
</div>
{{template "base/footer" .}}

View File

@@ -0,0 +1,5 @@
<ul>
{{range .SubNames}}
<li><a href="{{AppSubUrl}}/devtest/{{.}}">{{.}}</a></li>
{{end}}
</ul>

View File

@@ -198,24 +198,21 @@
</div>
{{if not $.Repository.IsArchived}}
<div class="gt-hidden" id="edit-content-form">
<template id="issue-comment-editor-template">
<div class="ui comment form">
<div class="ui top attached tabular menu">
<a class="active write item">{{$.locale.Tr "write"}}</a>
<a class="preview item" data-url="{{$.Repository.Link}}/markup" data-context="{{$.RepoLink}}">{{$.locale.Tr "preview"}}</a>
</div>
<div class="ui bottom attached active write tab segment">
<textarea class="review-textarea js-quick-submit" tabindex="1" name="content"></textarea>
</div>
<div class="ui bottom attached tab preview segment markup">
{{$.locale.Tr "loading"}}
</div>
{{template "shared/combomarkdowneditor" (dict
"locale" $.locale
"MarkdownPreviewUrl" (print $.Repository.Link "/markup")
"MarkdownPreviewContext" $.RepoLink
"TextareaName" "content"
"DropzoneParentContainer" ".ui.form"
)}}
<div class="text right edit buttons">
<button class="ui basic primary cancel button" tabindex="3">{{.locale.Tr "repo.issues.cancel"}}</button>
<button class="ui green save button" tabindex="2">{{.locale.Tr "repo.issues.save"}}</button>
</div>
</div>
</div>
</template>
{{end}}
{{template "repo/issue/view_content/reference_issue_dialog" .}}

View File

@@ -9,18 +9,16 @@
<input type="hidden" name="diff_start_cid">
<input type="hidden" name="diff_end_cid">
<input type="hidden" name="diff_base_cid">
<div class="ui top tabular menu" data-write="write" data-preview="preview">
<a class="active item" data-tab="write">{{$.root.locale.Tr "write"}}</a>
<a class="item" data-tab="preview" data-url="{{$.root.Repository.Link}}/markup" data-context="{{$.root.RepoLink}}">{{$.root.locale.Tr "preview"}}</a>
</div>
<div class="field">
<div class="ui active tab" data-tab="write">
<textarea name="content" placeholder="{{$.root.locale.Tr "repo.diff.comment.placeholder"}}"></textarea>
</div>
<div class="ui tab markup" data-tab="preview">
{{.locale.Tr "loading"}}
</div>
</div>
{{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"
)}}
<div class="field footer gt-mx-3">
<span class="markup-info">{{svg "octicon-markup"}} {{$.root.locale.Tr "repo.diff.comment.markdown_info"}}</span>
<div class="ui right">

View File

@@ -7,14 +7,19 @@
<div class="review-box-panel tippy-target">
<div class="ui segment">
<form class="ui form" action="{{.Link}}/reviews/submit" method="post">
{{.CsrfTokenHtml}}
{{.CsrfTokenHtml}}
<input type="hidden" name="commit_id" value="{{.AfterCommitID}}">
<div class="header gt-df gt-ac gt-pb-3">
<div class="gt-f1">{{$.locale.Tr "repo.diff.review.header"}}</div>
<a class="muted close gt-px-3">{{svg "octicon-x" 16}}</a>
</div>
<div class="ui field">
<textarea name="content" tabindex="0" rows="2" placeholder="{{$.locale.Tr "repo.diff.review.placeholder"}}"></textarea>
{{template "shared/combomarkdowneditor" (dict
"locale" $.locale
"TextareaName" "content"
"TextareaPlaceholder" ($.locale.Tr "repo.diff.review.placeholder")
"DropzoneParentContainer" "form"
)}}
</div>
{{if .IsAttachmentEnabled}}
<div class="field">

View File

@@ -1,17 +1,17 @@
<div class="ui top tabular menu" data-write="write" data-preview="preview">
<a class="active item" data-tab="write">{{.locale.Tr "write"}}</a>
<a class="item" data-tab="preview" data-url="{{.Repository.Link}}/markup" data-context="{{.RepoLink}}">{{.locale.Tr "preview"}}</a>
</div>
<div class="field">
<div class="ui bottom active tab" data-tab="write">
<textarea id="content" class="edit_area js-quick-submit" name="content" tabindex="4" data-id="issue-{{.RepoName}}" data-url="{{.Repository.Link}}/markup" data-context="{{.Repo.RepoLink}}">
{{- if .BodyQuery}}{{.BodyQuery}}{{else if .IssueTemplate}}{{.IssueTemplate}}{{else if .PullRequestTemplate}}{{.PullRequestTemplate}}{{else}}{{.content}}{{end -}}
</textarea>
</div>
<div class="ui bottom tab markup" data-tab="preview">
{{.locale.Tr "loading"}}
</div>
</div>
{{$textareaContent := .BodyQuery}}
{{if not $textareaContent}}{{$textareaContent = .IssueTemplate}}{{end}}
{{if not $textareaContent}}{{$textareaContent = .PullRequestTemplate}}{{end}}
{{if not $textareaContent}}{{$textareaContent = .content}}{{end}}
{{template "shared/combomarkdowneditor" (dict
"locale" $.locale
"MarkdownPreviewUrl" (print .Repository.Link "/markup")
"MarkdownPreviewContext" .RepoLink
"TextareaName" "content"
"TextareaContent" $textareaContent
"DropzoneParentContainer" "form, .ui.form"
)}}
{{if .IsAttachmentEnabled}}
<div class="field">
{{template "repo/upload" .}}

View File

@@ -2,5 +2,5 @@
{{template "repo/issue/fields/header" .}}
{{/* FIXME: preview markdown result */}}
{{/* FIXME: required validation for markdown editor */}}
<textarea name="form-field-{{.item.ID}}" placeholder="{{.item.Attributes.placeholder}}" class="edit_area {{if .item.Attributes.render}}no-easymde{{end}}" {{if and .item.Validations.required .item.Attributes.render}}required{{end}}>{{.item.Attributes.value}}</textarea>
<textarea name="form-field-{{.item.ID}}" placeholder="{{.item.Attributes.placeholder}}" {{if and .item.Validations.required .item.Attributes.render}}required{{end}}>{{.item.Attributes.value}}</textarea>
</div>

View File

@@ -20,7 +20,7 @@
<div class="required field">
<label for="name">{{.locale.Tr "repo.issues.label_title"}}</label>
<div class="ui small input">
<input class="label-name-input emoji-input" name="title" placeholder="{{.locale.Tr "repo.issues.new_label_placeholder"}}" autofocus required maxlength="50">
<input class="label-name-input" name="title" placeholder="{{.locale.Tr "repo.issues.new_label_placeholder"}}" autofocus required maxlength="50">
</div>
</div>
<div class="field label-exclusive-input-field">

View File

@@ -8,7 +8,7 @@
<div class="required field">
<label for="name">{{.locale.Tr "repo.issues.label_title"}}</label>
<div class="ui small input">
<input class="label-name-input emoji-input" name="title" placeholder="{{.locale.Tr "repo.issues.new_label_placeholder"}}" autofocus required maxlength="50">
<input class="label-name-input" name="title" placeholder="{{.locale.Tr "repo.issues.new_label_placeholder"}}" autofocus required maxlength="50">
</div>
</div>
<div class="field label-exclusive-input-field">

View File

@@ -164,25 +164,22 @@
{{template "repo/issue/view_content/sidebar" .}}
</div>
<div class="gt-hidden" id="edit-content-form">
<template id="issue-comment-editor-template">
<div class="ui comment form">
<div class="ui top tabular menu">
<a class="active write item">{{$.locale.Tr "write"}}</a>
<a class="preview item" data-url="{{$.Repository.Link}}/markup" data-context="{{$.RepoLink}}">{{$.locale.Tr "preview"}}</a>
</div>
<div class="field">
<div class="ui bottom active tab write">
<textarea tabindex="1" name="content" class="js-quick-submit"></textarea>
</div>
<div class="ui bottom tab preview markup">
{{$.locale.Tr "loading"}}
</div>
</div>
{{template "shared/combomarkdowneditor" (dict
"locale" $.locale
"MarkdownPreviewUrl" (print .Repository.Link "/markup")
"MarkdownPreviewContext" .RepoLink
"TextareaName" "content"
"DropzoneParentContainer" ".ui.form"
)}}
{{if .IsAttachmentEnabled}}
<div class="field">
{{template "repo/upload" .}}
</div>
{{end}}
<div class="field footer">
<div class="text right edit">
<button class="ui basic secondary cancel button" tabindex="3">{{.locale.Tr "repo.issues.cancel"}}</button>
@@ -190,7 +187,7 @@
</div>
</div>
</div>
</div>
</template>
{{template "repo/issue/view_content/reference_issue_dialog" .}}

View File

@@ -49,18 +49,17 @@
<label>{{.locale.Tr "repo.release.title"}}</label>
<input name="title" placeholder="{{.locale.Tr "repo.release.title"}}" value="{{.title}}" autofocus required maxlength="255">
</div>
<div class="field content-editor">
<div class="field">
<label>{{.locale.Tr "repo.release.content"}}</label>
<div class="ui top tabular menu" data-write="write" data-preview="preview">
<a class="active write item" data-tab="write">{{$.locale.Tr "write"}}</a>
<a class="preview item" data-tab="preview" data-url="{{$.Repository.Link}}/markup" data-context="{{$.RepoLink}}">{{$.locale.Tr "preview"}}</a>
</div>
<div class="ui bottom active tab" data-tab="write">
<textarea name="content">{{.content}}</textarea>
</div>
<div class="ui bottom tab markup" data-tab="preview">
{{$.locale.Tr "loading"}}
</div>
{{template "shared/combomarkdowneditor" (dict
"locale" $.locale
"MarkdownPreviewUrl" (print .Repository.Link "/markup")
"MarkdownPreviewContext" .RepoLink
"TextareaName" "content"
"TextareaContent" .content
"DropzoneParentContainer" "form"
)}}
</div>
{{range .attachments}}
<div class="field" id="attachment-{{.ID}}">

View File

@@ -19,15 +19,18 @@
<div class="help">
{{.locale.Tr "repo.wiki.page_name_desc"}}
</div>
<div class="ui top attached tabular menu previewtabs" data-write="write" data-preview="preview">
<a class="active item" data-tab="write">{{.locale.Tr "write"}}</a>
<a class="item" data-tab="preview" data-url="{{$.Repository.Link}}/markup" data-context="{{$.RepoLink}}">{{$.locale.Tr "preview"}}</a>
</div>
<div class="field content" data-loading="{{.locale.Tr "loading"}}">
<div class="ui bottom active tab" data-tab="write">
<textarea class="js-quick-submit" id="edit_area" name="content" data-id="wiki-{{.title}}" data-url="{{.Repository.Link}}/markup" data-context="{{.RepoLink}}">{{if .PageIsWikiEdit}}{{.content}}{{else}}{{.locale.Tr "repo.wiki.welcome"}}{{end}}</textarea>
</div>
</div>
{{$content := .content}}
{{if not .PageIsWikiEdit}}
{{$content = .locale.Tr "repo.wiki.welcome"}}
{{end}}
{{template "shared/combomarkdowneditor" (dict
"locale" $.locale
"MarkdownPreviewUrl" (print .Repository.Link "/markup")
"MarkdownPreviewContext" .RepoLink
"TextareaName" "content"
)}}
<div class="field">
<input name="message" placeholder="{{.locale.Tr "repo.wiki.default_commit_message"}}">
</div>

View File

@@ -0,0 +1,47 @@
{{/*
Template Attributes:
* locale
* ContainerId / ContainerClasses : for the container element
* MarkdownPreviewUrl / MarkdownPreviewContext: for the preview tab
* TextareaName / TextareaContent / TextareaPlaceholder: for the main textarea
* DropzoneParentContainer: for file upload (leave it empty if no upload)
*/}}
<div {{if .ContainerId}}id="{{.ContainerId}}"{{end}} class="combo-markdown-editor {{.ContainerClasses}}" data-dropzone-parent-container="{{.DropzoneParentContainer}}">
{{if .MarkdownPreviewUrl}}
<div class="ui top tabular menu">
<a class="active item" data-tab-for="markdown-writer">{{.locale.Tr "write"}}</a>
<a class="item" data-tab-for="markdown-previewer" data-preview-url="{{.MarkdownPreviewUrl}}" data-preview-context="{{.MarkdownPreviewContext}}">{{.locale.Tr "preview"}}</a>
</div>
{{end}}
<div class="ui tab active" data-tab-panel="markdown-writer">
<markdown-toolbar class="gt-df">
<div class="markdown-toolbar-group">
<md-header class="markdown-toolbar-button">{{svg "octicon-heading"}}</md-header>
<md-bold class="markdown-toolbar-button">{{svg "octicon-bold"}}</md-bold>
<md-italic class="markdown-toolbar-button">{{svg "octicon-italic"}}</md-italic>
</div>
<div class="markdown-toolbar-group">
<md-quote class="markdown-toolbar-button">{{svg "octicon-quote"}}</md-quote>
<md-code class="markdown-toolbar-button">{{svg "octicon-code"}}</md-code>
<md-link class="markdown-toolbar-button">{{svg "octicon-link"}}</md-link>
</div>
<div class="markdown-toolbar-group">
<md-unordered-list class="markdown-toolbar-button">{{svg "octicon-list-unordered"}}</md-unordered-list>
<md-ordered-list class="markdown-toolbar-button">{{svg "octicon-list-ordered"}}</md-ordered-list>
<md-task-list class="markdown-toolbar-button">{{svg "octicon-tasklist"}}</md-task-list>
</div>
<div class="markdown-toolbar-group">
<md-mention class="markdown-toolbar-button">{{svg "octicon-mention"}}</md-mention>
<md-ref class="markdown-toolbar-button">{{svg "octicon-cross-reference"}}</md-ref>
</div>
<div class="markdown-toolbar-group gt-f1"></div>
<div class="markdown-toolbar-group">
<span class="markdown-toolbar-button markdown-switch-easymde">{{svg "octicon-arrow-switch"}}</span>
</div>
</markdown-toolbar>
<textarea class="markdown-text-editor js-quick-submit" name="{{.TextareaName}}" placeholder="{{.TextareaPlaceholder}}">{{.TextareaContent}}</textarea>
</div>
<div class="ui tab markup" data-tab-panel="markdown-previewer">
{{.locale.Tr "loading"}}
</div>
</div>