truncate really long comments by default to keep side speedy!

This commit is contained in:
2026-05-14 13:36:09 +02:00
parent f386287421
commit f43f2d72ca
3 changed files with 70 additions and 15 deletions

View File

@@ -1925,6 +1925,32 @@ body.sidebar-right-hidden .global-sidebar-right {
/* Hidden by default, shown via JS if overflow detected */ /* Hidden by default, shown via JS if overflow detected */
} }
.item-comment-truncated-notice {
display: block;
margin-top: 8px;
font-size: 0.85em;
color: #666;
}
.load-full-comment-btn {
background: none;
border: none;
padding: 0;
color: var(--accent);
font-size: inherit;
font-family: inherit;
cursor: pointer;
opacity: 0.85;
text-decoration: underline;
text-underline-offset: 2px;
transition: opacity 0.15s;
}
.load-full-comment-btn:hover {
opacity: 1;
}
/* Avatar in sidebar activity */ /* Avatar in sidebar activity */
.sidebar-avatar-link { .sidebar-avatar-link {
flex-shrink: 0; flex-shrink: 0;
@@ -7886,6 +7912,7 @@ span.badge.badge-current {
text-decoration: underline; text-decoration: underline;
} }
.sidebar-comment-img.emoji { .sidebar-comment-img.emoji {
width: auto; width: auto;
display: inline-block; display: inline-block;

View File

@@ -461,7 +461,7 @@ class CommentSystem {
const contentEl = el.querySelector('.comment-content'); const contentEl = el.querySelector('.comment-content');
if (contentEl) { if (contentEl) {
contentEl.innerHTML = this.renderCommentContent(data.content); contentEl.innerHTML = this.renderCommentContent(data.content, data.comment_id);
// Flash effect to draw attention // Flash effect to draw attention
el.classList.remove('new-item-fade'); el.classList.remove('new-item-fade');
@@ -1237,7 +1237,7 @@ class CommentSystem {
const contentEl = el.querySelector('.comment-content'); const contentEl = el.querySelector('.comment-content');
if (contentEl && contentEl.dataset.raw !== incoming.content) { if (contentEl && contentEl.dataset.raw !== incoming.content) {
window.f0ckDebug(`[CommentSystem] Reconcile: Updating content for #c${id}`); window.f0ckDebug(`[CommentSystem] Reconcile: Updating content for #c${id}`);
contentEl.innerHTML = this.renderCommentContent(incoming.content); contentEl.innerHTML = this.renderCommentContent(incoming.content, incoming.id);
contentEl.dataset.raw = incoming.content; contentEl.dataset.raw = incoming.content;
} }
@@ -1366,14 +1366,17 @@ class CommentSystem {
syncLevel(roots, list, false); syncLevel(roots, list, false);
} }
renderCommentContent(content) { // Maximum characters to fully render in the item view per comment
static get ITEM_VIEW_MAX_CHARS() { return 10000; }
renderCommentContent(content, commentId = null, bypassTruncation = false) {
if (!content) return ''; if (!content) return '';
// Anti-recursion / Performance safeguard for extremely long comments // Truncate extremely long comments before any processing
if (content.length > 50000) { let truncated = false;
console.warn('Comment too long, skipping markdown for performance'); if (!bypassTruncation && content.length > CommentSystem.ITEM_VIEW_MAX_CHARS) {
// Use native escaping and <pre> to avoid all regex/marked overhead for huge strings content = content.substring(0, CommentSystem.ITEM_VIEW_MAX_CHARS);
return `<pre style="white-space: pre-wrap; font-family: inherit; margin: 0; padding: 0; background: none; border: none; font-size: inherit; color: inherit;">${this.escapeHtml(content)}</pre>`; truncated = true;
} }
if (typeof marked === 'undefined') { if (typeof marked === 'undefined') {
@@ -1633,10 +1636,19 @@ class CommentSystem {
if (window.Sanitizer && typeof Sanitizer.clean === 'function') { if (window.Sanitizer && typeof Sanitizer.clean === 'function') {
md = Sanitizer.clean(md); md = Sanitizer.clean(md);
} }
if (truncated) {
md += `<span class="item-comment-truncated-notice">… <button class="load-full-comment-btn" type="button">show full comment</button></span>`;
}
return md; return md;
} catch (e) { } catch (e) {
console.error('Markdown error:', e); console.error('Markdown error:', e);
return this.escapeHtml(content); let fallback = this.escapeHtml(content);
if (truncated) {
fallback += ` <span class="item-comment-truncated-notice">… <button class="load-full-comment-btn" type="button">show full comment</button></span>`;
}
return fallback;
} }
} }
@@ -1722,7 +1734,7 @@ class CommentSystem {
const isPinned = comment.is_pinned; const isPinned = comment.is_pinned;
// Add @mention prefix if this is a reply to a reply // Add @mention prefix if this is a reply to a reply
const content = isDeleted ? '<span class="deleted-msg">[deleted]</span>' : this.renderCommentContent(comment.content); const content = isDeleted ? '<span class="deleted-msg">[deleted]</span>' : this.renderCommentContent(comment.content, comment.id);
const date = new Date(comment.created_at).toLocaleString(); const date = new Date(comment.created_at).toLocaleString();
// Admin buttons // Admin buttons
@@ -2009,6 +2021,19 @@ class CommentSystem {
return; return;
} }
// Load full comment (expand truncated)
const loadFullBtn = target.closest('.load-full-comment-btn');
if (loadFullBtn) {
const contentEl = loadFullBtn.closest('.comment-content');
if (contentEl) {
const fullContent = contentEl.dataset.raw;
if (fullContent) {
contentEl.innerHTML = this.renderCommentContent(fullContent, null, true);
}
}
return;
}
// Comment Context Link (>>ID) // Comment Context Link (>>ID)
const contextLink = target.closest('.comment-context-link'); const contextLink = target.closest('.comment-context-link');
if (contextLink) { if (contextLink) {

View File

@@ -86,13 +86,16 @@
} }
}; };
// Maximum characters to render in the sidebar per comment
const SIDEBAR_CONTENT_TRUNCATE = 200;
const renderCommentContent = (content, commentId = null, itemId = null) => { const renderCommentContent = (content, commentId = null, itemId = null) => {
if (!content) return ''; if (!content) return '';
// Anti-recursion / Performance safeguard for extremely long comments // Truncate extremely long comments before any processing to keep the sidebar
if (content.length > 50000) { // fast and the DOM lean, regardless of markdown / regex complexity.
console.warn('Sidebar Activity: Comment too long, skipping markdown'); if (content.length > SIDEBAR_CONTENT_TRUNCATE) {
return `<pre style="white-space: pre-wrap; font-family: inherit; margin: 0; padding: 0; background: none; border: none; font-size: inherit; color: inherit;">${escapeHtml(content)}</pre>`; content = content.substring(0, SIDEBAR_CONTENT_TRUNCATE) + '\u2026';
} }
if (typeof marked === 'undefined') { if (typeof marked === 'undefined') {