feat: hold the campaign preview request until writing settles, since HTML mode runs it from the Edit tab and a designed body is tens of kilobytes to ship on every 250ms pause, and treat a document sitting behind a leading comment as one when deciding whether to adopt a paste as HTML or to open an A/B arm as markup, because a saved email opens with the tool that wrote it before its doctype

This commit is contained in:
Matthew Meszaros
2026-09-09 06:39:23 -07:00
parent 2c1b5d8204
commit 7f2bfa252e
4 changed files with 20 additions and 3 deletions
@@ -120,6 +120,10 @@ export default function EmailContentEditor({
// notes below the editor come from it, and an author writing markup
// is exactly who needs them while they write.
if (tab !== "preview" && !code) return;
// Switching to Preview is a deliberate act and should feel immediate.
// Writing markup is not: the request carries the whole body, which for
// a designed email is tens of kilobytes, so it waits for a real pause.
const settle = tab === "preview" ? 250 : 800;
// Responses can land out of order; only the newest request may paint.
let active = true;
const t = setTimeout(() => {
@@ -140,7 +144,7 @@ export default function EmailContentEditor({
.catch(() => {
if (active) setServerPreview(null);
});
}, 250);
}, settle);
return () => {
active = false;
clearTimeout(t);
+1 -1
View File
@@ -50,7 +50,7 @@ const DOCUMENT_CSS = `
// designed newsletter) must not be nested inside another one: the doctype and
// the <head> would land in the body, and the frame would preview something the
// recipient will never see. Its own <head> gets our shell instead.
const DOCUMENT_ROOT = /^\s*(?:<!doctype\s+html|<html[\s>])/i;
const DOCUMENT_ROOT = /^\s*(?:<!--[\s\S]*?-->\s*)*(?:<!doctype\s+html|<html[\s>])/i;
const HEAD_OPEN = /<head\b[^>]*>/i;
const HTML_OPEN = /<html\b[^>]*>/i;