/** * Shared contact-form relay wiring for HTML export. * * Any form component that wants to deliver submissions by email (ContactForm, * FormContainer, ...) emits the SAME marker/placeholder/honeypot shape so the * WHP publish step (`fs_rewrite_contact_forms`) can provision a token, rewrite * the action, and strip the marker. Keeping this in one place means the two * components can't drift apart (a drift would leak the recipient into published * HTML — see PR #47 review). */ import { escapeAttr, safeUrl, scopeId } from './escape'; export interface RelayWiring { /** true when a recipient is set (relay path); false = legacy formAction fallback */ useRelay: boolean; /** the `` marker (stripped at publish); '' when not relay */ marker: string; /** value for the form's `action` attribute (placeholder when relay, else the escaped fallback) */ actionAttr: string; /** hidden honeypot `` to render as the form's first child; '' when not relay */ honeypot: string; } /** * @param recipientEmail the "Send submissions to" address (empty/undefined = no relay) * @param thankYouUrl optional post-submit redirect (blank = hosted thank-you page) * @param fallbackAction the form's existing action to use when no recipient is set * @param nodeId the Craft node id of the calling form component, used to scope * the marker/placeholder id deterministically and uniquely -- * see `scopeId` in ./escape. Falls back to a stable hash of the * recipient/thankYouUrl/fallbackAction when omitted (never random). */ export function relayFormWiring( recipientEmail: string | undefined, thankYouUrl: string | undefined, fallbackAction: string | undefined, nodeId?: string, ): RelayWiring { if (!recipientEmail) { return { useRelay: false, marker: '', actionAttr: escapeAttr(safeUrl(fallbackAction || '#')), honeypot: '' }; } const fid = scopeId(nodeId, `${recipientEmail}::${thankYouUrl || ''}::${fallbackAction || ''}`, 'F'); return { useRelay: true, marker: ``, actionAttr: `__WHP_FORM_ACTION__${fid}__`, honeypot: ``, }; }