mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-06-20 16:10:50 +00:00
Some checks are pending
/ release (push) Waiting to run
testing / test-e2e (push) Blocked by required conditions
testing / backend-checks (push) Waiting to run
testing / frontend-checks (push) Waiting to run
testing / test-unit (push) Blocked by required conditions
testing / test-remote-cacher (redis) (push) Blocked by required conditions
testing / test-remote-cacher (valkey) (push) Blocked by required conditions
testing / test-remote-cacher (garnet) (push) Blocked by required conditions
testing / test-remote-cacher (redict) (push) Blocked by required conditions
testing / test-mysql (push) Blocked by required conditions
testing / test-pgsql (push) Blocked by required conditions
testing / test-sqlite (push) Blocked by required conditions
testing / security-check (push) Blocked by required conditions
The primary goal is to balance having the editor work as expected by developers (with Tab key affecting indentation) while also not impeding keyboard navigation.
* Tab indents, Shift+Tab unindents, but only when that indent would be valid. E.g. moving existing list items down or up one level.
* Indenting a selection always works.
* When an "invalid" indent is attempted, nothing happens and a toast is shown with a hint to press again to leave the editor.
* Attempting the same action again allows the textarea lose focus by allowing the browser's default key handler.
* Pressing Esc also loses focus immediately.
* No tab handling happens until the text editor has been interacted with (other than just having been focused).
* Changing indentation in block quotes adds or removes quote levels instead.
Screenshot of the toast being shown:
a6287d29
-4ce0-4977-aae8-ef1aff2ac89f
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/6813
Reviewed-by: Otto <otto@codeberg.org>
Reviewed-by: 0ko <0ko@noreply.codeberg.org>
Co-authored-by: Danko Aleksejevs <danko@very.lv>
Co-committed-by: Danko Aleksejevs <danko@very.lv>
120 lines
7.3 KiB
Go HTML Template
120 lines
7.3 KiB
Go HTML Template
{{/*
|
|
Template Attributes:
|
|
* ContainerId: id attribute for the container element
|
|
* ContainerClasses: additional classes for the container element
|
|
* MarkdownPreviewUrl: preview url for the preview tab
|
|
* MarkdownPreviewContext: preview context for the preview tab
|
|
* TextareaName: name attribute for the textarea
|
|
* TextareaContent: content for the textarea
|
|
* TextareaPlaceholder: placeholder attribute for the textarea
|
|
* TextareaAriaLabel: aria-label attribute for the textarea
|
|
* DropzoneParentContainer: container for file upload (leave it empty if no upload)
|
|
* DisableAutosize: whether to disable automatic height resizing
|
|
* EasyMDE: whether to display button for switching to legacy editor
|
|
*/}}
|
|
<div {{if .ContainerId}}id="{{.ContainerId}}"{{end}} class="combo-markdown-editor {{.ContainerClasses}}" data-dropzone-parent-container="{{.DropzoneParentContainer}}" data-tab-hint="{{ctx.Locale.TrString "editor.textarea.tab_hint"}}" data-shift-tab-hint="{{ctx.Locale.TrString "editor.textarea.shift_tab_hint"}}">
|
|
|
|
<markdown-toolbar>
|
|
{{if .MarkdownPreviewUrl}}
|
|
<div class="markdown-toolbar-switch">
|
|
<div class="switch">
|
|
<a href="#" class="active item" data-tab-for="markdown-writer">{{ctx.Locale.Tr "write"}}</a>
|
|
<a href="#" class="item" data-tab-for="markdown-previewer" data-preview-url="{{.MarkdownPreviewUrl}}" data-preview-context="{{.MarkdownPreviewContext}}">{{ctx.Locale.Tr "preview"}}</a>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
<div class="markdown-toolbar-group">
|
|
<md-header class="markdown-toolbar-button" data-tooltip-content="{{ctx.Locale.Tr "editor.buttons.heading.tooltip"}}">{{svg "octicon-heading"}}</md-header>
|
|
<md-bold class="markdown-toolbar-button" data-tooltip-content="{{ctx.Locale.Tr "editor.buttons.bold.tooltip"}}">{{svg "octicon-bold"}}</md-bold>
|
|
<md-italic class="markdown-toolbar-button" data-tooltip-content="{{ctx.Locale.Tr "editor.buttons.italic.tooltip"}}">{{svg "octicon-italic"}}</md-italic>
|
|
</div>
|
|
<div class="markdown-toolbar-group">
|
|
<md-quote class="markdown-toolbar-button" data-tooltip-content="{{ctx.Locale.Tr "editor.buttons.quote.tooltip"}}">{{svg "octicon-quote"}}</md-quote>
|
|
<md-code class="markdown-toolbar-button" data-tooltip-content="{{ctx.Locale.Tr "editor.buttons.code.tooltip"}}">{{svg "octicon-code"}}</md-code>
|
|
<button class="markdown-toolbar-button show-modal button" data-md-button data-md-action="new-link" data-tooltip-content="{{ctx.Locale.Tr "editor.buttons.link.tooltip"}}">{{svg "octicon-link"}}</button>
|
|
</div>
|
|
<div class="markdown-toolbar-group">
|
|
<md-unordered-list class="markdown-toolbar-button" data-tooltip-content="{{ctx.Locale.Tr "editor.buttons.list.unordered.tooltip"}}">{{svg "octicon-list-unordered"}}</md-unordered-list>
|
|
<md-ordered-list class="markdown-toolbar-button" data-tooltip-content="{{ctx.Locale.Tr "editor.buttons.list.ordered.tooltip"}}">{{svg "octicon-list-ordered"}}</md-ordered-list>
|
|
<md-task-list class="markdown-toolbar-button" data-tooltip-content="{{ctx.Locale.Tr "editor.buttons.list.task.tooltip"}}">{{svg "octicon-tasklist"}}</md-task-list>
|
|
<button type="button" class="markdown-toolbar-button" data-md-button data-md-action="unindent" data-tooltip-content="{{ctx.Locale.Tr "editor.buttons.unindent.tooltip"}}">{{svg "octicon-arrow-left"}}</button>
|
|
<button type="button" class="markdown-toolbar-button" data-md-button data-md-action="indent" data-tooltip-content="{{ctx.Locale.Tr "editor.buttons.indent.tooltip"}}">{{svg "octicon-arrow-right"}}</button>
|
|
</div>
|
|
<div class="markdown-toolbar-group">
|
|
<button type="button" class="markdown-toolbar-button show-modal button" data-md-button data-md-action="new-table" data-tooltip-content="{{ctx.Locale.Tr "editor.buttons.new_table.tooltip"}}">{{svg "octicon-table"}}</button>
|
|
<md-mention class="markdown-toolbar-button" data-tooltip-content="{{ctx.Locale.Tr "editor.buttons.mention.tooltip"}}">{{svg "octicon-mention"}}</md-mention>
|
|
<md-ref class="markdown-toolbar-button" data-tooltip-content="{{ctx.Locale.Tr "editor.buttons.ref.tooltip"}}">{{svg "octicon-cross-reference"}}</md-ref>
|
|
</div>
|
|
<div class="markdown-toolbar-group">
|
|
<button class="markdown-toolbar-button markdown-switch-monospace" data-md-button role="switch" data-enable-text="{{ctx.Locale.Tr "editor.buttons.enable_monospace_font"}}" data-disable-text="{{ctx.Locale.Tr "editor.buttons.disable_monospace_font"}}">{{svg "octicon-typography"}}</button>
|
|
{{if .EasyMDE}}
|
|
<button class="markdown-toolbar-button markdown-switch-easymde" data-tooltip-content="{{ctx.Locale.Tr "editor.buttons.switch_to_legacy.tooltip"}}">{{svg "octicon-arrow-switch"}}</button>
|
|
{{end}}
|
|
</div>
|
|
</markdown-toolbar>
|
|
<div class="ui tab active" data-tab-panel="markdown-writer">
|
|
<text-expander keys=": @" suffix="">
|
|
<textarea class="markdown-text-editor js-quick-submit"{{if .TextareaName}} name="{{.TextareaName}}"{{end}}{{if .TextareaPlaceholder}} placeholder="{{.TextareaPlaceholder}}"{{end}}{{if .TextareaAriaLabel}} aria-label="{{.TextareaAriaLabel}}"{{end}}{{if .DisableAutosize}} data-disable-autosize="{{.DisableAutosize}}"{{end}}>{{.TextareaContent}}</textarea>
|
|
</text-expander>
|
|
<script>
|
|
if (localStorage?.getItem('markdown-editor-monospace') === 'true') {
|
|
document.querySelector('.markdown-text-editor').classList.add('tw-font-mono');
|
|
}
|
|
</script>
|
|
</div>
|
|
<div class="ui tab markup" data-tab-panel="markdown-previewer">
|
|
{{ctx.Locale.Tr "loading"}}
|
|
</div>
|
|
|
|
<div class="ui small modal tw-w-fit" data-modal-name="new-markdown-table">
|
|
<div class="header">{{ctx.Locale.Tr "editor.table_modal.header"}}</div>
|
|
|
|
<div class="ui form content" data-selector-name="form">
|
|
<input type="hidden" name="table-header" value="{{ctx.Locale.Tr "editor.table_modal.placeholder.header"}}">
|
|
<input type="hidden" name="table-content" value="{{ctx.Locale.Tr "editor.table_modal.placeholder.content"}}">
|
|
<table>
|
|
<tbody>
|
|
<tr>
|
|
<td><label>{{ctx.Locale.Tr "editor.table_modal.label.rows"}}</label></td>
|
|
<td><input type="number" name="table-rows" min="1" value="2" required></td>
|
|
</tr>
|
|
<tr>
|
|
<td><label>{{ctx.Locale.Tr "editor.table_modal.label.columns"}}</label></td>
|
|
<td><input type="number" name="table-columns" min="1" value="2" required></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="text right actions">
|
|
<button class="ui cancel button" data-selector-name="cancel-button">{{ctx.Locale.Tr "cancel"}}</button>
|
|
<button class="ui primary button" data-selector-name="ok-button">{{ctx.Locale.Tr "ok"}}</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="ui small modal" data-modal-name="new-markdown-link">
|
|
<div class="header">{{ctx.Locale.Tr "editor.link_modal.header"}}</div>
|
|
|
|
<fieldset class="content">
|
|
<div class="ui form" data-selector-name="form">
|
|
<label>
|
|
{{ctx.Locale.Tr "editor.link_modal.url"}}
|
|
<input name="link-url" required dir="auto" autocomplete="off">
|
|
</label>
|
|
<label>
|
|
{{ctx.Locale.Tr "editor.link_modal.description"}}
|
|
<input name="link-description" required dir="auto" autocomplete="off">
|
|
</label>
|
|
|
|
<div class="help">
|
|
{{ctx.Locale.Tr "editor.link_modal.paste_reminder"}}
|
|
</div>
|
|
|
|
<div class="text right actions">
|
|
<button class="ui cancel button" data-selector-name="cancel-button">{{ctx.Locale.Tr "cancel"}}</button>
|
|
<button class="ui primary button" data-selector-name="ok-button">{{ctx.Locale.Tr "ok"}}</button>
|
|
</div>
|
|
</div>
|
|
</fieldset>
|
|
</div>
|
|
</div>
|