pagepilot-visual-editor 1.0.8 → 1.0.9
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/README.md +90 -1
- package/dist/editor/renderSections.d.ts +68 -0
- package/dist/editor-sample/App/InspectorDrawer/LayoutPanel/templateApplyHelpers.d.ts +25 -0
- package/dist/index.cjs +214 -210
- package/dist/index.d.ts +2 -0
- package/dist/index.js +13275 -12947
- package/dist/renderToStaticHtml.d.ts +107 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -935,6 +935,90 @@ import { Reader, renderToStaticMarkup } from "pagepilot-visual-editor";
|
|
|
935
935
|
const html = renderToStaticMarkup(myDoc, { rootBlockId: "root" });
|
|
936
936
|
```
|
|
937
937
|
|
|
938
|
+
### `renderToStaticHtml(CONFIGURATION, options)`
|
|
939
|
+
|
|
940
|
+
Higher-level renderer that always runs through the **same code path** the editor uses on Save Changes / Publish: bake formFields, sanitize block types this build doesn't know about (e.g. `Mdx` → `Text`), then call `renderToStaticMarkup`. One function, three call shapes — the first is sync, the API-backed shapes return a `Promise<string>`.
|
|
941
|
+
|
|
942
|
+
**1. Sync — render a document you already have in memory**
|
|
943
|
+
|
|
944
|
+
```ts
|
|
945
|
+
import { renderToStaticHtml } from "pagepilot-visual-editor";
|
|
946
|
+
|
|
947
|
+
const generatedHtml = renderToStaticHtml(CONFIGURATION, {
|
|
948
|
+
rootBlockId: "root",
|
|
949
|
+
});
|
|
950
|
+
```
|
|
951
|
+
|
|
952
|
+
- `CONFIGURATION` is the document tree (`{ root: { type: "EmailLayout", … }, "block-…": {…} }`) — the same shape stored on `contentMetadata.document`.
|
|
953
|
+
- Any `{{token}}`s in the doc are resolved automatically using `document.root.data.formFields`; unknown block types are coerced to `Text` blocks that carry the original `props.html` / `props.text` / `props.markdown`.
|
|
954
|
+
|
|
955
|
+
**2. Async — fetch a page from the pagepilot API and render every section**
|
|
956
|
+
|
|
957
|
+
```ts
|
|
958
|
+
const generatedHtml = await renderToStaticHtml(CONFIGURATION, {
|
|
959
|
+
rootBlockId: "root",
|
|
960
|
+
pageId, // required — page `_id`
|
|
961
|
+
baseUrl, // e.g. "https://pagepilot.fabbuilder.com/api"
|
|
962
|
+
tenantId, // required
|
|
963
|
+
authToken, // optional bearer for private pages
|
|
964
|
+
});
|
|
965
|
+
```
|
|
966
|
+
|
|
967
|
+
- `GET ${baseUrl}/tenant/${tenantId}/page/${pageId}`.
|
|
968
|
+
- Every section's `contentMetadata.document` is baked (with its own `formFields`) and re-rendered — the stored `section.content` HTML is **never reused**.
|
|
969
|
+
- Multi-section pages are wrapped in a `<!doctype html>` shell (viewport meta, body background/font from the first internal section's EmailLayout). Pass `wrapInDocumentShell: false` to get bare fragments instead.
|
|
970
|
+
- `CONFIGURATION` acts as a fallback if the API returns no sections.
|
|
971
|
+
|
|
972
|
+
**3. Async — fetch a template, override `variables`, render**
|
|
973
|
+
|
|
974
|
+
```ts
|
|
975
|
+
const generatedHtml = await renderToStaticHtml({}, {
|
|
976
|
+
rootBlockId: "root",
|
|
977
|
+
templateId, // required — template `_id`
|
|
978
|
+
baseUrl,
|
|
979
|
+
tenantId, // needed unless `isGlobal: true`
|
|
980
|
+
authToken, // optional (skipped when `isGlobal: true`)
|
|
981
|
+
isGlobal: false, // true → GET /global-template/:templateId (public, no auth)
|
|
982
|
+
variables: { fname: "Ishaan", ctaText: "Book Now" },
|
|
983
|
+
});
|
|
984
|
+
```
|
|
985
|
+
|
|
986
|
+
- **`isGlobal: false`** (default): `GET ${baseUrl}/tenant/${tenantId}/template/${templateId}` with the bearer token.
|
|
987
|
+
- **`isGlobal: true`**: `GET ${baseUrl}/global-template/${templateId}` — public endpoint, no auth header sent.
|
|
988
|
+
- `variables` accepts two shapes:
|
|
989
|
+
- Flat map — `{ fieldId: value }`. Values are stringified. Ids not on the template are appended as text fields, so `{{fname}}` still substitutes even if the template's authors never declared a `fname` field.
|
|
990
|
+
- Array of formField objects — `[{ id, name, type, value, itemFields?, sourceBlockId?, rowIds? }, …]`. Each entry deep-merges onto the template's existing field with the same `id`, so you can override array/repeatable fields (`fabFaqs`, etc.) end-to-end, not just their scalar `value`.
|
|
991
|
+
- Template envelope shapes handled: flat `configuration.root`, page-envelope `configuration.content.contentMetadata.document`, older `configuration.contentMetadata.document`, and `isIndividualBlock` block templates (a synthetic `EmailLayout` root is generated around `configuration.rootBlockId`).
|
|
992
|
+
|
|
993
|
+
**All options**
|
|
994
|
+
|
|
995
|
+
```ts
|
|
996
|
+
type RenderToStaticHtmlOptions = {
|
|
997
|
+
rootBlockId?: string; // "root"
|
|
998
|
+
injectElementIds?: boolean; // true — emits `id="ahd-<blockId>"`
|
|
999
|
+
minifyCss?: boolean; // true
|
|
1000
|
+
includePageCSS?: boolean; // true
|
|
1001
|
+
lang?: string; // falls back to document.root.data.lang
|
|
1002
|
+
skipLink?: TSkipLink; // falls back to root.data.skipLink
|
|
1003
|
+
accessibilityTools?: TA11yTools; // falls back to root.data.accessibilityTools
|
|
1004
|
+
injectTabsScrollSyncScript?: boolean; // true when the doc has a Tabs block
|
|
1005
|
+
injectCarouselScript?: boolean; // true when the doc has a Carousel block
|
|
1006
|
+
injectFontAssets?: boolean; // banners only
|
|
1007
|
+
seo?: TSeo;
|
|
1008
|
+
headHtml?: string; // appended before </head>
|
|
1009
|
+
bodyBottomHtml?: string; // appended before </body>
|
|
1010
|
+
isBanner?: boolean;
|
|
1011
|
+
// Page-only:
|
|
1012
|
+
pageId?: string; tenantId?: string; baseUrl?: string; authToken?: string;
|
|
1013
|
+
wrapInDocumentShell?: boolean; // true — set false to get raw fragments
|
|
1014
|
+
// Template-only:
|
|
1015
|
+
templateId?: string; isGlobal?: boolean;
|
|
1016
|
+
variables?: Record<string, string | number | boolean | null | undefined>
|
|
1017
|
+
| Array<Partial<TemplateFormField>>;
|
|
1018
|
+
fetchFn?: typeof fetch; // custom fetch for Node < 18 / tracing
|
|
1019
|
+
};
|
|
1020
|
+
```
|
|
1021
|
+
|
|
938
1022
|
---
|
|
939
1023
|
|
|
940
1024
|
## Exports
|
|
@@ -955,7 +1039,8 @@ export {
|
|
|
955
1039
|
// Reader / renderer
|
|
956
1040
|
export {
|
|
957
1041
|
Reader, ReaderBlock,
|
|
958
|
-
renderToStaticMarkup,
|
|
1042
|
+
renderToStaticMarkup, // low-level React → HTML string
|
|
1043
|
+
renderToStaticHtml, // high-level: bake + sanitize + render, also fetches page / template from the API
|
|
959
1044
|
ReaderBlockSchema, ReaderDocumentSchema,
|
|
960
1045
|
} from "pagepilot-visual-editor";
|
|
961
1046
|
|
|
@@ -972,6 +1057,10 @@ export type {
|
|
|
972
1057
|
BlockKey, BlockToggles,
|
|
973
1058
|
PagepilotApiConfig, ListParams, PageListRow, PageListResponse,
|
|
974
1059
|
TReaderBlock, TReaderDocument, TReaderBlockProps, TReaderProps,
|
|
1060
|
+
RenderToStaticHtmlOptions,
|
|
1061
|
+
RenderToStaticHtmlSyncOptions,
|
|
1062
|
+
RenderToStaticHtmlPageOptions,
|
|
1063
|
+
RenderToStaticHtmlTemplateOptions,
|
|
975
1064
|
} from "pagepilot-visual-editor";
|
|
976
1065
|
```
|
|
977
1066
|
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export interface SectionForRender {
|
|
2
|
+
sectionType?: "internal" | "external" | string;
|
|
3
|
+
content?: string;
|
|
4
|
+
contentMetadata?: {
|
|
5
|
+
document?: any;
|
|
6
|
+
[key: string]: any;
|
|
7
|
+
};
|
|
8
|
+
[key: string]: any;
|
|
9
|
+
}
|
|
10
|
+
export interface RenderDocumentForSaveOptions {
|
|
11
|
+
rootBlockId?: string;
|
|
12
|
+
injectTabsScrollSyncScript?: boolean;
|
|
13
|
+
injectCarouselScript?: boolean;
|
|
14
|
+
injectFontAssets?: boolean;
|
|
15
|
+
headHtml?: string;
|
|
16
|
+
bodyBottomHtml?: string;
|
|
17
|
+
isBanner?: boolean;
|
|
18
|
+
seo?: any;
|
|
19
|
+
}
|
|
20
|
+
export declare function isExternalSection(section: SectionForRender | undefined): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Same call `Shell.buildPayload` makes: `renderToStaticMarkup` with the
|
|
23
|
+
* defaults the editor persists on Save Changes (root id, ids injected,
|
|
24
|
+
* page CSS included, css minified, lang / skipLink / accessibilityTools
|
|
25
|
+
* auto-derived from the document's root data).
|
|
26
|
+
*/
|
|
27
|
+
export declare function renderDocumentForSave(document: any, options?: RenderDocumentForSaveOptions): string;
|
|
28
|
+
export interface CombineSectionsOptions extends RenderDocumentForSaveOptions {
|
|
29
|
+
/**
|
|
30
|
+
* External sections come from the API as stored `content` strings —
|
|
31
|
+
* usually `<div id="…"></div>` anchor placeholders. When true (default),
|
|
32
|
+
* that content is passed through. When false, external sections are
|
|
33
|
+
* skipped entirely.
|
|
34
|
+
*/
|
|
35
|
+
includeExternalSections?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* When false, only the concatenated fragments are returned — no
|
|
38
|
+
* `<!doctype html>` shell. Defaults to true, matching Shell.buildPayload.
|
|
39
|
+
*/
|
|
40
|
+
wrapInDocumentShell?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Overrides for the outer shell. When omitted, values come from the
|
|
43
|
+
* first internal section's EmailLayout root data.
|
|
44
|
+
*/
|
|
45
|
+
lang?: string;
|
|
46
|
+
canvasColor?: string;
|
|
47
|
+
fontFamily?: string;
|
|
48
|
+
seoTitle?: string;
|
|
49
|
+
seoDescription?: string;
|
|
50
|
+
extraHead?: string;
|
|
51
|
+
extraBodyBottom?: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Render each section's document to a fragment, then stitch them into the
|
|
55
|
+
* same `<!doctype html>` shell Shell.tsx uses on Save Changes.
|
|
56
|
+
*
|
|
57
|
+
* Returns `{ html, sectionHtml, flushedSections }`:
|
|
58
|
+
* - `html`: combined document (or bare fragments when `wrapInDocumentShell` is false).
|
|
59
|
+
* - `sectionHtml`: per-section fragments in input order.
|
|
60
|
+
* - `flushedSections`: input sections with their re-rendered `content` field
|
|
61
|
+
* written back — matches the shape `Shell.buildPayload` persists in
|
|
62
|
+
* `SaveChangesPayload.record.sections`.
|
|
63
|
+
*/
|
|
64
|
+
export declare function combineSectionsToHtml(sections: SectionForRender[], options?: CombineSectionsOptions): {
|
|
65
|
+
html: string;
|
|
66
|
+
sectionHtml: string[];
|
|
67
|
+
flushedSections: SectionForRender[];
|
|
68
|
+
};
|
|
@@ -12,6 +12,31 @@
|
|
|
12
12
|
* - Legacy `templateRecord.formFields` mirror at the record root.
|
|
13
13
|
*/
|
|
14
14
|
export declare function resolveTemplateFormFields(templateRecord: any): any[];
|
|
15
|
+
/**
|
|
16
|
+
* Unwrap a saved template `configuration` down to the raw
|
|
17
|
+
* `{ root, "block-…" }` document tree the renderer / editor expect.
|
|
18
|
+
*
|
|
19
|
+
* The standalone editor is a **page-only** surface, so this helper only
|
|
20
|
+
* knows the page-shaped envelopes. Ordered by frequency, matches the
|
|
21
|
+
* `PageTypes.Page` branch of ahd-fe's `normalizeTemplateConfiguration`
|
|
22
|
+
* plus the block-template synthesis path:
|
|
23
|
+
*
|
|
24
|
+
* 1. `configuration.root` — flat document tree (legacy / tenant templates,
|
|
25
|
+
* most global page templates the backend serves today).
|
|
26
|
+
* 2. `configuration.isIndividualBlock` block template — no root exists;
|
|
27
|
+
* synthesize a minimal EmailLayout that hosts `configuration.rootBlockId`
|
|
28
|
+
* so the standalone renderer has something to walk. `formFields` on
|
|
29
|
+
* the configuration wrapper are hoisted onto the synthetic root's
|
|
30
|
+
* `data.formFields` so `bakeTemplateValues` finds them via the usual
|
|
31
|
+
* `getTemplateForms(document)` path.
|
|
32
|
+
* 3. `configuration.content.contentMetadata.document` — the page envelope
|
|
33
|
+
* the backend uses for page-derived global templates (CyberSecurity Page).
|
|
34
|
+
* 4. `configuration.contentMetadata.document` — one-off older shape.
|
|
35
|
+
* 5. `record.contentMetadata.document` — bare page-record envelope.
|
|
36
|
+
*
|
|
37
|
+
* Returns `null` when no candidate is available so callers can fall back.
|
|
38
|
+
*/
|
|
39
|
+
export declare function resolveTemplateDocument(templateRecord: any): any | null;
|
|
15
40
|
/**
|
|
16
41
|
* Rewrite container-repeat fields' `sourceBlockId` / `rowIds` through an id
|
|
17
42
|
* remap. Used by individual-block apply: block ids are regenerated so the
|