fix quoting
This commit is contained in:
@@ -3144,7 +3144,7 @@ body.layout-legacy .scroll-to-bottom svg {
|
|||||||
color: #888;
|
color: #888;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: flex-end;
|
align-items: flex-start;
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
gap: 2px 10px;
|
gap: 2px 10px;
|
||||||
@@ -3152,8 +3152,9 @@ body.layout-legacy .scroll-to-bottom svg {
|
|||||||
|
|
||||||
.comment-header-left {
|
.comment-header-left {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 5px;
|
gap: 2px 6px;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
flex-shrink: 1;
|
flex-shrink: 1;
|
||||||
}
|
}
|
||||||
@@ -3276,9 +3277,13 @@ body.layout-legacy .scroll-to-bottom svg {
|
|||||||
.comment-author {
|
.comment-author {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: var(--accent);
|
color: var(--accent);
|
||||||
margin-right: 8px;
|
margin-right: 2px;
|
||||||
padding-right: 0 !important;
|
padding-right: 0 !important;
|
||||||
word-break: break-word;
|
white-space: nowrap;
|
||||||
|
flex-shrink: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
.comment-time {
|
.comment-time {
|
||||||
@@ -3337,6 +3342,7 @@ body.layout-legacy .scroll-to-bottom svg {
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.comment-context-link:hover,
|
.comment-context-link:hover,
|
||||||
@@ -3400,10 +3406,7 @@ body.layout-legacy .scroll-to-bottom svg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.comment-backlinks {
|
.comment-backlinks {
|
||||||
display: inline-block;
|
display: contents;
|
||||||
font-size: 0.85em;
|
|
||||||
opacity: 0.8;
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.comments-header-actions {
|
.comments-header-actions {
|
||||||
|
|||||||
@@ -596,7 +596,7 @@ class CommentSystem {
|
|||||||
if (cached) cached.content = fullContent;
|
if (cached) cached.content = fullContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
contentEl.dataset.raw = this.escapeHtml(fullContent);
|
contentEl.dataset.raw = fullContent;
|
||||||
contentEl.innerHTML = this.renderCommentContent(fullContent, commentId);
|
contentEl.innerHTML = this.renderCommentContent(fullContent, commentId);
|
||||||
CommentSystem.autoplayConvertedGifs(contentEl);
|
CommentSystem.autoplayConvertedGifs(contentEl);
|
||||||
CommentSystem.playEmojiVideos(contentEl);
|
CommentSystem.playEmojiVideos(contentEl);
|
||||||
@@ -622,6 +622,7 @@ class CommentSystem {
|
|||||||
|
|
||||||
const contentEl = el.querySelector('.comment-content');
|
const contentEl = el.querySelector('.comment-content');
|
||||||
if (contentEl) {
|
if (contentEl) {
|
||||||
|
contentEl.dataset.raw = data.content;
|
||||||
contentEl.innerHTML = this.renderCommentContent(data.content, data.comment_id);
|
contentEl.innerHTML = this.renderCommentContent(data.content, data.comment_id);
|
||||||
CommentSystem.autoplayConvertedGifs(contentEl);
|
CommentSystem.autoplayConvertedGifs(contentEl);
|
||||||
CommentSystem.playEmojiVideos(contentEl);
|
CommentSystem.playEmojiVideos(contentEl);
|
||||||
@@ -1173,7 +1174,12 @@ class CommentSystem {
|
|||||||
const contentEl = body.querySelector('.comment-content');
|
const contentEl = body.querySelector('.comment-content');
|
||||||
if (contentEl) {
|
if (contentEl) {
|
||||||
const LINE_MAX = 200;
|
const LINE_MAX = 200;
|
||||||
const rawText = (contentEl.dataset.raw || '').trim();
|
let rawText = (contentEl.dataset.raw || '').trim();
|
||||||
|
if (rawText.includes('>') || rawText.includes('<') || rawText.includes('&')) {
|
||||||
|
const txt = document.createElement('textarea');
|
||||||
|
txt.innerHTML = rawText;
|
||||||
|
rawText = txt.value;
|
||||||
|
}
|
||||||
// Preserve all lines but cap any single line exceeding LINE_MAX chars
|
// Preserve all lines but cap any single line exceeding LINE_MAX chars
|
||||||
const lines = rawText.split('\n').map(line =>
|
const lines = rawText.split('\n').map(line =>
|
||||||
line.length > LINE_MAX ? line.substring(0, LINE_MAX) + '\u2026' : line
|
line.length > LINE_MAX ? line.substring(0, LINE_MAX) + '\u2026' : line
|
||||||
@@ -1794,7 +1800,7 @@ class CommentSystem {
|
|||||||
const renderedContent = quoteEmojis
|
const renderedContent = quoteEmojis
|
||||||
? quoteContent.replace(/:([a-z0-9_]+):/g, (m, n) => this.renderEmoji(m, n))
|
? quoteContent.replace(/:([a-z0-9_]+):/g, (m, n) => this.renderEmoji(m, n))
|
||||||
: quoteContent;
|
: quoteContent;
|
||||||
return `<span class="greentext">>${renderedContent}</span>`;
|
return `<span class="greentext">>${renderedContent.replace(/>/g, '>')}</span>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Per-line limit to prevent marked.parse recursion on single giant lines
|
// 2. Per-line limit to prevent marked.parse recursion on single giant lines
|
||||||
@@ -2199,7 +2205,7 @@ class CommentSystem {
|
|||||||
if (!unsafe) return '';
|
if (!unsafe) return '';
|
||||||
const div = document.createElement('div');
|
const div = document.createElement('div');
|
||||||
div.textContent = unsafe;
|
div.textContent = unsafe;
|
||||||
return div.innerHTML;
|
return div.innerHTML.replace(/"/g, '"').replace(/'/g, ''');
|
||||||
}
|
}
|
||||||
|
|
||||||
renderCommentAttachments(files, content = '') {
|
renderCommentAttachments(files, content = '') {
|
||||||
@@ -3336,9 +3342,15 @@ class CommentSystem {
|
|||||||
params.append('has_poll', '1');
|
params.append('has_poll', '1');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const csrfToken = window.f0ckSession?.csrf_token || '';
|
||||||
|
if (csrfToken) params.append('csrf_token', csrfToken);
|
||||||
|
|
||||||
const res = await fetch('/api/comments', {
|
const res = await fetch('/api/comments', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
...(csrfToken ? { 'X-CSRF-Token': csrfToken } : {})
|
||||||
|
},
|
||||||
body: params
|
body: params
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -2119,7 +2119,12 @@
|
|||||||
const contentEl = commentEl.querySelector('.comment-content');
|
const contentEl = commentEl.querySelector('.comment-content');
|
||||||
if (!contentEl) return;
|
if (!contentEl) return;
|
||||||
|
|
||||||
const raw = (contentEl.dataset.raw || '').replace(/<br\s*\/?>/gi, '\n').trim();
|
let raw = (contentEl.dataset.raw || '').replace(/<br\s*\/?>/gi, '\n').trim();
|
||||||
|
if (raw.includes('>') || raw.includes('<') || raw.includes('&')) {
|
||||||
|
const txt = document.createElement('textarea');
|
||||||
|
txt.innerHTML = raw;
|
||||||
|
raw = txt.value;
|
||||||
|
}
|
||||||
const lines = raw.split('\n');
|
const lines = raw.split('\n');
|
||||||
const quote = `>>${id}\n${lines.map(line => `>${line}`).join('\n')}\n`;
|
const quote = `>>${id}\n${lines.map(line => `>${line}`).join('\n')}\n`;
|
||||||
|
|
||||||
@@ -2787,11 +2792,16 @@
|
|||||||
if (!content || !commentsItemId || commentsPosting) return;
|
if (!content || !commentsItemId || commentsPosting) return;
|
||||||
commentsPosting = true; commentSendBtn.disabled = true;
|
commentsPosting = true; commentSendBtn.disabled = true;
|
||||||
try {
|
try {
|
||||||
|
const csrfToken = window.f0ckSession?.csrf_token || window.scrollerCsrf || '';
|
||||||
let postBody = `item_id=${commentsItemId}&content=${encodeURIComponent(content)}`;
|
let postBody = `item_id=${commentsItemId}&content=${encodeURIComponent(content)}`;
|
||||||
if (replyToCommentId) postBody += `&parent_id=${replyToCommentId}`;
|
if (replyToCommentId) postBody += `&parent_id=${replyToCommentId}`;
|
||||||
|
if (csrfToken) postBody += `&csrf_token=${encodeURIComponent(csrfToken)}`;
|
||||||
const resp = await fetch('/api/comments', {
|
const resp = await fetch('/api/comments', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
...(csrfToken ? { 'X-CSRF-Token': csrfToken } : {})
|
||||||
|
},
|
||||||
body: postBody
|
body: postBody
|
||||||
});
|
});
|
||||||
const data = await resp.json();
|
const data = await resp.json();
|
||||||
@@ -3658,7 +3668,11 @@
|
|||||||
if (sMarkAll) {
|
if (sMarkAll) {
|
||||||
sMarkAll.addEventListener('click', async () => {
|
sMarkAll.addEventListener('click', async () => {
|
||||||
try {
|
try {
|
||||||
await fetch('/api/notifications/read', { method: 'POST' });
|
const csrfToken = window.f0ckSession?.csrf_token || window.scrollerCsrf || '';
|
||||||
|
await fetch('/api/notifications/read', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { ...(csrfToken ? { 'X-CSRF-Token': csrfToken } : {}) }
|
||||||
|
});
|
||||||
updateScrollerNotifBadge(0);
|
updateScrollerNotifBadge(0);
|
||||||
sCachedNotifs = sCachedNotifs.map(n => ({ ...n, is_read: true }));
|
sCachedNotifs = sCachedNotifs.map(n => ({ ...n, is_read: true }));
|
||||||
updateScrollerTabBadges(sCachedNotifs);
|
updateScrollerTabBadges(sCachedNotifs);
|
||||||
@@ -3673,7 +3687,12 @@
|
|||||||
if (!item) return;
|
if (!item) return;
|
||||||
const nid = item.dataset.id;
|
const nid = item.dataset.id;
|
||||||
if (nid && item.classList.contains('unread')) {
|
if (nid && item.classList.contains('unread')) {
|
||||||
fetch(`/api/notifications/${nid}/read`, { method: 'POST', keepalive: true }).catch(() => {});
|
const csrfToken = window.f0ckSession?.csrf_token || window.scrollerCsrf || '';
|
||||||
|
fetch(`/api/notifications/${nid}/read`, {
|
||||||
|
method: 'POST',
|
||||||
|
keepalive: true,
|
||||||
|
headers: { ...(csrfToken ? { 'X-CSRF-Token': csrfToken } : {}) }
|
||||||
|
}).catch(() => {});
|
||||||
item.classList.remove('unread');
|
item.classList.remove('unread');
|
||||||
// Update cache
|
// Update cache
|
||||||
const cached = sCachedNotifs.find(n => String(n.id) === String(nid));
|
const cached = sCachedNotifs.find(n => String(n.id) === String(nid));
|
||||||
|
|||||||
@@ -47,7 +47,7 @@
|
|||||||
if (!unsafe) return '';
|
if (!unsafe) return '';
|
||||||
const div = document.createElement('div');
|
const div = document.createElement('div');
|
||||||
div.textContent = unsafe;
|
div.textContent = unsafe;
|
||||||
return div.innerHTML;
|
return div.innerHTML.replace(/"/g, '"').replace(/'/g, ''');
|
||||||
};
|
};
|
||||||
|
|
||||||
const playSidebarEmojiVideos = (container) => {
|
const playSidebarEmojiVideos = (container) => {
|
||||||
@@ -271,7 +271,7 @@
|
|||||||
const rendered = quoteEmojis
|
const rendered = quoteEmojis
|
||||||
? quoteContent.replace(/:([a-z0-9_]+):/g, (m, n) => renderEmoji(m, n))
|
? quoteContent.replace(/:([a-z0-9_]+):/g, (m, n) => renderEmoji(m, n))
|
||||||
: quoteContent;
|
: quoteContent;
|
||||||
return `<span class="greentext">>${rendered}</span>`;
|
return `<span class="greentext">>${rendered.replace(/>/g, '>')}</span>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Per-line limit to prevent marked.parse recursion on single giant lines
|
// Per-line limit to prevent marked.parse recursion on single giant lines
|
||||||
|
|||||||
@@ -306,7 +306,7 @@ if (!window.UserCommentSystem) {
|
|||||||
const trimmed = line.trimStart();
|
const trimmed = line.trimStart();
|
||||||
if (trimmed.startsWith('>') && !trimmed.match(/^>>\d+/)) {
|
if (trimmed.startsWith('>') && !trimmed.match(/^>>\d+/)) {
|
||||||
const quoteContent = line.substring(line.indexOf('>') + 1);
|
const quoteContent = line.substring(line.indexOf('>') + 1);
|
||||||
return `<span class="greentext">>${quoteContent}</span>`;
|
return `<span class="greentext">>${quoteContent.replace(/>/g, '>')}</span>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Per-line limit
|
// Per-line limit
|
||||||
@@ -450,7 +450,7 @@ if (!window.UserCommentSystem) {
|
|||||||
if (!unsafe) return '';
|
if (!unsafe) return '';
|
||||||
const div = document.createElement('div');
|
const div = document.createElement('div');
|
||||||
div.textContent = unsafe;
|
div.textContent = unsafe;
|
||||||
return div.innerHTML;
|
return div.innerHTML.replace(/"/g, '"').replace(/'/g, ''');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user