2026-07-07 13:35:18 -07:00
|
|
|
/**
|
|
|
|
|
* 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).
|
|
|
|
|
*/
|
|
|
|
|
|
2026-07-12 14:43:31 -07:00
|
|
|
import { escapeAttr, safeUrl, scopeId } from './escape';
|
2026-07-07 13:35:18 -07:00
|
|
|
|
|
|
|
|
export interface RelayWiring {
|
|
|
|
|
/** true when a recipient is set (relay path); false = legacy formAction fallback */
|
|
|
|
|
useRelay: boolean;
|
|
|
|
|
/** the `<!--WHP-FORM ...-->` 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 `<input>` 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
|
2026-07-12 14:43:31 -07:00
|
|
|
* @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).
|
2026-07-07 13:35:18 -07:00
|
|
|
*/
|
|
|
|
|
export function relayFormWiring(
|
|
|
|
|
recipientEmail: string | undefined,
|
|
|
|
|
thankYouUrl: string | undefined,
|
|
|
|
|
fallbackAction: string | undefined,
|
2026-07-12 14:43:31 -07:00
|
|
|
nodeId?: string,
|
2026-07-07 13:35:18 -07:00
|
|
|
): RelayWiring {
|
|
|
|
|
if (!recipientEmail) {
|
2026-07-12 12:05:57 -07:00
|
|
|
return { useRelay: false, marker: '', actionAttr: escapeAttr(safeUrl(fallbackAction || '#')), honeypot: '' };
|
2026-07-07 13:35:18 -07:00
|
|
|
}
|
2026-07-12 14:43:31 -07:00
|
|
|
const fid = scopeId(nodeId, `${recipientEmail}::${thankYouUrl || ''}::${fallbackAction || ''}`, 'F');
|
2026-07-07 13:35:18 -07:00
|
|
|
return {
|
|
|
|
|
useRelay: true,
|
2026-07-12 11:49:10 -07:00
|
|
|
marker: `<!--WHP-FORM id="${fid}" recipient="${escapeAttr(recipientEmail)}" thankyou="${escapeAttr(thankYouUrl || '')}"-->`,
|
2026-07-07 13:35:18 -07:00
|
|
|
actionAttr: `__WHP_FORM_ACTION__${fid}__`,
|
|
|
|
|
honeypot: `<input type="text" name="_gotcha" tabindex="-1" autocomplete="off" style="position:absolute;left:-9999px" aria-hidden="true">`,
|
|
|
|
|
};
|
|
|
|
|
}
|