Preserve HTML email quote history

This commit is contained in:
pewdiepie-archdaemon
2026-06-30 12:48:47 +00:00
parent 0cdbdf4186
commit 6127e43113
3 changed files with 42 additions and 4 deletions
+3 -3
View File
@@ -219,8 +219,8 @@
}, { once: true });
})();
</script>
<link rel="stylesheet" href="/static/style.css?v=20260630modelfallback">
<link rel="modulepreload" href="/static/app.js?v=20260630modelfallback">
<link rel="stylesheet" href="/static/style.css?v=20260630emailhtmlquote">
<link rel="modulepreload" href="/static/app.js?v=20260630emailhtmlquote">
<link rel="modulepreload" href="/static/js/chat.js">
<link rel="modulepreload" href="/static/js/ui.js">
<link rel="modulepreload" href="/static/js/sessions.js">
@@ -2512,7 +2512,7 @@
<script type="module" src="/static/js/settings.js"></script>
<script type="module" src="/static/js/admin.js"></script>
<script type="module" src="/static/js/assistant.js"></script>
<script type="module" src="/static/app.js?v=20260630modelfallback"></script> <!-- app.js must be LAST -->
<script type="module" src="/static/app.js?v=20260630emailhtmlquote"></script> <!-- app.js must be LAST -->
<script type="module" src="/static/js/init.js"></script>
<script type="module" src="/static/js/a11y.js"></script>
<script nonce="{{CSP_NONCE}}">if('serviceWorker' in navigator){navigator.serviceWorker.register('/static/sw.js').catch(()=>{});}</script>
+38
View File
@@ -2588,9 +2588,47 @@ import { bindMenuDismiss, dismissOrRemove } from './escMenuStack.js';
return -1;
}
function _emailQuoteStartOffset(text) {
const original = String(text || '');
if (!original) return -1;
const boundary = String.raw`(?:^|\n|<br\s*\/?>|<\/(?:p|div|blockquote|li|tr|h[1-6])>)`;
const patterns = [
new RegExp(`${boundary}\\s*(?:[-_=–—\\s]|&nbsp;){3,}(?:previous|original|forwarded)\\s+(?:message|email|mail)(?:[-_=–—\\s]|&nbsp;){3,}`, 'i'),
new RegExp(`${boundary}\\s*On\\s+.{1,700}?\\s+wrote:\\s*`, 'i'),
new RegExp(`${boundary}\\s*-{2,}\\s*Original Message\\s*-{2,}`, 'i'),
];
let best = -1;
for (const re of patterns) {
const m = re.exec(original);
if (!m) continue;
let idx = m.index;
const prefix = m[0].match(/^(?:\n|<br\s*\/?>|<\/(?:p|div|blockquote|li|tr|h[1-6])>)/i);
if (prefix) idx += prefix[0].length;
if (best < 0 || idx < best) best = idx;
}
const fromRe = new RegExp(`${boundary}\\s*From:\\s*\\S`, 'i');
const fromMatch = fromRe.exec(original);
if (fromMatch) {
let idx = fromMatch.index;
const prefix = fromMatch[0].match(/^(?:\n|<br\s*\/?>|<\/(?:p|div|blockquote|li|tr|h[1-6])>)/i);
if (prefix) idx += prefix[0].length;
const nearby = original.slice(idx, idx + 1200);
if (/(?:^|\n|<br\s*\/?>|<\/(?:p|div|blockquote|li|tr|h[1-6])>)\s*(?:To|Subject):\s*/i.test(nearby)) {
if (best < 0 || idx < best) best = idx;
}
}
return best;
}
function _splitEmailReplyQuote(text) {
const original = String(text || '');
if (!original) return { body: '', quote: '', stripped: false };
const htmlQuoteOffset = _emailQuoteStartOffset(original);
if (htmlQuoteOffset >= 0) {
const body = original.slice(0, htmlQuoteOffset).trim();
const quote = original.slice(htmlQuoteOffset).trim();
return { body, quote, stripped: true };
}
const lines = original.split('\n');
const quoteIdx = _emailQuoteStartIndex(lines);
if (quoteIdx < 0) return { body: original.trim(), quote: '', stripped: false };
+1 -1
View File
@@ -7,7 +7,7 @@
// - Other static assets (images/fonts/libs): cache-first with bg refresh.
// - API / non-GET: never cached.
// Bump CACHE_NAME whenever the precache list or SW logic changes.
const CACHE_NAME = 'odysseus-v334';
const CACHE_NAME = 'odysseus-v335';
// Core shell precached on install so repeat opens are instant without any
// network wait. Keep this list in sync with the <script type="module"> tags