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 */
}
.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 */
.sidebar-avatar-link {
flex-shrink: 0;
@@ -7886,6 +7912,7 @@ span.badge.badge-current {
text-decoration: underline;
}
.sidebar-comment-img.emoji {
width: auto;
display: inline-block;

View File

@@ -461,7 +461,7 @@ class CommentSystem {
const contentEl = el.querySelector('.comment-content');
if (contentEl) {
contentEl.innerHTML = this.renderCommentContent(data.content);
contentEl.innerHTML = this.renderCommentContent(data.content, data.comment_id);
// Flash effect to draw attention
el.classList.remove('new-item-fade');
@@ -1237,7 +1237,7 @@ class CommentSystem {
const contentEl = el.querySelector('.comment-content');
if (contentEl && contentEl.dataset.raw !== incoming.content) {
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;
}
@@ -1366,14 +1366,17 @@ class CommentSystem {
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 '';
// Anti-recursion / Performance safeguard for extremely long comments
if (content.length > 50000) {
console.warn('Comment too long, skipping markdown for performance');
// Use native escaping and <pre> to avoid all regex/marked overhead for huge strings
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>`;
// Truncate extremely long comments before any processing
let truncated = false;
if (!bypassTruncation && content.length > CommentSystem.ITEM_VIEW_MAX_CHARS) {
content = content.substring(0, CommentSystem.ITEM_VIEW_MAX_CHARS);
truncated = true;
}
if (typeof marked === 'undefined') {
@@ -1633,10 +1636,19 @@ class CommentSystem {
if (window.Sanitizer && typeof Sanitizer.clean === 'function') {
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;
} catch (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;
// 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();
// Admin buttons
@@ -2009,6 +2021,19 @@ class CommentSystem {
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)
const contextLink = target.closest('.comment-context-link');
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) => {
if (!content) return '';
// Anti-recursion / Performance safeguard for extremely long comments
if (content.length > 50000) {
console.warn('Sidebar Activity: Comment too long, skipping markdown');
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>`;
// Truncate extremely long comments before any processing to keep the sidebar
// fast and the DOM lean, regardless of markdown / regex complexity.
if (content.length > SIDEBAR_CONTENT_TRUNCATE) {
content = content.substring(0, SIDEBAR_CONTENT_TRUNCATE) + '\u2026';
}
if (typeof marked === 'undefined') {