| [33e1dbd] | 1 | <%#
|
|---|
| 2 | Rich reply editor (shared component) — progressive enhancement.
|
|---|
| 3 |
|
|---|
| 4 | Renders a plain <textarea name="text"> form that works without JS; the shared
|
|---|
| 5 | /assets/js/reply-editor.js upgrades it to a rich contenteditable with a small
|
|---|
| 6 | toolbar, a language select and (on ≤700px) a full-screen compose overlay,
|
|---|
| 7 | which is the right pattern on mobile. On submit the JS fills the hidden
|
|---|
| 8 | `content` field with the editor HTML and `text` with a plain-text fallback;
|
|---|
| 9 | the server prefers `content` and sanitizes it (fedi-reply / authorize_interaction).
|
|---|
| 10 |
|
|---|
| 11 | Locals:
|
|---|
| 12 | action POST target (required)
|
|---|
| 13 | hiddenFields [{ name, value }] extra hidden inputs (optional)
|
|---|
| 14 | placeholder textarea/editor placeholder (required)
|
|---|
| 15 | submitLabel submit button label (required)
|
|---|
| 16 | rows textarea rows for the no-JS fallback (default 3)
|
|---|
| 17 | defaultLang preselected reply language (default: UI lang)
|
|---|
| [5190152] | 18 | initialHtml prefill for EDIT mode (our own sanitized HTML) (optional)
|
|---|
| 19 | initialText plain-text prefill for the no-JS textarea (optional)
|
|---|
| 20 | noAttach true hides the media button (edits do not touch attachments)
|
|---|
| [33e1dbd] | 21 | %>
|
|---|
| [5190152] | 22 | <% var _reInitHtml = (typeof initialHtml !== 'undefined' && initialHtml) || ''; %>
|
|---|
| 23 | <% var _reInitText = (typeof initialText !== 'undefined' && initialText) || ''; %>
|
|---|
| 24 | <% var _reNoAttach = (typeof noAttach !== 'undefined' && noAttach); %>
|
|---|
| [33e1dbd] | 25 | <% var _reLang = (typeof defaultLang !== 'undefined' && defaultLang) || (typeof lang !== 'undefined' ? lang : 'en'); %>
|
|---|
| [feced2c] | 26 | <form method="post" action="<%= action %>" class="re-form" data-re
|
|---|
| 27 | data-upload="/posts/upload-reply-media" data-upload-err="<%= t('re.attach_err') %>">
|
|---|
| [33e1dbd] | 28 | <% (typeof hiddenFields !== 'undefined' ? hiddenFields : []).forEach(function (h) { %>
|
|---|
| 29 | <input type="hidden" name="<%= h.name %>" value="<%= h.value %>">
|
|---|
| 30 | <% }); %>
|
|---|
| 31 | <input type="hidden" name="content" value="">
|
|---|
| 32 | <%# Full-screen top bar (mobile compose). Hidden until JS + fullscreen. %>
|
|---|
| 33 | <div class="re-head" hidden>
|
|---|
| 34 | <button type="button" class="re-cancel" aria-label="<%= t('comments.cancel') %>">×</button>
|
|---|
| 35 | <strong class="re-head-title"><%= t('re.title') %></strong>
|
|---|
| 36 | <button type="submit" class="btn re-send-top"><%= submitLabel %></button>
|
|---|
| 37 | </div>
|
|---|
| 38 | <div class="re-toolbar" role="toolbar" aria-label="<%= t('re.title') %>" hidden>
|
|---|
| 39 | <button type="button" data-cmd="bold" title="<%= t('re.bold') %>" aria-label="<%= t('re.bold') %>"><b>B</b></button>
|
|---|
| 40 | <button type="button" data-cmd="italic" title="<%= t('re.italic') %>" aria-label="<%= t('re.italic') %>"><i>I</i></button>
|
|---|
| 41 | <button type="button" data-cmd="link" title="<%= t('re.link') %>" aria-label="<%= t('re.link') %>">🔗</button>
|
|---|
| 42 | <button type="button" data-cmd="list" title="<%= t('re.list') %>" aria-label="<%= t('re.list') %>">•≡</button>
|
|---|
| 43 | <button type="button" data-cmd="quote" title="<%= t('re.quote') %>" aria-label="<%= t('re.quote') %>">❝</button>
|
|---|
| [5190152] | 44 | <% if (!_reNoAttach) { %>
|
|---|
| 45 | <button type="button" data-cmd="attach" title="<%= t('re.attach') %>" aria-label="<%= t('re.attach') %>">📎</button>
|
|---|
| 46 | <input type="file" class="re-file" accept="image/*,audio/*,video/*" multiple hidden>
|
|---|
| 47 | <% } %>
|
|---|
| [33e1dbd] | 48 | </div>
|
|---|
| [5190152] | 49 | <% if (!_reNoAttach) { %>
|
|---|
| 50 | <input type="hidden" name="attachments" value="">
|
|---|
| 51 | <div class="re-attachments" hidden></div>
|
|---|
| 52 | <% } %>
|
|---|
| 53 | <textarea name="text" rows="<%= typeof rows !== 'undefined' ? rows : 3 %>" required placeholder="<%= placeholder %>"><%= _reInitText %></textarea>
|
|---|
| [33e1dbd] | 54 | <div class="re-editor" contenteditable="true" role="textbox" aria-multiline="true"
|
|---|
| [5190152] | 55 | data-ph="<%= placeholder %>" aria-label="<%= placeholder %>" hidden><%- _reInitHtml %></div>
|
|---|
| [33e1dbd] | 56 | <div class="re-foot">
|
|---|
| 57 | <select name="language" class="re-lang" aria-label="<%= t('re.lang') %>" hidden>
|
|---|
| 58 | <% [['en','English'],['nl','Nederlands'],['de','Deutsch'],['fr','Français'],['es','Español'],['it','Italiano'],['pt','Português'],['pl','Polski'],['ru','Русский'],['uk','Українська'],['sv','Svenska'],['da','Dansk'],['nb','Norsk'],['fi','Suomi'],['tr','Türkçe'],['ja','日本語'],['zh','中文'],['ar','العربية']].forEach(function (l) { %>
|
|---|
| 59 | <option value="<%= l[0] %>" <%= l[0] === _reLang ? 'selected' : '' %>><%= l[1] %></option>
|
|---|
| 60 | <% }); %>
|
|---|
| 61 | </select>
|
|---|
| 62 | <button type="submit" class="btn re-send"><%= submitLabel %></button>
|
|---|
| 63 | </div>
|
|---|
| 64 | </form>
|
|---|
| 65 | <%# Assets once per render, even when this partial repeats per comment. %>
|
|---|
| 66 | <% if (!locals.__reAssets) { locals.__reAssets = 1; %>
|
|---|
| 67 | <link rel="stylesheet" href="/assets/css/reply-editor.css">
|
|---|
| 68 | <script src="/assets/js/reply-editor.js" defer></script>
|
|---|
| 69 | <% } %>
|
|---|