mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-01-18 13:32:58 +01:00
Merge commit '469aa5511fcfb3c75d2d5e3f60d066a3a968da90' into v3.x
This commit is contained in:
26
CHANGELOG.md
26
CHANGELOG.md
@@ -1,3 +1,29 @@
|
||||
#### v3.1.3 (2023-05-15)
|
||||
|
||||
##### Chores
|
||||
|
||||
* incrementing version number - v3.1.2 (40fa3489)
|
||||
* update changelog for v3.1.2 (5b398782)
|
||||
* incrementing version number - v3.1.1 (40250733)
|
||||
* incrementing version number - v3.1.0 (0cb386bd)
|
||||
* incrementing version number - v3.0.1 (26f6ea49)
|
||||
* incrementing version number - v3.0.0 (224e08cd)
|
||||
|
||||
##### Continuous Integration
|
||||
|
||||
* use GitHub Actions expression instead of handlebars template (#11599) (412a1ecf)
|
||||
* tag with branch name if not default branch (cd7fdfce)
|
||||
|
||||
##### Bug Fixes
|
||||
|
||||
* #11601, dont trigger edit if chat input has text (d55cd464)
|
||||
* #11600, prevent helmet crash on startup (8eed5a84)
|
||||
* #11594 (85d104c3)
|
||||
|
||||
##### Other Changes
|
||||
|
||||
* use csrf_token in ws handshake (#11573) (51096ad2)
|
||||
|
||||
#### v3.1.2 (2023-05-12)
|
||||
|
||||
##### Chores
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
"nodebb-plugin-dbsearch": "6.0.1",
|
||||
"nodebb-plugin-emoji": "5.0.10",
|
||||
"nodebb-plugin-emoji-android": "4.0.0",
|
||||
"nodebb-plugin-markdown": "12.0.3",
|
||||
"nodebb-plugin-markdown": "12.0.4",
|
||||
"nodebb-plugin-mentions": "4.1.1",
|
||||
"nodebb-plugin-ntfy": "1.0.15",
|
||||
"nodebb-plugin-spam-be-gone": "2.0.7",
|
||||
|
||||
@@ -55,7 +55,7 @@ define('forum/chats', [
|
||||
|
||||
Chats.initialised = true;
|
||||
messages.scrollToBottom($('.expanded-chat ul.chat-content'));
|
||||
|
||||
messages.wrapImagesInLinks($('.expanded-chat ul.chat-content'));
|
||||
search.init();
|
||||
};
|
||||
|
||||
@@ -69,6 +69,7 @@ define('forum/chats', [
|
||||
Chats.addScrollHandler(ajaxify.data.roomId, ajaxify.data.uid, $('.chat-content'));
|
||||
Chats.addScrollBottomHandler($('.chat-content'));
|
||||
Chats.addCharactersLeftHandler($('[component="chat/main-wrapper"]'));
|
||||
Chats.addTextareaResizeHandler($('[component="chat/main-wrapper"]'));
|
||||
Chats.addIPHandler($('[component="chat/main-wrapper"]'));
|
||||
Chats.createAutoComplete(ajaxify.data.roomId, $('[component="chat/input"]'));
|
||||
Chats.addUploadHandler({
|
||||
@@ -169,10 +170,8 @@ define('forum/chats', [
|
||||
messages.parseMessage(data, function (html) {
|
||||
const currentScrollTop = el.scrollTop();
|
||||
const previousHeight = el[0].scrollHeight;
|
||||
html = $(html);
|
||||
el.prepend(html);
|
||||
html.find('.timeago').timeago();
|
||||
html.find('img:not(.not-responsive)').addClass('img-fluid');
|
||||
messages.onMessagesAddedToDom(html);
|
||||
el.scrollTop((el[0].scrollHeight - previousHeight) + currentScrollTop);
|
||||
loading = false;
|
||||
});
|
||||
@@ -195,6 +194,19 @@ define('forum/chats', [
|
||||
});
|
||||
};
|
||||
|
||||
Chats.addTextareaResizeHandler = function (parent) {
|
||||
// https://stackoverflow.com/questions/454202/creating-a-textarea-with-auto-resize
|
||||
const textarea = parent.find('[component="chat/input"]');
|
||||
textarea.on('input', function () {
|
||||
const isAtBottom = messages.isAtBottom(parent.find('.chat-content'));
|
||||
textarea.css({ height: 0 });
|
||||
textarea.css({ height: textarea.prop('scrollHeight') + 'px' });
|
||||
if (isAtBottom) {
|
||||
messages.scrollToBottom(parent.find('.chat-content'));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Chats.addActionHandlers = function (element, roomId) {
|
||||
element.on('click', '[data-action]', function () {
|
||||
const messageId = $(this).parents('[data-mid]').attr('data-mid');
|
||||
|
||||
@@ -3,8 +3,11 @@
|
||||
|
||||
define('forum/chats/messages', [
|
||||
'components', 'translator', 'benchpress', 'hooks',
|
||||
'bootbox', 'alerts', 'messages', 'api',
|
||||
], function (components, translator, Benchpress, hooks, bootbox, alerts, messagesModule, api) {
|
||||
'bootbox', 'alerts', 'messages', 'api', 'forum/topic/images',
|
||||
], function (
|
||||
components, translator, Benchpress, hooks,
|
||||
bootbox, alerts, messagesModule, api, images
|
||||
) {
|
||||
const messages = {};
|
||||
|
||||
messages.sendMessage = async function (roomId, inputEl) {
|
||||
@@ -25,6 +28,7 @@ define('forum/chats/messages', [
|
||||
}).catch((err) => {
|
||||
inputEl.val(message).trigger('input');
|
||||
messages.updateRemainingLength(inputEl.parent());
|
||||
messages.updateTextAreaHeight(chatContent);
|
||||
if (err.message === '[[error:email-not-confirmed-chat]]') {
|
||||
return messagesModule.showEmailConfirmWarning(err.message);
|
||||
}
|
||||
@@ -49,18 +53,9 @@ define('forum/chats/messages', [
|
||||
};
|
||||
|
||||
messages.updateTextAreaHeight = function (chatContentEl) {
|
||||
// https://stackoverflow.com/questions/454202/creating-a-textarea-with-auto-resize
|
||||
const textarea = chatContentEl.find('[component="chat/input"]');
|
||||
const scrollHeight = textarea.prop('scrollHeight');
|
||||
textarea.css({ height: scrollHeight + 'px' });
|
||||
textarea.on('input', function () {
|
||||
const isAtBottom = messages.isAtBottom(chatContentEl.find('.chat-content'));
|
||||
textarea.css({ height: 0 });
|
||||
textarea.css({ height: textarea.prop('scrollHeight') + 'px' });
|
||||
if (isAtBottom) {
|
||||
messages.scrollToBottom(chatContentEl.find('.chat-content'));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function autoresizeTextArea(textarea) {
|
||||
@@ -89,8 +84,7 @@ define('forum/chats/messages', [
|
||||
const newMessage = $(html);
|
||||
const isAtBottom = messages.isAtBottom(chatContentEl);
|
||||
newMessage.appendTo(chatContentEl);
|
||||
newMessage.find('.timeago').timeago();
|
||||
newMessage.find('img:not(.not-responsive)').addClass('img-fluid');
|
||||
messages.onMessagesAddedToDom(newMessage);
|
||||
if (isAtBottom) {
|
||||
messages.scrollToBottom(chatContentEl);
|
||||
}
|
||||
@@ -100,10 +94,15 @@ define('forum/chats/messages', [
|
||||
});
|
||||
}
|
||||
|
||||
messages.onMessagesAddedToDom = function (messageEls) {
|
||||
messageEls.find('.timeago').timeago();
|
||||
messageEls.find('img:not(.not-responsive)').addClass('img-fluid');
|
||||
messages.wrapImagesInLinks(messageEls.first().parent());
|
||||
};
|
||||
|
||||
messages.parseMessage = function (data, callback) {
|
||||
function done(html) {
|
||||
translator.translate(html, callback);
|
||||
translator.translate(html, translated => callback($(translated)));
|
||||
}
|
||||
const tplData = {
|
||||
messages: data,
|
||||
@@ -134,6 +133,12 @@ define('forum/chats/messages', [
|
||||
}
|
||||
};
|
||||
|
||||
messages.wrapImagesInLinks = function (containerEl) {
|
||||
containerEl.find('[component="chat/message/body"] img:not(.emoji)').each(function () {
|
||||
images.wrapImageInLink($(this));
|
||||
});
|
||||
};
|
||||
|
||||
messages.toggleScrollUpAlert = function (containerEl) {
|
||||
const isAtBottom = messages.isAtBottom(containerEl, 300);
|
||||
containerEl.parent()
|
||||
@@ -225,7 +230,7 @@ define('forum/chats/messages', [
|
||||
const body = components.get('chat/message', message.messageId);
|
||||
if (body.length) {
|
||||
body.replaceWith(html);
|
||||
components.get('chat/message', message.messageId).find('.timeago').timeago();
|
||||
messages.onMessagesAddedToDom(html);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -234,13 +239,15 @@ define('forum/chats/messages', [
|
||||
function onChatMessageDeleted(messageId) {
|
||||
components.get('chat/message', messageId)
|
||||
.toggleClass('deleted', true)
|
||||
.find('[component="chat/message/body"]').translateHtml('[[modules:chat.message-deleted]]');
|
||||
.find('[component="chat/message/body"]')
|
||||
.translateHtml('[[modules:chat.message-deleted]]');
|
||||
}
|
||||
|
||||
function onChatMessageRestored(message) {
|
||||
components.get('chat/message', message.messageId)
|
||||
.toggleClass('deleted', false)
|
||||
.find('[component="chat/message/body"]').html(message.content);
|
||||
.find('[component="chat/message/body"]')
|
||||
.html(message.content);
|
||||
}
|
||||
|
||||
messages.delete = function (messageId, roomId) {
|
||||
|
||||
@@ -113,7 +113,6 @@ define('forum/post-queue', [
|
||||
if (subselector) {
|
||||
const action = subselector.getAttribute('data-action');
|
||||
const uid = subselector.closest('[data-uid]').getAttribute('data-uid');
|
||||
|
||||
switch (action) {
|
||||
case 'editCategory': {
|
||||
const categoryEl = e.target.closest('[data-id]').querySelector('.topic-category');
|
||||
|
||||
@@ -234,7 +234,7 @@ define('forum/topic', [
|
||||
let codeBlocks = $('[component="topic"] [component="post/content"] code:not([data-button-added])');
|
||||
codeBlocks = codeBlocks.filter((i, el) => $(el).text().includes('\n'));
|
||||
const container = $('<div class="hover-parent position-relative"></div>');
|
||||
const buttonDiv = $('<button component="copy/code/btn" class="hover-visible position-absolute end-0 top-0 btn btn-sm btn-outline-secondary me-4"><i class="fa fa-fw fa-copy"></i></button>');
|
||||
const buttonDiv = $('<button component="copy/code/btn" class="hover-visible position-absolute end-0 top-0 btn btn-sm btn-outline-secondary mt-2 me-4"><i class="fa fa-fw fa-copy"></i></button>');
|
||||
codeBlocks.parent().wrap(container).parent().append(buttonDiv);
|
||||
codeBlocks.parent().parent().find('[component="copy/code/btn"]').translateAttr('title', '[[topic:copy-code]]');
|
||||
codeBlocks.attr('data-button-added', 1);
|
||||
|
||||
@@ -9,9 +9,8 @@ define('forum/topic/events', [
|
||||
'forum/topic/images',
|
||||
'components',
|
||||
'translator',
|
||||
'benchpress',
|
||||
'hooks',
|
||||
], function (postTools, threadTools, posts, images, components, translator, Benchpress, hooks) {
|
||||
], function (postTools, threadTools, posts, images, components, translator, hooks) {
|
||||
const Events = {};
|
||||
|
||||
const events = {
|
||||
|
||||
@@ -4,30 +4,32 @@
|
||||
define('forum/topic/images', [], function () {
|
||||
const Images = {};
|
||||
|
||||
const suffixRegex = /-resized(\.[\w]+)?$/;
|
||||
|
||||
Images.wrapImagesInLinks = function (posts) {
|
||||
posts.find('[component="post/content"] img:not(.emoji)').each(function () {
|
||||
const $this = $(this);
|
||||
let src = $this.attr('src') || '';
|
||||
const alt = $this.attr('alt') || '';
|
||||
const suffixRegex = /-resized(\.[\w]+)?$/;
|
||||
Images.wrapImageInLink($(this));
|
||||
});
|
||||
};
|
||||
|
||||
if (src === 'about:blank') {
|
||||
return;
|
||||
}
|
||||
Images.wrapImageInLink = function (imageEl) {
|
||||
let src = imageEl.attr('src') || '';
|
||||
if (src === 'about:blank') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!imageEl.parent().is('a')) {
|
||||
if (utils.isRelativeUrl(src) && suffixRegex.test(src)) {
|
||||
src = src.replace(suffixRegex, '$1');
|
||||
}
|
||||
const alt = imageEl.attr('alt') || '';
|
||||
const srcExt = src.split('.').slice(1).pop();
|
||||
const altFilename = alt.split('/').pop();
|
||||
const altExt = altFilename.split('.').slice(1).pop();
|
||||
|
||||
if (!$this.parent().is('a')) {
|
||||
$this.wrap('<a href="' + src + '" ' +
|
||||
(!srcExt && altExt ? ' download="' + altFilename + '" ' : '') +
|
||||
' target="_blank" rel="noopener">');
|
||||
}
|
||||
});
|
||||
imageEl.wrap('<a href="' + src + '" ' +
|
||||
(!srcExt && altExt ? ' download="' + altFilename + '" ' : '') +
|
||||
' target="_blank" rel="noopener">');
|
||||
}
|
||||
};
|
||||
|
||||
return Images;
|
||||
|
||||
@@ -246,6 +246,7 @@ define('chat', [
|
||||
chatModal.css('position', 'fixed');
|
||||
chatModal.appendTo($('body'));
|
||||
chatModal.find('.timeago').timeago();
|
||||
ChatsMessages.wrapImagesInLinks(chatModal.find('[component="chat/messages"] .chat-content'));
|
||||
module.center(chatModal);
|
||||
|
||||
app.loadJQueryUI(function () {
|
||||
@@ -331,6 +332,7 @@ define('chat', [
|
||||
Chats.addScrollBottomHandler(chatModal.find('.chat-content'));
|
||||
|
||||
Chats.addCharactersLeftHandler(chatModal);
|
||||
Chats.addTextareaResizeHandler(chatModal);
|
||||
Chats.addIPHandler(chatModal);
|
||||
|
||||
Chats.addUploadHandler({
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<title></title> <!-- The title tag shows in email notifications, like Android 4.4. -->
|
||||
|
||||
<!-- Web Font / @font-face : BEGIN -->
|
||||
<!-- NOTE: If web fonts are not required, lines 10 - 27 can be safely removed. -->
|
||||
<!-- NOTE: If web fonts are not required, lines 10 - 27 can be safely removed. -->
|
||||
|
||||
<!-- Desktop Outlook chokes on web font references and defaults to Times New Roman, so we force a safe fallback font. -->
|
||||
<!--[if mso]>
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
<!-- Web Font / @font-face : END -->
|
||||
|
||||
<!-- CSS Reset -->
|
||||
<!-- CSS Reset -->
|
||||
<style>
|
||||
|
||||
/* What it does: Remove spaces around the email design added by some email clients. */
|
||||
@@ -90,13 +90,13 @@
|
||||
|
||||
/* What it does: Prevents Gmail from displaying an download button on large, non-linked images. */
|
||||
.a6S {
|
||||
display: none !important;
|
||||
opacity: 0.01 !important;
|
||||
display: none !important;
|
||||
opacity: 0.01 !important;
|
||||
}
|
||||
/* If the above doesn't work, add a .g-img class to any image in question. */
|
||||
img.g-img + div {
|
||||
display:none !important;
|
||||
}
|
||||
display:none !important;
|
||||
}
|
||||
|
||||
/* What it does: Prevents underlining the button text in Windows 10 */
|
||||
.button-link {
|
||||
@@ -132,56 +132,61 @@
|
||||
@media screen and (max-width: 600px) {
|
||||
|
||||
/* What it does: Adjust typography on small screens to improve readability */
|
||||
.email-container p {
|
||||
font-size: 17px !important;
|
||||
line-height: 26px !important;
|
||||
}
|
||||
|
||||
}
|
||||
.email-container p {
|
||||
font-size: 17px !important;
|
||||
line-height: 26px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.notification-body img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
</style>
|
||||
/* https://github.com/NodeBB/NodeBB/issues/11572 */
|
||||
img[src*="nodebb-plugin-emoji"] {
|
||||
width: 23px;
|
||||
height: auto;
|
||||
vertical-align: top;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- What it does: Makes background images in 72ppi Outlook render at correct size. -->
|
||||
<!--[if gte mso 9]>
|
||||
<xml>
|
||||
<o:OfficeDocumentSettings>
|
||||
<o:AllowPNG/>
|
||||
<o:PixelsPerInch>96</o:PixelsPerInch>
|
||||
</o:OfficeDocumentSettings>
|
||||
</xml>
|
||||
<![endif]-->
|
||||
<!-- What it does: Makes background images in 72ppi Outlook render at correct size. -->
|
||||
<!--[if gte mso 9]>
|
||||
<xml>
|
||||
<o:OfficeDocumentSettings>
|
||||
<o:AllowPNG/>
|
||||
<o:PixelsPerInch>96</o:PixelsPerInch>
|
||||
</o:OfficeDocumentSettings>
|
||||
</xml>
|
||||
<![endif]-->
|
||||
|
||||
</head>
|
||||
|
||||
<body width="100%" bgcolor="#f6f6f6" style="margin: 0; mso-line-height-rule: exactly;">
|
||||
<center style="width: 100%; background: #f6f6f6; text-align: left;">
|
||||
<center style="width: 100%; background: #f6f6f6; text-align: left;">
|
||||
|
||||
<!--
|
||||
Set the email width. Defined in two places:
|
||||
1. max-width for all clients except Desktop Windows Outlook, allowing the email to squish on narrow but never go wider than 600px.
|
||||
2. MSO tags for Desktop Windows Outlook enforce a 600px width.
|
||||
-->
|
||||
<div style="max-width: 600px; margin: auto;{{{ if rtl }}} text-align: right; direction: rtl;{{{ end }}}" class="email-container">
|
||||
<!--[if mso]>
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="600" align="center">
|
||||
<tr>
|
||||
<td>
|
||||
<![endif]-->
|
||||
<!--
|
||||
Set the email width. Defined in two places:
|
||||
1. max-width for all clients except Desktop Windows Outlook, allowing the email to squish on narrow but never go wider than 600px.
|
||||
2. MSO tags for Desktop Windows Outlook enforce a 600px width.
|
||||
-->
|
||||
<div style="max-width: 600px; margin: auto;{{{ if rtl }}} text-align: right; direction: rtl;{{{ end }}}" class="email-container">
|
||||
<!--[if mso]>
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="600" align="center">
|
||||
<tr>
|
||||
<td>
|
||||
<![endif]-->
|
||||
|
||||
<!-- Email Header : BEGIN -->
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" align="center" width="100%" style="max-width: 600px;">
|
||||
<tr>
|
||||
<td style="padding: 20px 0; text-align: center">
|
||||
{{{ if logo.src }}}
|
||||
<img src="{logo.src}" height="auto" width="{logo.width}" alt="{site_title}" border="0" style="height: auto; width: {logo.width}px; background: #f6f6f6; font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol; font-size: 15px; line-height: 20px; color: #333333;">
|
||||
{{{ else }}}
|
||||
|
||||
{{{ end }}}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<!-- Email Header : END -->
|
||||
<!-- Email Header : BEGIN -->
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" align="center" width="100%" style="max-width: 600px;">
|
||||
<tr>
|
||||
<td style="padding: 20px 0; text-align: center">
|
||||
{{{ if logo.src }}}
|
||||
<img src="{logo.src}" height="auto" width="{logo.width}" alt="{site_title}" border="0" style="height: auto; width: {logo.width}px; background: #f6f6f6; font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol; font-size: 15px; line-height: 20px; color: #333333;">
|
||||
{{{ else }}}
|
||||
|
||||
{{{ end }}}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<!-- Email Header : END -->
|
||||
@@ -45,7 +45,7 @@
|
||||
{{{ end }}}
|
||||
|
||||
{{{ each posts }}}
|
||||
<div class="card mb-3" data-id="{posts.id}">
|
||||
<div class="card mb-3" data-id="{./id}"data-uid="{./user.uid}">
|
||||
<div class="card-header">
|
||||
{{{ if !singlePost }}}
|
||||
<input type="checkbox" class="form-check-input" autocomplete="off" />
|
||||
@@ -82,7 +82,7 @@
|
||||
{{{ if posts.data.tid }}}
|
||||
<a href="{config.relative_path}/topic/{posts.data.tid}">{posts.topic.title}</a>
|
||||
{{{ end }}}
|
||||
<span class="title-text">{posts.data.title}</span>
|
||||
<span data-action="editTitle" class="title-text">{posts.data.title}</span>
|
||||
</div>
|
||||
{{{if !posts.data.tid}}}
|
||||
<div class="topic-title-editable hidden">
|
||||
@@ -94,7 +94,7 @@
|
||||
<hr/>
|
||||
<div>
|
||||
<strong>[[post-queue:content]] <i class="fa fa-fw fa-edit" data-bs-toggle="tooltip" title="[[post-queue:content-editable]]"></i></strong>
|
||||
<div class="post-content text-break">{posts.data.content}</div>
|
||||
<div data-action="editContent" class="post-content text-break">{posts.data.content}</div>
|
||||
<div class="post-content-editable hidden">
|
||||
<textarea class="form-control w-100" style="height:300px;">{posts.data.rawContent}</textarea>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user