@singleton-sd/post-kit-editor 0.3.0
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/LICENSE +21 -0
- package/README.md +105 -0
- package/dist/canvas/EditorBlock.d.ts +6 -0
- package/dist/canvas/EditorBlock.js +25 -0
- package/dist/canvas/EditorBlock.js.map +1 -0
- package/dist/canvas/EmailBuilderCanvas.d.ts +7 -0
- package/dist/canvas/EmailBuilderCanvas.js +15 -0
- package/dist/canvas/EmailBuilderCanvas.js.map +1 -0
- package/dist/canvas/blocks/ColumnsContainerEditor.d.ts +2 -0
- package/dist/canvas/blocks/ColumnsContainerEditor.js +47 -0
- package/dist/canvas/blocks/ColumnsContainerEditor.js.map +1 -0
- package/dist/canvas/blocks/ColumnsContainerPropsSchema.d.ts +183 -0
- package/dist/canvas/blocks/ColumnsContainerPropsSchema.js +19 -0
- package/dist/canvas/blocks/ColumnsContainerPropsSchema.js.map +1 -0
- package/dist/canvas/blocks/ContainerEditor.d.ts +2 -0
- package/dist/canvas/blocks/ContainerEditor.js +39 -0
- package/dist/canvas/blocks/ContainerEditor.js.map +1 -0
- package/dist/canvas/blocks/ContainerPropsSchema.d.ts +83 -0
- package/dist/canvas/blocks/ContainerPropsSchema.js +16 -0
- package/dist/canvas/blocks/ContainerPropsSchema.js.map +1 -0
- package/dist/canvas/blocks/EmailLayoutEditor.d.ts +2 -0
- package/dist/canvas/blocks/EmailLayoutEditor.js +80 -0
- package/dist/canvas/blocks/EmailLayoutEditor.js.map +1 -0
- package/dist/canvas/blocks/EmailLayoutPropsSchema.d.ts +28 -0
- package/dist/canvas/blocks/EmailLayoutPropsSchema.js +33 -0
- package/dist/canvas/blocks/EmailLayoutPropsSchema.js.map +1 -0
- package/dist/canvas/editor-context.d.ts +22 -0
- package/dist/canvas/editor-context.js +55 -0
- package/dist/canvas/editor-context.js.map +1 -0
- package/dist/canvas/editor-core.d.ts +2910 -0
- package/dist/canvas/editor-core.js +87 -0
- package/dist/canvas/editor-core.js.map +1 -0
- package/dist/canvas/helpers/AddBlockMenu.d.ts +7 -0
- package/dist/canvas/helpers/AddBlockMenu.js +23 -0
- package/dist/canvas/helpers/AddBlockMenu.js.map +1 -0
- package/dist/canvas/helpers/EditorBlockWrapper.d.ts +5 -0
- package/dist/canvas/helpers/EditorBlockWrapper.js +36 -0
- package/dist/canvas/helpers/EditorBlockWrapper.js.map +1 -0
- package/dist/canvas/helpers/EditorChildrenIds.d.ts +11 -0
- package/dist/canvas/helpers/EditorChildrenIds.js +38 -0
- package/dist/canvas/helpers/EditorChildrenIds.js.map +1 -0
- package/dist/canvas/helpers/block-templates.d.ts +7 -0
- package/dist/canvas/helpers/block-templates.js +87 -0
- package/dist/canvas/helpers/block-templates.js.map +1 -0
- package/dist/email-template-editor.d.ts +11 -0
- package/dist/email-template-editor.js +32 -0
- package/dist/email-template-editor.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/insertion-target.d.ts +18 -0
- package/dist/insertion-target.js +41 -0
- package/dist/insertion-target.js.map +1 -0
- package/dist/metadata/MetadataPanel.d.ts +7 -0
- package/dist/metadata/MetadataPanel.js +56 -0
- package/dist/metadata/MetadataPanel.js.map +1 -0
- package/dist/metadata/insert-at-cursor.d.ts +5 -0
- package/dist/metadata/insert-at-cursor.js +22 -0
- package/dist/metadata/insert-at-cursor.js.map +1 -0
- package/dist/metadata/subject-preview.d.ts +2 -0
- package/dist/metadata/subject-preview.js +12 -0
- package/dist/metadata/subject-preview.js.map +1 -0
- package/dist/metadata/template-key.d.ts +4 -0
- package/dist/metadata/template-key.js +21 -0
- package/dist/metadata/template-key.js.map +1 -0
- package/dist/preview/PreviewDataEditor.d.ts +7 -0
- package/dist/preview/PreviewDataEditor.js +37 -0
- package/dist/preview/PreviewDataEditor.js.map +1 -0
- package/dist/preview/PreviewPane.d.ts +7 -0
- package/dist/preview/PreviewPane.js +39 -0
- package/dist/preview/PreviewPane.js.map +1 -0
- package/dist/preview/preview-frame.d.ts +8 -0
- package/dist/preview/preview-frame.js +41 -0
- package/dist/preview/preview-frame.js.map +1 -0
- package/dist/preview/preview-rows.d.ts +10 -0
- package/dist/preview/preview-rows.js +54 -0
- package/dist/preview/preview-rows.js.map +1 -0
- package/dist/preview/render-template-preview.d.ts +10 -0
- package/dist/preview/render-template-preview.js +27 -0
- package/dist/preview/render-template-preview.js.map +1 -0
- package/dist/serialization.d.ts +15 -0
- package/dist/serialization.js +128 -0
- package/dist/serialization.js.map +1 -0
- package/dist/types.d.ts +14 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/variables/VariableCatalogue.d.ts +7 -0
- package/dist/variables/VariableCatalogue.js +77 -0
- package/dist/variables/VariableCatalogue.js.map +1 -0
- package/dist/variables/clipboard.d.ts +3 -0
- package/dist/variables/clipboard.js +16 -0
- package/dist/variables/clipboard.js.map +1 -0
- package/dist/variables/copy-feedback.d.ts +7 -0
- package/dist/variables/copy-feedback.js +14 -0
- package/dist/variables/copy-feedback.js.map +1 -0
- package/dist/variables/resolve-catalogue.d.ts +2 -0
- package/dist/variables/resolve-catalogue.js +10 -0
- package/dist/variables/resolve-catalogue.js.map +1 -0
- package/dist/working-files.d.ts +6 -0
- package/dist/working-files.js +25 -0
- package/dist/working-files.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const TEMPLATE_KEY_CHARSET_MESSAGE = "Template key may only contain letters, numbers, dots, underscores, and hyphens.";
|
|
2
|
+
export declare const TEMPLATE_KEY_RESERVED_MESSAGE = "Template key cannot be \".\" or \"..\".";
|
|
3
|
+
export declare function templateKeyInputError(value: string): string | null;
|
|
4
|
+
export declare function isAcceptableTemplateKeyInput(value: string): boolean;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TEMPLATE_KEY_RESERVED_MESSAGE = exports.TEMPLATE_KEY_CHARSET_MESSAGE = void 0;
|
|
4
|
+
exports.templateKeyInputError = templateKeyInputError;
|
|
5
|
+
exports.isAcceptableTemplateKeyInput = isAcceptableTemplateKeyInput;
|
|
6
|
+
const SAFE_TEMPLATE_KEY_CHARS = /^[a-zA-Z0-9._-]*$/;
|
|
7
|
+
exports.TEMPLATE_KEY_CHARSET_MESSAGE = 'Template key may only contain letters, numbers, dots, underscores, and hyphens.';
|
|
8
|
+
exports.TEMPLATE_KEY_RESERVED_MESSAGE = 'Template key cannot be "." or "..".';
|
|
9
|
+
function templateKeyInputError(value) {
|
|
10
|
+
if (value === '.' || value === '..') {
|
|
11
|
+
return exports.TEMPLATE_KEY_RESERVED_MESSAGE;
|
|
12
|
+
}
|
|
13
|
+
if (!SAFE_TEMPLATE_KEY_CHARS.test(value)) {
|
|
14
|
+
return exports.TEMPLATE_KEY_CHARSET_MESSAGE;
|
|
15
|
+
}
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
function isAcceptableTemplateKeyInput(value) {
|
|
19
|
+
return templateKeyInputError(value) === null;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=template-key.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-key.js","sourceRoot":"","sources":["../../src/metadata/template-key.ts"],"names":[],"mappings":";;;AAoBA,sDAQC;AAMD,oEAEC;AA9BD,MAAM,uBAAuB,GAAG,mBAAmB,CAAC;AAEvC,QAAA,4BAA4B,GACvC,iFAAiF,CAAC;AAEvE,QAAA,6BAA6B,GAAG,qCAAqC,CAAC;AASnF,SAAgB,qBAAqB,CAAC,KAAa;IACjD,IAAI,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACpC,OAAO,qCAA6B,CAAC;IACvC,CAAC;IACD,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACzC,OAAO,oCAA4B,CAAC;IACtC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAMD,SAAgB,4BAA4B,CAAC,KAAa;IACxD,OAAO,qBAAqB,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { TemplatePreviewData } from '@singleton-sd/post-kit-types';
|
|
2
|
+
export interface PreviewDataEditorProps {
|
|
3
|
+
declaredVariables: readonly string[];
|
|
4
|
+
previewData: TemplatePreviewData;
|
|
5
|
+
onChange: (previewData: TemplatePreviewData) => void;
|
|
6
|
+
}
|
|
7
|
+
export declare function PreviewDataEditor({ declaredVariables, previewData, onChange, }: PreviewDataEditorProps): JSX.Element;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PreviewDataEditor = PreviewDataEditor;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const email_template_editor_1 = require("../email-template-editor");
|
|
7
|
+
const preview_rows_1 = require("./preview-rows");
|
|
8
|
+
function PreviewDataEditor({ declaredVariables, previewData, onChange, }) {
|
|
9
|
+
const p = email_template_editor_1.EDITOR_CLASS_PREFIX;
|
|
10
|
+
const rows = (0, preview_rows_1.buildPreviewRows)(declaredVariables, previewData);
|
|
11
|
+
const [newKey, setNewKey] = (0, react_1.useState)('');
|
|
12
|
+
const [addError, setAddError] = (0, react_1.useState)(null);
|
|
13
|
+
const addInputId = (0, react_1.useId)();
|
|
14
|
+
const handleValueChange = (0, react_1.useCallback)((key, value) => {
|
|
15
|
+
onChange((0, preview_rows_1.setPreviewValue)(previewData, key, value));
|
|
16
|
+
}, [onChange, previewData]);
|
|
17
|
+
const handleRemove = (0, react_1.useCallback)((key) => {
|
|
18
|
+
onChange((0, preview_rows_1.removePreviewKey)(previewData, key));
|
|
19
|
+
}, [onChange, previewData]);
|
|
20
|
+
const handleAdd = (0, react_1.useCallback)((event) => {
|
|
21
|
+
event.preventDefault();
|
|
22
|
+
const next = (0, preview_rows_1.addPreviewKey)(previewData, newKey);
|
|
23
|
+
if (next === null) {
|
|
24
|
+
const trimmed = newKey.trim();
|
|
25
|
+
setAddError(trimmed === '' ? 'Enter a variable name.' : `"${trimmed}" is already in preview data.`);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
setAddError(null);
|
|
29
|
+
setNewKey('');
|
|
30
|
+
onChange(next);
|
|
31
|
+
}, [newKey, onChange, previewData]);
|
|
32
|
+
return ((0, jsx_runtime_1.jsxs)("section", { className: `${p}preview-data`, "data-testid": `${p}preview-data`, children: [(0, jsx_runtime_1.jsx)("h2", { className: `${p}preview-data-heading`, children: "Preview data" }), (0, jsx_runtime_1.jsx)("p", { className: `${p}preview-data-hint`, children: "Sample values only \u2014 never real personal data. These are committed with the template source." }), (0, jsx_runtime_1.jsx)("ul", { className: `${p}preview-data-list`, "data-testid": `${p}preview-data-list`, children: rows.map((row) => ((0, jsx_runtime_1.jsxs)("li", { className: `${p}preview-data-row${row.extra ? ` ${p}preview-data-row-extra` : ''}`, "data-testid": `${p}preview-data-row`, "data-extra": row.extra ? 'true' : 'false', "data-key": row.key, children: [(0, jsx_runtime_1.jsxs)("label", { className: `${p}preview-data-key`, htmlFor: `${p}preview-${row.key}`, children: [row.key, row.extra ? ((0, jsx_runtime_1.jsx)("span", { className: `${p}preview-data-extra-badge`, "data-testid": `${p}preview-extra`, children: "extra" })) : null] }), (0, jsx_runtime_1.jsx)("input", { id: `${p}preview-${row.key}`, className: `${p}preview-data-value`, type: "text", value: row.value, onChange: (event) => handleValueChange(row.key, event.target.value), "data-testid": `${p}preview-value-${row.key}`, autoComplete: "off", spellCheck: false }), (0, jsx_runtime_1.jsx)("button", { type: "button", className: `${p}preview-data-remove`, onClick: () => handleRemove(row.key), "data-testid": `${p}preview-remove-${row.key}`, children: "Remove" })] }, row.key))) }), (0, jsx_runtime_1.jsxs)("form", { className: `${p}preview-data-add`, onSubmit: handleAdd, "data-testid": `${p}preview-data-add`, children: [(0, jsx_runtime_1.jsx)("label", { className: `${p}preview-data-label`, htmlFor: addInputId, children: "Add preview key" }), (0, jsx_runtime_1.jsx)("input", { id: addInputId, className: `${p}preview-data-input`, type: "text", value: newKey, onChange: (event) => {
|
|
33
|
+
setNewKey(event.target.value);
|
|
34
|
+
setAddError(null);
|
|
35
|
+
}, placeholder: "variable.name", autoComplete: "off", spellCheck: false, "data-testid": `${p}preview-add-key` }), (0, jsx_runtime_1.jsx)("button", { type: "submit", className: `${p}preview-data-add-button`, "data-testid": `${p}preview-add`, children: "Add" }), addError ? ((0, jsx_runtime_1.jsx)("p", { className: `${p}preview-data-error`, "data-testid": `${p}preview-add-error`, role: "status", children: addError })) : null] })] }));
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=PreviewDataEditor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PreviewDataEditor.js","sourceRoot":"","sources":["../../src/preview/PreviewDataEditor.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { TemplateSourceFiles } from '../types';
|
|
2
|
+
export interface PreviewPaneProps {
|
|
3
|
+
files: TemplateSourceFiles;
|
|
4
|
+
onPreviewRendered?: (html: string) => void;
|
|
5
|
+
debounceMs?: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function PreviewPane({ files, onPreviewRendered, debounceMs, }: PreviewPaneProps): JSX.Element;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PreviewPane = PreviewPane;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const email_template_editor_1 = require("../email-template-editor");
|
|
7
|
+
const preview_frame_1 = require("./preview-frame");
|
|
8
|
+
const render_template_preview_1 = require("./render-template-preview");
|
|
9
|
+
function PreviewPane({ files, onPreviewRendered, debounceMs = render_template_preview_1.PREVIEW_DEBOUNCE_MS, }) {
|
|
10
|
+
const p = email_template_editor_1.EDITOR_CLASS_PREFIX;
|
|
11
|
+
const [result, setResult] = (0, react_1.useState)(null);
|
|
12
|
+
const [pending, setPending] = (0, react_1.useState)(true);
|
|
13
|
+
const onPreviewRenderedRef = (0, react_1.useRef)(onPreviewRendered);
|
|
14
|
+
onPreviewRenderedRef.current = onPreviewRendered;
|
|
15
|
+
const requestIdRef = (0, react_1.useRef)(0);
|
|
16
|
+
(0, react_1.useEffect)(() => {
|
|
17
|
+
setPending(true);
|
|
18
|
+
const requestId = ++requestIdRef.current;
|
|
19
|
+
const timer = setTimeout(() => {
|
|
20
|
+
void (async () => {
|
|
21
|
+
const next = await (0, render_template_preview_1.renderTemplatePreview)(files);
|
|
22
|
+
if (requestId !== requestIdRef.current) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
setResult(next);
|
|
26
|
+
setPending(false);
|
|
27
|
+
if (next.ok) {
|
|
28
|
+
onPreviewRenderedRef.current?.(next.html);
|
|
29
|
+
}
|
|
30
|
+
})();
|
|
31
|
+
}, debounceMs);
|
|
32
|
+
return () => {
|
|
33
|
+
clearTimeout(timer);
|
|
34
|
+
requestIdRef.current += 1;
|
|
35
|
+
};
|
|
36
|
+
}, [files, debounceMs]);
|
|
37
|
+
return ((0, jsx_runtime_1.jsxs)("section", { className: `${p}preview-pane`, "data-testid": `${p}preview-pane`, children: [(0, jsx_runtime_1.jsx)("h2", { className: `${p}preview-pane-heading`, children: "Preview" }), result === null ? ((0, jsx_runtime_1.jsx)("p", { className: `${p}preview-pane-status`, "data-testid": `${p}preview-pending`, children: "Rendering preview\u2026" })) : null, pending && result !== null ? ((0, jsx_runtime_1.jsx)("p", { className: `${p}preview-pane-status`, "data-testid": `${p}preview-updating`, children: "Updating preview\u2026" })) : null, result && !result.ok ? (0, jsx_runtime_1.jsx)(preview_frame_1.PreviewErrorBanner, { message: result.error }) : null, result?.ok ? (0, jsx_runtime_1.jsx)(preview_frame_1.PreviewFrame, { html: result.html }) : null] }));
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=PreviewPane.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PreviewPane.js","sourceRoot":"","sources":["../../src/preview/PreviewPane.tsx"],"names":[],"mappings":";;AA+BA,kCAsDC;;AArFD,iCAA2D;AAE3D,oEAA+D;AAE/D,mDAAmE;AACnE,uEAImC;AAsBnC,SAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,iBAAiB,EACjB,UAAU,GAAG,6CAAmB,GACf;IACjB,MAAM,CAAC,GAAG,2CAAmB,CAAC;IAC9B,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,IAAA,gBAAQ,EAA6B,IAAI,CAAC,CAAC;IACvE,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,IAAA,gBAAQ,EAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,oBAAoB,GAAG,IAAA,cAAM,EAAC,iBAAiB,CAAC,CAAC;IACvD,oBAAoB,CAAC,OAAO,GAAG,iBAAiB,CAAC;IACjD,MAAM,YAAY,GAAG,IAAA,cAAM,EAAC,CAAC,CAAC,CAAC;IAE/B,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,UAAU,CAAC,IAAI,CAAC,CAAC;QACjB,MAAM,SAAS,GAAG,EAAE,YAAY,CAAC,OAAO,CAAC;QACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,KAAK,CAAC,KAAK,IAAI,EAAE;gBACf,MAAM,IAAI,GAAG,MAAM,IAAA,+CAAqB,EAAC,KAAK,CAAC,CAAC;gBAEhD,IAAI,SAAS,KAAK,YAAY,CAAC,OAAO,EAAE,CAAC;oBACvC,OAAO;gBACT,CAAC;gBACD,SAAS,CAAC,IAAI,CAAC,CAAC;gBAChB,UAAU,CAAC,KAAK,CAAC,CAAC;gBAClB,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;oBACZ,oBAAoB,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC5C,CAAC;YACH,CAAC,CAAC,EAAE,CAAC;QACP,CAAC,EAAE,UAAU,CAAC,CAAC;QAEf,OAAO,GAAG,EAAE;YACV,YAAY,CAAC,KAAK,CAAC,CAAC;YAEpB,YAAY,CAAC,OAAO,IAAI,CAAC,CAAC;QAC5B,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC;IAExB,OAAO,CACL,qCAAS,SAAS,EAAE,GAAG,CAAC,cAAc,iBAAe,GAAG,CAAC,cAAc,aACrE,+BAAI,SAAS,EAAE,GAAG,CAAC,sBAAsB,wBAAc,EACtD,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,CACjB,8BAAG,SAAS,EAAE,GAAG,CAAC,qBAAqB,iBAAe,GAAG,CAAC,iBAAiB,wCAEvE,CACL,CAAC,CAAC,CAAC,IAAI,EACP,OAAO,IAAI,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,CAC5B,8BAAG,SAAS,EAAE,GAAG,CAAC,qBAAqB,iBAAe,GAAG,CAAC,kBAAkB,uCAExE,CACL,CAAC,CAAC,CAAC,IAAI,EACP,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,uBAAC,kCAAkB,IAAC,OAAO,EAAE,MAAM,CAAC,KAAK,GAAI,CAAC,CAAC,CAAC,IAAI,EAC3E,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,uBAAC,4BAAY,IAAC,IAAI,EAAE,MAAM,CAAC,IAAI,GAAI,CAAC,CAAC,CAAC,IAAI,IAChD,CACX,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const PREVIEW_DOCUMENT_CSP = "default-src 'none'; script-src 'none'; connect-src 'none'; style-src 'unsafe-inline'; img-src data:; font-src data:; object-src 'none'; base-uri 'none'; form-action 'none'; frame-src 'none'";
|
|
2
|
+
export declare function wrapPreviewHtmlWithCsp(html: string): string;
|
|
3
|
+
export declare function PreviewErrorBanner({ message }: {
|
|
4
|
+
message: string;
|
|
5
|
+
}): JSX.Element;
|
|
6
|
+
export declare function PreviewFrame({ html }: {
|
|
7
|
+
html: string;
|
|
8
|
+
}): JSX.Element;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PREVIEW_DOCUMENT_CSP = void 0;
|
|
7
|
+
exports.wrapPreviewHtmlWithCsp = wrapPreviewHtmlWithCsp;
|
|
8
|
+
exports.PreviewErrorBanner = PreviewErrorBanner;
|
|
9
|
+
exports.PreviewFrame = PreviewFrame;
|
|
10
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
11
|
+
const react_1 = __importDefault(require("react"));
|
|
12
|
+
const email_template_editor_1 = require("../email-template-editor");
|
|
13
|
+
exports.PREVIEW_DOCUMENT_CSP = "default-src 'none'; script-src 'none'; connect-src 'none'; style-src 'unsafe-inline'; img-src data:; font-src data:; object-src 'none'; base-uri 'none'; form-action 'none'; frame-src 'none'";
|
|
14
|
+
function wrapPreviewHtmlWithCsp(html) {
|
|
15
|
+
const meta = `<meta http-equiv="Content-Security-Policy" content="${exports.PREVIEW_DOCUMENT_CSP}">`;
|
|
16
|
+
const trimmed = html.trim();
|
|
17
|
+
if (/^<!DOCTYPE/i.test(trimmed) || /^<html[\s>]/i.test(trimmed)) {
|
|
18
|
+
if (/<head[\s>]/i.test(trimmed)) {
|
|
19
|
+
return trimmed.replace(/<head([^>]*)>/i, `<head$1>${meta}`);
|
|
20
|
+
}
|
|
21
|
+
return trimmed.replace(/<html([^>]*)>/i, `<html$1><head>${meta}</head>`);
|
|
22
|
+
}
|
|
23
|
+
return `<!DOCTYPE html><html><head>${meta}</head><body>${html}</body></html>`;
|
|
24
|
+
}
|
|
25
|
+
function PreviewErrorBanner({ message }) {
|
|
26
|
+
const p = email_template_editor_1.EDITOR_CLASS_PREFIX;
|
|
27
|
+
return ((0, jsx_runtime_1.jsx)("p", { className: `${p}preview-pane-error`, "data-testid": `${p}preview-error`, role: "alert", children: message }));
|
|
28
|
+
}
|
|
29
|
+
function PreviewFrame({ html }) {
|
|
30
|
+
const p = email_template_editor_1.EDITOR_CLASS_PREFIX;
|
|
31
|
+
const srcDoc = wrapPreviewHtmlWithCsp(html);
|
|
32
|
+
return react_1.default.createElement('iframe', {
|
|
33
|
+
className: `${p}preview-frame`,
|
|
34
|
+
title: 'Email preview',
|
|
35
|
+
sandbox: '',
|
|
36
|
+
srcDoc,
|
|
37
|
+
'data-testid': `${p}preview-frame`,
|
|
38
|
+
csp: exports.PREVIEW_DOCUMENT_CSP,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=preview-frame.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preview-frame.js","sourceRoot":"","sources":["../../src/preview/preview-frame.tsx"],"names":[],"mappings":";;;;;;AAwBA,wDAUC;AAED,gDAOC;AAED,oCAeC;;AArDD,kDAA0B;AAE1B,oEAA+D;AASlD,QAAA,oBAAoB,GAC/B,+LAA+L,CAAC;AAKlM,SAAgB,sBAAsB,CAAC,IAAY;IACjD,MAAM,IAAI,GAAG,uDAAuD,4BAAoB,IAAI,CAAC;IAC7F,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAChE,IAAI,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAChC,OAAO,OAAO,CAAC,OAAO,CAAC,gBAAgB,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC;QAC9D,CAAC;QACD,OAAO,OAAO,CAAC,OAAO,CAAC,gBAAgB,EAAE,iBAAiB,IAAI,SAAS,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,8BAA8B,IAAI,gBAAgB,IAAI,gBAAgB,CAAC;AAChF,CAAC;AAED,SAAgB,kBAAkB,CAAC,EAAE,OAAO,EAAuB;IACjE,MAAM,CAAC,GAAG,2CAAmB,CAAC;IAC9B,OAAO,CACL,8BAAG,SAAS,EAAE,GAAG,CAAC,oBAAoB,iBAAe,GAAG,CAAC,eAAe,EAAE,IAAI,EAAC,OAAO,YACnF,OAAO,GACN,CACL,CAAC;AACJ,CAAC;AAED,SAAgB,YAAY,CAAC,EAAE,IAAI,EAAoB;IACrD,MAAM,CAAC,GAAG,2CAAmB,CAAC;IAC9B,MAAM,MAAM,GAAG,sBAAsB,CAAC,IAAI,CAAC,CAAC;IAE5C,OAAO,eAAK,CAAC,aAAa,CAAC,QAAQ,EAAE;QACnC,SAAS,EAAE,GAAG,CAAC,eAAe;QAC9B,KAAK,EAAE,eAAe;QACtB,OAAO,EAAE,EAAE;QACX,MAAM;QACN,aAAa,EAAE,GAAG,CAAC,eAAe;QAClC,GAAG,EAAE,4BAAoB;KAI1B,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { TemplatePreviewData } from '@singleton-sd/post-kit-types';
|
|
2
|
+
export interface PreviewDataRow {
|
|
3
|
+
key: string;
|
|
4
|
+
value: string;
|
|
5
|
+
extra: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function buildPreviewRows(declaredVariables: readonly string[], previewData: TemplatePreviewData): PreviewDataRow[];
|
|
8
|
+
export declare function setPreviewValue(previewData: TemplatePreviewData, key: string, value: string): TemplatePreviewData;
|
|
9
|
+
export declare function removePreviewKey(previewData: TemplatePreviewData, key: string): TemplatePreviewData;
|
|
10
|
+
export declare function addPreviewKey(previewData: TemplatePreviewData, key: string, value?: string): TemplatePreviewData | null;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildPreviewRows = buildPreviewRows;
|
|
4
|
+
exports.setPreviewValue = setPreviewValue;
|
|
5
|
+
exports.removePreviewKey = removePreviewKey;
|
|
6
|
+
exports.addPreviewKey = addPreviewKey;
|
|
7
|
+
function buildPreviewRows(declaredVariables, previewData) {
|
|
8
|
+
const seenDeclared = new Set();
|
|
9
|
+
const rows = [];
|
|
10
|
+
for (const key of declaredVariables) {
|
|
11
|
+
if (seenDeclared.has(key)) {
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
seenDeclared.add(key);
|
|
15
|
+
rows.push({
|
|
16
|
+
key,
|
|
17
|
+
value: Object.prototype.hasOwnProperty.call(previewData, key) ? (previewData[key] ?? '') : '',
|
|
18
|
+
extra: false,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
const extras = Object.keys(previewData)
|
|
22
|
+
.filter((key) => !seenDeclared.has(key))
|
|
23
|
+
.sort((a, b) => a.localeCompare(b));
|
|
24
|
+
for (const key of extras) {
|
|
25
|
+
rows.push({
|
|
26
|
+
key,
|
|
27
|
+
value: previewData[key] ?? '',
|
|
28
|
+
extra: true,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
return rows;
|
|
32
|
+
}
|
|
33
|
+
function setPreviewValue(previewData, key, value) {
|
|
34
|
+
return { ...previewData, [key]: value };
|
|
35
|
+
}
|
|
36
|
+
function removePreviewKey(previewData, key) {
|
|
37
|
+
if (!Object.prototype.hasOwnProperty.call(previewData, key)) {
|
|
38
|
+
return previewData;
|
|
39
|
+
}
|
|
40
|
+
const next = { ...previewData };
|
|
41
|
+
delete next[key];
|
|
42
|
+
return next;
|
|
43
|
+
}
|
|
44
|
+
function addPreviewKey(previewData, key, value = '') {
|
|
45
|
+
const trimmed = key.trim();
|
|
46
|
+
if (!trimmed) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
if (Object.prototype.hasOwnProperty.call(previewData, trimmed)) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
return { ...previewData, [trimmed]: value };
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=preview-rows.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preview-rows.js","sourceRoot":"","sources":["../../src/preview/preview-rows.ts"],"names":[],"mappings":";;AAuBA,4CAgCC;AAMD,0CAMC;AAMD,4CAUC;AAKD,sCAaC;AA9ED,SAAgB,gBAAgB,CAC9B,iBAAoC,EACpC,WAAgC;IAEhC,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;IACvC,MAAM,IAAI,GAAqB,EAAE,CAAC;IAElC,KAAK,MAAM,GAAG,IAAI,iBAAiB,EAAE,CAAC;QACpC,IAAI,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,SAAS;QACX,CAAC;QACD,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,IAAI,CAAC;YACR,GAAG;YACH,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE;YAC7F,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;IACL,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC;SACpC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;SACvC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;IAEtC,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,CAAC;YACR,GAAG;YACH,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE;YAC7B,KAAK,EAAE,IAAI;SACZ,CAAC,CAAC;IACL,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAMD,SAAgB,eAAe,CAC7B,WAAgC,EAChC,GAAW,EACX,KAAa;IAEb,OAAO,EAAE,GAAG,WAAW,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC;AAC1C,CAAC;AAMD,SAAgB,gBAAgB,CAC9B,WAAgC,EAChC,GAAW;IAEX,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,EAAE,CAAC;QAC5D,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,MAAM,IAAI,GAAG,EAAE,GAAG,WAAW,EAAE,CAAC;IAChC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;IACjB,OAAO,IAAI,CAAC;AACd,CAAC;AAKD,SAAgB,aAAa,CAC3B,WAAgC,EAChC,GAAW,EACX,KAAK,GAAG,EAAE;IAEV,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,EAAE,CAAC;QAC/D,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,EAAE,GAAG,WAAW,EAAE,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC;AAC9C,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { TemplateSourceFiles } from '../types';
|
|
2
|
+
export type PreviewRenderResult = {
|
|
3
|
+
ok: true;
|
|
4
|
+
html: string;
|
|
5
|
+
} | {
|
|
6
|
+
ok: false;
|
|
7
|
+
error: string;
|
|
8
|
+
};
|
|
9
|
+
export declare function renderTemplatePreview(files: TemplateSourceFiles): Promise<PreviewRenderResult>;
|
|
10
|
+
export declare const PREVIEW_DEBOUNCE_MS = 300;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PREVIEW_DEBOUNCE_MS = void 0;
|
|
4
|
+
exports.renderTemplatePreview = renderTemplatePreview;
|
|
5
|
+
const preview_1 = require("@singleton-sd/post-kit-compiler/preview");
|
|
6
|
+
async function renderTemplatePreview(files) {
|
|
7
|
+
const source = {
|
|
8
|
+
templateJson: files.templateJson,
|
|
9
|
+
metadata: files.metadata,
|
|
10
|
+
previewData: files.previewData,
|
|
11
|
+
};
|
|
12
|
+
try {
|
|
13
|
+
const html = await (0, preview_1.renderPreview)(source);
|
|
14
|
+
return { ok: true, html };
|
|
15
|
+
}
|
|
16
|
+
catch (err) {
|
|
17
|
+
if (err instanceof preview_1.CompilerError) {
|
|
18
|
+
return { ok: false, error: err.message };
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
ok: false,
|
|
22
|
+
error: err instanceof Error ? err.message : String(err),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.PREVIEW_DEBOUNCE_MS = 300;
|
|
27
|
+
//# sourceMappingURL=render-template-preview.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-template-preview.js","sourceRoot":"","sources":["../../src/preview/render-template-preview.ts"],"names":[],"mappings":";;;AAWA,sDAqBC;AA/BD,qEAAuF;AAUhF,KAAK,UAAU,qBAAqB,CACzC,KAA0B;IAE1B,MAAM,MAAM,GAAmB;QAC7B,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,WAAW,EAAE,KAAK,CAAC,WAAW;KAC/B,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,IAAA,uBAAa,EAAC,MAAM,CAAC,CAAC;QACzC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC5B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,uBAAa,EAAE,CAAC;YACjC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;QAC3C,CAAC;QACD,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SACxD,CAAC;IACJ,CAAC;AACH,CAAC;AAGY,QAAA,mBAAmB,GAAG,GAAG,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { TemplateSourceFiles } from './types';
|
|
2
|
+
export declare class TemplateSourceError extends Error {
|
|
3
|
+
readonly file: 'template.json' | 'metadata.json' | 'preview.json';
|
|
4
|
+
constructor(file: TemplateSourceError['file'], message: string);
|
|
5
|
+
}
|
|
6
|
+
export declare function loadTemplateSource(input: {
|
|
7
|
+
templateJson: unknown;
|
|
8
|
+
metadata: unknown;
|
|
9
|
+
previewData: unknown;
|
|
10
|
+
}): TemplateSourceFiles;
|
|
11
|
+
export declare function serializeTemplateSource(files: TemplateSourceFiles): {
|
|
12
|
+
templateJson: string;
|
|
13
|
+
metadataJson: string;
|
|
14
|
+
previewJson: string;
|
|
15
|
+
};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TemplateSourceError = void 0;
|
|
4
|
+
exports.loadTemplateSource = loadTemplateSource;
|
|
5
|
+
exports.serializeTemplateSource = serializeTemplateSource;
|
|
6
|
+
const post_kit_types_1 = require("@singleton-sd/post-kit-types");
|
|
7
|
+
class TemplateSourceError extends Error {
|
|
8
|
+
constructor(file, message) {
|
|
9
|
+
super(`${file}: ${message}`);
|
|
10
|
+
this.name = 'TemplateSourceError';
|
|
11
|
+
this.file = file;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
exports.TemplateSourceError = TemplateSourceError;
|
|
15
|
+
function isPlainObject(value) {
|
|
16
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
17
|
+
}
|
|
18
|
+
function assertTemplateJson(value) {
|
|
19
|
+
if (!isPlainObject(value)) {
|
|
20
|
+
throw new TemplateSourceError('template.json', 'must be a JSON object');
|
|
21
|
+
}
|
|
22
|
+
if (!('root' in value)) {
|
|
23
|
+
throw new TemplateSourceError('template.json', 'must be an EmailBuilder document object with a root block');
|
|
24
|
+
}
|
|
25
|
+
const root = value.root;
|
|
26
|
+
if (!isPlainObject(root) ||
|
|
27
|
+
typeof root.type !== 'string' ||
|
|
28
|
+
root.type.trim() === '' ||
|
|
29
|
+
!isPlainObject(root.data)) {
|
|
30
|
+
throw new TemplateSourceError('template.json', 'must be an EmailBuilder document object with a root block');
|
|
31
|
+
}
|
|
32
|
+
return value;
|
|
33
|
+
}
|
|
34
|
+
function assertMetadata(value) {
|
|
35
|
+
if (!isPlainObject(value)) {
|
|
36
|
+
throw new TemplateSourceError('metadata.json', 'must be a JSON object');
|
|
37
|
+
}
|
|
38
|
+
const requiredStrings = ['key', 'name', 'subject', 'schemaVersion'];
|
|
39
|
+
for (const field of requiredStrings) {
|
|
40
|
+
if (typeof value[field] !== 'string' || value[field].trim() === '') {
|
|
41
|
+
throw new TemplateSourceError('metadata.json', `metadata.${field} must be a non-empty string`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (value.schemaVersion !== post_kit_types_1.TEMPLATE_SCHEMA_VERSION) {
|
|
45
|
+
throw new TemplateSourceError('metadata.json', `metadata.schemaVersion must be "${post_kit_types_1.TEMPLATE_SCHEMA_VERSION}" (got ${JSON.stringify(value.schemaVersion)})`);
|
|
46
|
+
}
|
|
47
|
+
if (!Array.isArray(value.variables)) {
|
|
48
|
+
throw new TemplateSourceError('metadata.json', 'metadata.variables must be an array');
|
|
49
|
+
}
|
|
50
|
+
for (let i = 0; i < value.variables.length; i++) {
|
|
51
|
+
if (typeof value.variables[i] !== 'string') {
|
|
52
|
+
throw new TemplateSourceError('metadata.json', `metadata.variables[${i}] must be a string`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (value.description !== undefined && typeof value.description !== 'string') {
|
|
56
|
+
throw new TemplateSourceError('metadata.json', 'metadata.description must be a string');
|
|
57
|
+
}
|
|
58
|
+
return value;
|
|
59
|
+
}
|
|
60
|
+
function assertPreviewData(value) {
|
|
61
|
+
if (!isPlainObject(value)) {
|
|
62
|
+
throw new TemplateSourceError('preview.json', 'must be a JSON object');
|
|
63
|
+
}
|
|
64
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
65
|
+
if (typeof entry !== 'string') {
|
|
66
|
+
throw new TemplateSourceError('preview.json', `preview.${key} must be a string`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return value;
|
|
70
|
+
}
|
|
71
|
+
function sortKeys(value, preferredOrder = []) {
|
|
72
|
+
if (Array.isArray(value)) {
|
|
73
|
+
return value.map((entry) => sortKeys(entry, preferredOrder));
|
|
74
|
+
}
|
|
75
|
+
if (!isPlainObject(value)) {
|
|
76
|
+
return value;
|
|
77
|
+
}
|
|
78
|
+
const preferred = preferredOrder.filter((key) => key in value);
|
|
79
|
+
const remaining = Object.keys(value)
|
|
80
|
+
.filter((key) => !preferred.includes(key))
|
|
81
|
+
.sort();
|
|
82
|
+
const orderedKeys = [...preferred, ...remaining];
|
|
83
|
+
const sorted = {};
|
|
84
|
+
for (const key of orderedKeys) {
|
|
85
|
+
sorted[key] = sortKeys(value[key], preferredOrder);
|
|
86
|
+
}
|
|
87
|
+
return sorted;
|
|
88
|
+
}
|
|
89
|
+
function stableTemplateJson(value) {
|
|
90
|
+
const ordered = sortKeys(value, ['root']);
|
|
91
|
+
return `${JSON.stringify(ordered, null, 2)}\n`;
|
|
92
|
+
}
|
|
93
|
+
function stableMetadataJson(value) {
|
|
94
|
+
const ordered = sortKeys(value, [
|
|
95
|
+
'key',
|
|
96
|
+
'name',
|
|
97
|
+
'subject',
|
|
98
|
+
'description',
|
|
99
|
+
'variables',
|
|
100
|
+
'schemaVersion',
|
|
101
|
+
]);
|
|
102
|
+
return `${JSON.stringify(ordered, null, 2)}\n`;
|
|
103
|
+
}
|
|
104
|
+
function stablePreviewJson(value) {
|
|
105
|
+
const ordered = sortKeys(value);
|
|
106
|
+
return `${JSON.stringify(ordered, null, 2)}\n`;
|
|
107
|
+
}
|
|
108
|
+
function loadTemplateSource(input) {
|
|
109
|
+
const templateJson = assertTemplateJson(input.templateJson);
|
|
110
|
+
const metadata = assertMetadata(input.metadata);
|
|
111
|
+
const previewData = assertPreviewData(input.previewData);
|
|
112
|
+
return {
|
|
113
|
+
templateJson: templateJson,
|
|
114
|
+
metadata,
|
|
115
|
+
previewData,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function serializeTemplateSource(files) {
|
|
119
|
+
if (!isPlainObject(files.templateJson)) {
|
|
120
|
+
throw new TemplateSourceError('template.json', 'must be a JSON object');
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
templateJson: stableTemplateJson(files.templateJson),
|
|
124
|
+
metadataJson: stableMetadataJson(files.metadata),
|
|
125
|
+
previewJson: stablePreviewJson(files.previewData),
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=serialization.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serialization.js","sourceRoot":"","sources":["../src/serialization.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { TReaderDocument } from '@usewaypoint/email-builder';
|
|
2
|
+
import type { TemplateSourceMetadata, TemplatePreviewData } from '@singleton-sd/post-kit-types';
|
|
3
|
+
export type EmailBuilderDocument = TReaderDocument & Record<string, unknown>;
|
|
4
|
+
export interface TemplateSourceFiles {
|
|
5
|
+
templateJson: EmailBuilderDocument;
|
|
6
|
+
metadata: TemplateSourceMetadata;
|
|
7
|
+
previewData: TemplatePreviewData;
|
|
8
|
+
}
|
|
9
|
+
export interface TemplateVariable {
|
|
10
|
+
name: string;
|
|
11
|
+
label?: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
example?: string;
|
|
14
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { TemplateVariable } from '../types';
|
|
2
|
+
export interface VariableCatalogueProps {
|
|
3
|
+
availableVariables?: TemplateVariable[];
|
|
4
|
+
metadataVariables: string[];
|
|
5
|
+
onMetadataVariablesChange: (variables: string[]) => void;
|
|
6
|
+
}
|
|
7
|
+
export declare function VariableCatalogue({ availableVariables, metadataVariables, onMetadataVariablesChange, }: VariableCatalogueProps): JSX.Element;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.VariableCatalogue = VariableCatalogue;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const email_template_editor_1 = require("../email-template-editor");
|
|
7
|
+
const insertion_target_1 = require("../insertion-target");
|
|
8
|
+
const insert_at_cursor_1 = require("../metadata/insert-at-cursor");
|
|
9
|
+
const clipboard_1 = require("./clipboard");
|
|
10
|
+
const copy_feedback_1 = require("./copy-feedback");
|
|
11
|
+
const resolve_catalogue_1 = require("./resolve-catalogue");
|
|
12
|
+
function VariableCatalogue({ availableVariables, metadataVariables, onMetadataVariablesChange, }) {
|
|
13
|
+
const p = email_template_editor_1.EDITOR_CLASS_PREFIX;
|
|
14
|
+
const { target } = (0, insertion_target_1.useInsertionTarget)();
|
|
15
|
+
const entries = (0, resolve_catalogue_1.resolveCatalogueVariables)(availableVariables, metadataVariables);
|
|
16
|
+
const [copyFeedback, setCopyFeedback] = (0, react_1.useState)(null);
|
|
17
|
+
const [newVariable, setNewVariable] = (0, react_1.useState)('');
|
|
18
|
+
const [addError, setAddError] = (0, react_1.useState)(null);
|
|
19
|
+
const fallbackSelectRef = (0, react_1.useRef)(null);
|
|
20
|
+
const addInputId = (0, react_1.useId)();
|
|
21
|
+
const handleCopy = (0, react_1.useCallback)(async (name) => {
|
|
22
|
+
const text = (0, insert_at_cursor_1.variablePlaceholder)(name);
|
|
23
|
+
const result = await (0, clipboard_1.copyTextToClipboard)(text);
|
|
24
|
+
const kind = (0, copy_feedback_1.copyFeedbackKind)(result);
|
|
25
|
+
if (kind === 'manual') {
|
|
26
|
+
const el = fallbackSelectRef.current;
|
|
27
|
+
if (el) {
|
|
28
|
+
el.value = text;
|
|
29
|
+
el.focus();
|
|
30
|
+
el.select();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
setCopyFeedback({ name, kind });
|
|
34
|
+
}, []);
|
|
35
|
+
const handleInsert = (0, react_1.useCallback)((name) => {
|
|
36
|
+
if (!target) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
target.insert((0, insert_at_cursor_1.variablePlaceholder)(name));
|
|
40
|
+
}, [target]);
|
|
41
|
+
const preserveInsertionTarget = (0, react_1.useCallback)((event) => {
|
|
42
|
+
event.preventDefault();
|
|
43
|
+
}, []);
|
|
44
|
+
const handleAdd = (0, react_1.useCallback)((event) => {
|
|
45
|
+
event.preventDefault();
|
|
46
|
+
const name = newVariable.trim();
|
|
47
|
+
if (!name) {
|
|
48
|
+
setAddError('Enter a variable name.');
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (metadataVariables.includes(name)) {
|
|
52
|
+
setAddError(`"${name}" is already declared.`);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
setAddError(null);
|
|
56
|
+
setNewVariable('');
|
|
57
|
+
onMetadataVariablesChange([...metadataVariables, name]);
|
|
58
|
+
}, [metadataVariables, newVariable, onMetadataVariablesChange]);
|
|
59
|
+
const handleRemove = (0, react_1.useCallback)((name) => {
|
|
60
|
+
onMetadataVariablesChange(metadataVariables.filter((entry) => entry !== name));
|
|
61
|
+
}, [metadataVariables, onMetadataVariablesChange]);
|
|
62
|
+
const insertDisabled = target === null;
|
|
63
|
+
const insertDisabledReason = 'Focus the subject field (or another editable target) before inserting a variable.';
|
|
64
|
+
return ((0, jsx_runtime_1.jsxs)("section", { className: `${p}variables`, "data-testid": `${p}variables`, children: [(0, jsx_runtime_1.jsx)("h2", { className: `${p}variables-heading`, children: "Available variables" }), (0, jsx_runtime_1.jsx)("input", { ref: fallbackSelectRef, className: `${p}variables-clipboard-fallback`, type: "text", readOnly: true, "aria-hidden": "true", tabIndex: -1, "data-testid": `${p}variables-clipboard-fallback` }), entries.length === 0 ? ((0, jsx_runtime_1.jsx)("p", { className: `${p}variables-empty`, children: "No variables declared yet." })) : ((0, jsx_runtime_1.jsx)("ul", { className: `${p}variables-list`, children: entries.map((entry) => {
|
|
65
|
+
const placeholder = (0, insert_at_cursor_1.variablePlaceholder)(entry.name);
|
|
66
|
+
const label = entry.label ?? entry.name;
|
|
67
|
+
return ((0, jsx_runtime_1.jsxs)("li", { className: `${p}variables-item`, children: [(0, jsx_runtime_1.jsxs)("div", { className: `${p}variables-item-main`, children: [(0, jsx_runtime_1.jsx)("span", { className: `${p}variables-item-label`, children: label }), (0, jsx_runtime_1.jsx)("code", { className: `${p}variables-item-placeholder`, children: placeholder }), entry.description ? ((0, jsx_runtime_1.jsx)("span", { className: `${p}variables-item-description`, children: entry.description })) : null] }), (0, jsx_runtime_1.jsxs)("div", { className: `${p}variables-item-actions`, children: [(0, jsx_runtime_1.jsx)("button", { type: "button", className: `${p}variables-copy`, onClick: () => {
|
|
68
|
+
void handleCopy(entry.name);
|
|
69
|
+
}, "data-testid": `${p}variables-copy-${entry.name}`, children: (0, copy_feedback_1.copyButtonLabel)(copyFeedback, entry.name) }), (0, jsx_runtime_1.jsx)("button", { type: "button", className: `${p}variables-insert`, onMouseDown: preserveInsertionTarget, onClick: () => handleInsert(entry.name), disabled: insertDisabled, title: insertDisabled ? insertDisabledReason : `Insert ${placeholder}`, "aria-label": insertDisabled
|
|
70
|
+
? insertDisabledReason
|
|
71
|
+
: `Insert ${placeholder} into the focused field`, "data-testid": `${p}variables-insert-${entry.name}`, children: "Insert" })] })] }, entry.name));
|
|
72
|
+
}) })), (0, jsx_runtime_1.jsxs)("div", { className: `${p}variables-declared`, children: [(0, jsx_runtime_1.jsx)("h3", { className: `${p}variables-declared-heading`, children: "Declared variables" }), (0, jsx_runtime_1.jsx)("p", { className: `${p}variables-declared-hint`, children: "The declared list is what validation and the compiler use. Removing an entry does not rewrite the subject or document." }), metadataVariables.length > 0 ? ((0, jsx_runtime_1.jsx)("ul", { className: `${p}variables-declared-list`, children: metadataVariables.map((name) => ((0, jsx_runtime_1.jsxs)("li", { className: `${p}variables-declared-item`, children: [(0, jsx_runtime_1.jsx)("code", { children: (0, insert_at_cursor_1.variablePlaceholder)(name) }), (0, jsx_runtime_1.jsx)("button", { type: "button", className: `${p}variables-remove`, onClick: () => handleRemove(name), "data-testid": `${p}variables-remove-${name}`, children: "Remove" })] }, name))) })) : null, (0, jsx_runtime_1.jsxs)("form", { className: `${p}variables-add`, onSubmit: handleAdd, children: [(0, jsx_runtime_1.jsx)("label", { className: `${p}variables-add-label`, htmlFor: addInputId, children: "Add variable" }), (0, jsx_runtime_1.jsx)("input", { id: addInputId, className: `${p}variables-add-input`, type: "text", value: newVariable, onChange: (event) => {
|
|
73
|
+
setNewVariable(event.target.value);
|
|
74
|
+
setAddError(null);
|
|
75
|
+
}, placeholder: "e.g. firstName", "data-testid": `${p}variables-add-input` }), (0, jsx_runtime_1.jsx)("button", { type: "submit", className: `${p}variables-add-submit`, "data-testid": `${p}variables-add-submit`, children: "Add" }), addError ? ((0, jsx_runtime_1.jsx)("p", { className: `${p}variables-add-error`, role: "status", children: addError })) : null] })] })] }));
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=VariableCatalogue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VariableCatalogue.js","sourceRoot":"","sources":["../../src/variables/VariableCatalogue.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.copyTextToClipboard = copyTextToClipboard;
|
|
4
|
+
async function copyTextToClipboard(text) {
|
|
5
|
+
try {
|
|
6
|
+
const clipboard = globalThis.navigator?.clipboard;
|
|
7
|
+
if (clipboard && typeof clipboard.writeText === 'function') {
|
|
8
|
+
await clipboard.writeText(text);
|
|
9
|
+
return { ok: true };
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
}
|
|
14
|
+
return { ok: false };
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=clipboard.js.map
|