payload-plugin-newsletter 0.20.6 → 0.20.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +44 -0
- package/dist/admin.js +11 -1
- package/dist/collections.cjs +26 -2
- package/dist/collections.cjs.map +1 -1
- package/dist/collections.js +26 -2
- package/dist/collections.js.map +1 -1
- package/dist/server.d.ts +6 -4
- package/dist/server.js +26 -2
- package/dist/types.d.cts +8 -5
- package/dist/types.d.ts +8 -5
- package/dist/utils.cjs +2 -1
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.cts +2 -0
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +2 -1
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,47 @@
|
|
|
1
|
+
## [0.20.7] - 2025-08-02
|
|
2
|
+
|
|
3
|
+
### Added
|
|
4
|
+
- **Comprehensive Email Wrapper System** - Unified email rendering that uses the same wrapper for previews and actual sends
|
|
5
|
+
- Preview component now passes ALL form fields to the preview endpoint as `documentData`
|
|
6
|
+
- Custom wrappers receive complete document data, not just content
|
|
7
|
+
- Consistent HTML output between preview and actual email sends
|
|
8
|
+
- Support for accessing any custom fields added to broadcasts collection
|
|
9
|
+
- Wrapper is applied during actual send operations, not just previews
|
|
10
|
+
|
|
11
|
+
### Enhanced
|
|
12
|
+
- **Email Preview Component** - Builds document data from all form fields for wrapper access
|
|
13
|
+
- Collects all field values using `useFormFields` hook
|
|
14
|
+
- Passes complete form state to preview endpoint
|
|
15
|
+
- Enables custom wrappers to access metadata like slug, issueNumber, custom fields
|
|
16
|
+
|
|
17
|
+
- **Preview Endpoint** - Updated to accept and forward documentData to email wrapper
|
|
18
|
+
- Receives documentData from preview component
|
|
19
|
+
- Passes through to convertToEmailSafeHtml function
|
|
20
|
+
- Maintains backward compatibility with existing implementations
|
|
21
|
+
|
|
22
|
+
- **Email Wrapper Interface** - Enhanced type definitions for better developer experience
|
|
23
|
+
- Added `EmailWrapperOptions` interface with documentData support
|
|
24
|
+
- Updated `CustomEmailWrapper` type for consistency
|
|
25
|
+
- Generic `Record<string, any>` allows any custom fields
|
|
26
|
+
|
|
27
|
+
- **Broadcast Sync Hooks** - Now apply wrapper during actual email sends
|
|
28
|
+
- Create operation uses wrapper when syncing to provider
|
|
29
|
+
- Update operation maintains wrapper consistency
|
|
30
|
+
- Deferred creates (from draft to published) include wrapper
|
|
31
|
+
- Same HTML template used for both preview and actual sends
|
|
32
|
+
|
|
33
|
+
### Technical Changes
|
|
34
|
+
- Updated `convertToEmailSafeHtml` to accept documentData in options
|
|
35
|
+
- Modified all sync operations in Broadcasts collection to use email preview config
|
|
36
|
+
- Wrapper customization now available throughout the email lifecycle
|
|
37
|
+
- No breaking changes - wrapper remains optional with sensible defaults
|
|
38
|
+
|
|
39
|
+
### Benefits
|
|
40
|
+
- **Flexibility** - Users can pass any custom fields without plugin modifications
|
|
41
|
+
- **Consistency** - Identical HTML in preview and actual email sends
|
|
42
|
+
- **Future Proof** - Add new fields to broadcasts without updating plugin code
|
|
43
|
+
- **No Breaking Changes** - Existing implementations continue to work unchanged
|
|
44
|
+
|
|
1
45
|
## [0.20.6] - 2025-08-01
|
|
2
46
|
|
|
3
47
|
### Fixed
|
package/dist/admin.js
CHANGED
|
@@ -22,10 +22,20 @@ var BroadcastInlinePreview = () => {
|
|
|
22
22
|
setLoading(false);
|
|
23
23
|
return;
|
|
24
24
|
}
|
|
25
|
+
const documentData = {};
|
|
26
|
+
Object.entries(fields || {}).forEach(([key, field]) => {
|
|
27
|
+
if (field && typeof field === "object" && "value" in field) {
|
|
28
|
+
documentData[key] = field.value;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
25
31
|
const response = await fetch("/api/broadcasts/preview", {
|
|
26
32
|
method: "POST",
|
|
27
33
|
headers: { "Content-Type": "application/json" },
|
|
28
|
-
body: JSON.stringify({
|
|
34
|
+
body: JSON.stringify({
|
|
35
|
+
content: contentValue,
|
|
36
|
+
documentData
|
|
37
|
+
// Pass all form data
|
|
38
|
+
})
|
|
29
39
|
});
|
|
30
40
|
if (!response.ok) {
|
|
31
41
|
throw new Error(`Preview failed: ${response.statusText}`);
|
package/dist/collections.cjs
CHANGED
|
@@ -979,7 +979,8 @@ async function convertToEmailSafeHtml(editorState, options) {
|
|
|
979
979
|
if (options.customWrapper) {
|
|
980
980
|
return await Promise.resolve(options.customWrapper(sanitizedHtml, {
|
|
981
981
|
preheader: options.preheader,
|
|
982
|
-
subject: options.subject
|
|
982
|
+
subject: options.subject,
|
|
983
|
+
documentData: options.documentData
|
|
983
984
|
}));
|
|
984
985
|
}
|
|
985
986
|
return wrapInEmailTemplate(sanitizedHtml, options.preheader);
|
|
@@ -1866,7 +1867,7 @@ var createBroadcastPreviewEndpoint = (config, _collectionSlug) => {
|
|
|
1866
1867
|
handler: async (req) => {
|
|
1867
1868
|
try {
|
|
1868
1869
|
const data = await (req.json?.() || Promise.resolve({}));
|
|
1869
|
-
const { content, preheader, subject } = data;
|
|
1870
|
+
const { content, preheader, subject, documentData } = data;
|
|
1870
1871
|
if (!content) {
|
|
1871
1872
|
return Response.json({
|
|
1872
1873
|
success: false,
|
|
@@ -1882,6 +1883,8 @@ var createBroadcastPreviewEndpoint = (config, _collectionSlug) => {
|
|
|
1882
1883
|
preheader,
|
|
1883
1884
|
subject,
|
|
1884
1885
|
mediaUrl,
|
|
1886
|
+
documentData,
|
|
1887
|
+
// Pass all document data
|
|
1885
1888
|
customBlockConverter: config.customizations?.broadcasts?.customBlockConverter,
|
|
1886
1889
|
customWrapper: emailPreviewConfig?.customWrapper
|
|
1887
1890
|
});
|
|
@@ -2181,7 +2184,14 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
2181
2184
|
const provider = new BroadcastApiProvider2(providerConfig);
|
|
2182
2185
|
req.payload.logger.info("Populating media fields and converting content to HTML...");
|
|
2183
2186
|
const populatedContent = await populateMediaFields(doc.contentSection?.content, req.payload, pluginConfig);
|
|
2187
|
+
const emailPreviewConfig = pluginConfig.customizations?.broadcasts?.emailPreview;
|
|
2184
2188
|
const htmlContent = await convertToEmailSafeHtml(populatedContent, {
|
|
2189
|
+
wrapInTemplate: emailPreviewConfig?.wrapInTemplate ?? true,
|
|
2190
|
+
customWrapper: emailPreviewConfig?.customWrapper,
|
|
2191
|
+
preheader: doc.contentSection?.preheader,
|
|
2192
|
+
subject: doc.subject,
|
|
2193
|
+
documentData: doc,
|
|
2194
|
+
// Pass entire document
|
|
2185
2195
|
customBlockConverter: pluginConfig.customizations?.broadcasts?.customBlockConverter
|
|
2186
2196
|
});
|
|
2187
2197
|
if (!htmlContent || htmlContent.trim() === "") {
|
|
@@ -2281,7 +2291,14 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
2281
2291
|
}
|
|
2282
2292
|
req.payload.logger.info("Creating broadcast in provider (deferred from initial create)...");
|
|
2283
2293
|
const populatedContent = await populateMediaFields(doc.contentSection?.content, req.payload, pluginConfig);
|
|
2294
|
+
const emailPreviewConfig = pluginConfig.customizations?.broadcasts?.emailPreview;
|
|
2284
2295
|
const htmlContent = await convertToEmailSafeHtml(populatedContent, {
|
|
2296
|
+
wrapInTemplate: emailPreviewConfig?.wrapInTemplate ?? true,
|
|
2297
|
+
customWrapper: emailPreviewConfig?.customWrapper,
|
|
2298
|
+
preheader: doc.contentSection?.preheader,
|
|
2299
|
+
subject: doc.subject,
|
|
2300
|
+
documentData: doc,
|
|
2301
|
+
// Pass entire document
|
|
2285
2302
|
customBlockConverter: pluginConfig.customizations?.broadcasts?.customBlockConverter
|
|
2286
2303
|
});
|
|
2287
2304
|
if (!htmlContent || htmlContent.trim() === "") {
|
|
@@ -2343,7 +2360,14 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
2343
2360
|
}
|
|
2344
2361
|
if (JSON.stringify(doc.contentSection?.content) !== JSON.stringify(previousDoc?.contentSection?.content)) {
|
|
2345
2362
|
const populatedContent = await populateMediaFields(doc.contentSection?.content, req.payload, pluginConfig);
|
|
2363
|
+
const emailPreviewConfig = pluginConfig.customizations?.broadcasts?.emailPreview;
|
|
2346
2364
|
updates.content = await convertToEmailSafeHtml(populatedContent, {
|
|
2365
|
+
wrapInTemplate: emailPreviewConfig?.wrapInTemplate ?? true,
|
|
2366
|
+
customWrapper: emailPreviewConfig?.customWrapper,
|
|
2367
|
+
preheader: doc.contentSection?.preheader,
|
|
2368
|
+
subject: doc.subject,
|
|
2369
|
+
documentData: doc,
|
|
2370
|
+
// Pass entire document
|
|
2347
2371
|
customBlockConverter: pluginConfig.customizations?.broadcasts?.customBlockConverter
|
|
2348
2372
|
});
|
|
2349
2373
|
}
|