fix(editor): repaint existing links when the theme link style changes
Problem
Changing the theme's link color (for example with setGlobalStyles from the global inspector) left existing links in the editor on the old color until a reload. Exported HTML was already correct, so only the live editor display was wrong. This is the upstream fix for the @react-email/editor pnpm patch in resend/resend-monorepo#11930.
Cause
Since #3418, the Link mark's renderHTML inlines the resolved theme link style into each <a class="node-link">. ProseMirror only re-creates a mark's DOM when the mark's attrs change. A theme change doesn't touch link attrs, so the inlined color goes stale. The EmailTheming plugin already injects the same style as scoped .node-link CSS, and that CSS updates live.
Fix
The Link mark now has a mark view (addMarkView). ProseMirror uses mark views only for the live editor DOM.
- Live editor: the mark view renders the
<a>without the theme style, so the live theme CSS paints it. A link's ownstyle(for example a per-link color) stays inline and still wins. If thethemingextension isn't registered, there's no live theme CSS, so the mark view keeps inlining the theme style as before. - Serialization:
renderHTMLstill inlines the theme style, sogetHTML()and copied HTML keep themed links through Visual → HTML → Visual round trips. That's the contract #3418 added andlink.spec.tscovers. - Email export: unchanged. It resolves link styles through
getNodeStylesand the EmailMark renderer.
Both paths build the <a> with one shared renderLinkSpec helper.
The monorepo patch removed the inline theme style from renderHTML entirely. That would also drop link colors from getHTML(), which is why this PR uses a mark view instead.
Tests
New tests in link.spec.ts mount the editor into the document. They check that:
- an existing link's computed color follows a
setGlobalStyleslink color change; - a link with its own color keeps it;
- the live
<a>doesn't carry the theme inline style; getHTML()serializes the new theme color.
Without the mark view, the repaint test fails with the stale #0670db.
vitest --project unit: 54 files, 524 tests pass.vitest --project browser: 4 files, 19 tests pass.tsc --noEmitandbiome checkare clean.- I also ran a throwaway Chromium test (not committed) covering the theme color change, the per-link color, typing inside a link, unlink and re-link. The live colors were right throughout.


Summary by cubic
Fixes the live editor so existing links repaint immediately when the theme link style changes, instead of keeping the old color until a reload.
- The Link mark now has a mark view (
addMarkView) that renders live<a>elements without the inlined theme style, so the EmailTheming plugin's scoped.node-linkCSS paints them and updates live; without thethemingextension, the mark view falls back to inlining the theme style as before. renderHTMLstill inlines the theme style, keeping themed links ingetHTML()and copied HTML; email export is unchanged. Both paths share arenderLinkSpechelper.- New tests in
link.spec.tsmount the editor into the document and verify live repaint onsetGlobalStyles, per-link color precedence, live DOM output, andgetHTML()serialization.