@react-email/editor 0.0.0-experimental.16 → 0.0.0-experimental.17
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/dist/index.cjs +474 -194
- package/dist/index.d.cts +212 -155
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +210 -153
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +473 -198
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -34,6 +34,7 @@ let _tiptap_react = require("@tiptap/react");
|
|
|
34
34
|
let react = require("react");
|
|
35
35
|
react = __toESM(react);
|
|
36
36
|
let _tiptap_starter_kit = require("@tiptap/starter-kit");
|
|
37
|
+
_tiptap_starter_kit = __toESM(_tiptap_starter_kit);
|
|
37
38
|
let _tiptap_extension_blockquote = require("@tiptap/extension-blockquote");
|
|
38
39
|
_tiptap_extension_blockquote = __toESM(_tiptap_extension_blockquote);
|
|
39
40
|
let _tiptap_extension_bullet_list = require("@tiptap/extension-bullet-list");
|
|
@@ -47,10 +48,15 @@ let _tiptap_pm_view = require("@tiptap/pm/view");
|
|
|
47
48
|
let hast_util_from_html = require("hast-util-from-html");
|
|
48
49
|
let prismjs = require("prismjs");
|
|
49
50
|
prismjs = __toESM(prismjs);
|
|
51
|
+
let _tiptap_extension_horizontal_rule = require("@tiptap/extension-horizontal-rule");
|
|
52
|
+
_tiptap_extension_horizontal_rule = __toESM(_tiptap_extension_horizontal_rule);
|
|
50
53
|
let _tiptap_extension_hard_break = require("@tiptap/extension-hard-break");
|
|
51
54
|
_tiptap_extension_hard_break = __toESM(_tiptap_extension_hard_break);
|
|
55
|
+
let _tiptap_extension_heading = require("@tiptap/extension-heading");
|
|
52
56
|
let _tiptap_extension_italic = require("@tiptap/extension-italic");
|
|
53
57
|
_tiptap_extension_italic = __toESM(_tiptap_extension_italic);
|
|
58
|
+
let _tiptap_extension_link = require("@tiptap/extension-link");
|
|
59
|
+
_tiptap_extension_link = __toESM(_tiptap_extension_link);
|
|
54
60
|
let _tiptap_extension_list_item = require("@tiptap/extension-list-item");
|
|
55
61
|
_tiptap_extension_list_item = __toESM(_tiptap_extension_list_item);
|
|
56
62
|
let _tiptap_extension_ordered_list = require("@tiptap/extension-ordered-list");
|
|
@@ -1174,10 +1180,153 @@ const Div = EmailNode.create({
|
|
|
1174
1180
|
}
|
|
1175
1181
|
});
|
|
1176
1182
|
|
|
1183
|
+
//#endregion
|
|
1184
|
+
//#region src/extensions/divider.tsx
|
|
1185
|
+
const Divider = EmailNode.from(_tiptap_extension_horizontal_rule.default.extend({
|
|
1186
|
+
addAttributes() {
|
|
1187
|
+
return { class: { default: "divider" } };
|
|
1188
|
+
},
|
|
1189
|
+
addInputRules() {
|
|
1190
|
+
return [new _tiptap_core.InputRule({
|
|
1191
|
+
find: /^(?:---|—-|___\s|\*\*\*\s)$/,
|
|
1192
|
+
handler: ({ state, range }) => {
|
|
1193
|
+
const attributes = {};
|
|
1194
|
+
const { tr } = state;
|
|
1195
|
+
const start = range.from;
|
|
1196
|
+
const end = range.to;
|
|
1197
|
+
tr.insert(start - 1, this.type.create(attributes)).delete(tr.mapping.map(start), tr.mapping.map(end));
|
|
1198
|
+
}
|
|
1199
|
+
})];
|
|
1200
|
+
},
|
|
1201
|
+
addNodeView() {
|
|
1202
|
+
return (0, _tiptap_react.ReactNodeViewRenderer)((props) => {
|
|
1203
|
+
const node = props.node;
|
|
1204
|
+
const { class: className, ...rest } = node.attrs;
|
|
1205
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_tiptap_react.NodeViewWrapper, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_react_email_components.Hr, {
|
|
1206
|
+
...rest,
|
|
1207
|
+
className: "node-hr",
|
|
1208
|
+
style: inlineCssToJs(node.attrs.style)
|
|
1209
|
+
}) });
|
|
1210
|
+
});
|
|
1211
|
+
}
|
|
1212
|
+
}), ({ node, style }) => {
|
|
1213
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_react_email_components.Hr, {
|
|
1214
|
+
className: node.attrs?.class || void 0,
|
|
1215
|
+
style: {
|
|
1216
|
+
...style,
|
|
1217
|
+
...inlineCssToJs(node.attrs?.style)
|
|
1218
|
+
}
|
|
1219
|
+
});
|
|
1220
|
+
});
|
|
1221
|
+
|
|
1222
|
+
//#endregion
|
|
1223
|
+
//#region src/extensions/global-content.ts
|
|
1224
|
+
const GLOBAL_CONTENT_NODE_TYPE = "globalContent";
|
|
1225
|
+
let cachedGlobalPosition = null;
|
|
1226
|
+
function findGlobalContentPositions(doc) {
|
|
1227
|
+
const positions = [];
|
|
1228
|
+
doc.descendants((node, position) => {
|
|
1229
|
+
if (node.type.name === GLOBAL_CONTENT_NODE_TYPE) positions.push(position);
|
|
1230
|
+
});
|
|
1231
|
+
return positions;
|
|
1232
|
+
}
|
|
1233
|
+
function getCachedGlobalContentPosition(doc) {
|
|
1234
|
+
if (cachedGlobalPosition != null) try {
|
|
1235
|
+
if (doc.nodeAt(cachedGlobalPosition)?.type.name === GLOBAL_CONTENT_NODE_TYPE) return cachedGlobalPosition;
|
|
1236
|
+
} catch {
|
|
1237
|
+
cachedGlobalPosition = null;
|
|
1238
|
+
}
|
|
1239
|
+
cachedGlobalPosition = findGlobalContentPositions(doc)[0] ?? null;
|
|
1240
|
+
return cachedGlobalPosition;
|
|
1241
|
+
}
|
|
1242
|
+
function getGlobalContent(key, editor) {
|
|
1243
|
+
const position = getCachedGlobalContentPosition(editor.state.doc);
|
|
1244
|
+
if (cachedGlobalPosition == null) return null;
|
|
1245
|
+
return editor.state.doc.nodeAt(position)?.attrs.data[key] ?? null;
|
|
1246
|
+
}
|
|
1247
|
+
const GlobalContent = _tiptap_core.Node.create({
|
|
1248
|
+
name: GLOBAL_CONTENT_NODE_TYPE,
|
|
1249
|
+
addOptions() {
|
|
1250
|
+
return {
|
|
1251
|
+
key: GLOBAL_CONTENT_NODE_TYPE,
|
|
1252
|
+
data: {}
|
|
1253
|
+
};
|
|
1254
|
+
},
|
|
1255
|
+
group: "block",
|
|
1256
|
+
selectable: false,
|
|
1257
|
+
draggable: false,
|
|
1258
|
+
atom: true,
|
|
1259
|
+
addAttributes() {
|
|
1260
|
+
return { data: { default: this.options.data } };
|
|
1261
|
+
},
|
|
1262
|
+
parseHTML() {
|
|
1263
|
+
return [{ tag: `div[data-type="${this.name}"]` }];
|
|
1264
|
+
},
|
|
1265
|
+
renderHTML({ HTMLAttributes }) {
|
|
1266
|
+
return ["div", (0, _tiptap_core.mergeAttributes)(HTMLAttributes, {
|
|
1267
|
+
"data-type": this.name,
|
|
1268
|
+
style: "width: 100%; height: 1px; visibility: hidden;"
|
|
1269
|
+
})];
|
|
1270
|
+
},
|
|
1271
|
+
addCommands() {
|
|
1272
|
+
return { setGlobalContent: (key, value) => ({ tr, dispatch }) => {
|
|
1273
|
+
const ensureGlobalPosition = () => {
|
|
1274
|
+
const positions = findGlobalContentPositions(tr.doc);
|
|
1275
|
+
for (let i = positions.length - 1; i > 0; i--) tr.delete(positions[i], positions[i] + 1);
|
|
1276
|
+
const pos = positions[0] ?? -1;
|
|
1277
|
+
if (pos >= 0) cachedGlobalPosition = pos;
|
|
1278
|
+
else {
|
|
1279
|
+
cachedGlobalPosition = 0;
|
|
1280
|
+
tr.insert(0, this.type.create());
|
|
1281
|
+
}
|
|
1282
|
+
};
|
|
1283
|
+
if (dispatch) {
|
|
1284
|
+
ensureGlobalPosition();
|
|
1285
|
+
if (cachedGlobalPosition == null) return false;
|
|
1286
|
+
tr.setNodeAttribute(cachedGlobalPosition, "data", {
|
|
1287
|
+
...tr.doc.nodeAt(cachedGlobalPosition)?.attrs.data,
|
|
1288
|
+
[key]: value
|
|
1289
|
+
});
|
|
1290
|
+
}
|
|
1291
|
+
return true;
|
|
1292
|
+
} };
|
|
1293
|
+
}
|
|
1294
|
+
});
|
|
1295
|
+
|
|
1177
1296
|
//#endregion
|
|
1178
1297
|
//#region src/extensions/hard-break.tsx
|
|
1179
1298
|
const HardBreak = EmailNode.from(_tiptap_extension_hard_break.default, () => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}));
|
|
1180
1299
|
|
|
1300
|
+
//#endregion
|
|
1301
|
+
//#region src/extensions/heading.tsx
|
|
1302
|
+
const Heading = EmailNode.from(_tiptap_extension_heading.Heading.extend({ addNodeView() {
|
|
1303
|
+
return (0, _tiptap_react.ReactNodeViewRenderer)(({ node }) => {
|
|
1304
|
+
const level = node.attrs.level ?? 1;
|
|
1305
|
+
const { class: className, ...rest } = node.attrs;
|
|
1306
|
+
const attrs = {
|
|
1307
|
+
...rest,
|
|
1308
|
+
className: `node-h${level} ${className}`,
|
|
1309
|
+
style: inlineCssToJs(node.attrs.style)
|
|
1310
|
+
};
|
|
1311
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_tiptap_react.NodeViewWrapper, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_react_email_components.Heading, {
|
|
1312
|
+
as: `h${level}`,
|
|
1313
|
+
...attrs,
|
|
1314
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_tiptap_react.NodeViewContent, {})
|
|
1315
|
+
}) });
|
|
1316
|
+
});
|
|
1317
|
+
} }), ({ children, node, style }) => {
|
|
1318
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_react_email_components.Heading, {
|
|
1319
|
+
as: `h${node.attrs?.level ?? 1}`,
|
|
1320
|
+
className: node.attrs?.class || void 0,
|
|
1321
|
+
style: {
|
|
1322
|
+
...style,
|
|
1323
|
+
...inlineCssToJs(node.attrs?.style),
|
|
1324
|
+
...getTextAlignment(node.attrs?.align ?? node.attrs?.alignment)
|
|
1325
|
+
},
|
|
1326
|
+
children
|
|
1327
|
+
});
|
|
1328
|
+
});
|
|
1329
|
+
|
|
1181
1330
|
//#endregion
|
|
1182
1331
|
//#region src/extensions/italic.tsx
|
|
1183
1332
|
const Italic = EmailMark.from(_tiptap_extension_italic.default, ({ children, style }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("em", {
|
|
@@ -1185,6 +1334,160 @@ const Italic = EmailMark.from(_tiptap_extension_italic.default, ({ children, sty
|
|
|
1185
1334
|
children
|
|
1186
1335
|
}));
|
|
1187
1336
|
|
|
1337
|
+
//#endregion
|
|
1338
|
+
//#region src/extensions/preserved-style.tsx
|
|
1339
|
+
const PreservedStyle = EmailMark.create({
|
|
1340
|
+
name: "preservedStyle",
|
|
1341
|
+
addAttributes() {
|
|
1342
|
+
return { style: {
|
|
1343
|
+
default: null,
|
|
1344
|
+
parseHTML: (element) => element.getAttribute("style"),
|
|
1345
|
+
renderHTML: (attributes) => {
|
|
1346
|
+
if (!attributes.style) return {};
|
|
1347
|
+
return { style: attributes.style };
|
|
1348
|
+
}
|
|
1349
|
+
} };
|
|
1350
|
+
},
|
|
1351
|
+
parseHTML() {
|
|
1352
|
+
return [{
|
|
1353
|
+
tag: "span[style]",
|
|
1354
|
+
getAttrs: (element) => {
|
|
1355
|
+
if (typeof element === "string") return false;
|
|
1356
|
+
const style = element.getAttribute("style");
|
|
1357
|
+
if (style && hasPreservableStyles(style)) return { style };
|
|
1358
|
+
return false;
|
|
1359
|
+
}
|
|
1360
|
+
}];
|
|
1361
|
+
},
|
|
1362
|
+
renderHTML({ HTMLAttributes }) {
|
|
1363
|
+
return [
|
|
1364
|
+
"span",
|
|
1365
|
+
(0, _tiptap_core.mergeAttributes)(HTMLAttributes),
|
|
1366
|
+
0
|
|
1367
|
+
];
|
|
1368
|
+
},
|
|
1369
|
+
renderToReactEmail({ children, mark }) {
|
|
1370
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1371
|
+
style: mark.attrs?.style ? inlineCssToJs(mark.attrs.style) : void 0,
|
|
1372
|
+
children
|
|
1373
|
+
});
|
|
1374
|
+
}
|
|
1375
|
+
});
|
|
1376
|
+
const LINK_INDICATOR_STYLES = [
|
|
1377
|
+
"color",
|
|
1378
|
+
"text-decoration",
|
|
1379
|
+
"text-decoration-line",
|
|
1380
|
+
"text-decoration-color",
|
|
1381
|
+
"text-decoration-style"
|
|
1382
|
+
];
|
|
1383
|
+
function parseStyleString(styleString) {
|
|
1384
|
+
const temp = document.createElement("div");
|
|
1385
|
+
temp.style.cssText = styleString;
|
|
1386
|
+
return temp.style;
|
|
1387
|
+
}
|
|
1388
|
+
function hasBackground(style) {
|
|
1389
|
+
const bgColor = style.backgroundColor;
|
|
1390
|
+
const bg = style.background;
|
|
1391
|
+
if (bgColor && bgColor !== "transparent" && bgColor !== "rgba(0, 0, 0, 0)") return true;
|
|
1392
|
+
if (bg && bg !== "transparent" && bg !== "none" && bg !== "rgba(0, 0, 0, 0)") return true;
|
|
1393
|
+
return false;
|
|
1394
|
+
}
|
|
1395
|
+
function hasPreservableStyles(styleString) {
|
|
1396
|
+
return processStylesForUnlink(styleString) !== null;
|
|
1397
|
+
}
|
|
1398
|
+
/**
|
|
1399
|
+
* Processes styles when unlinking:
|
|
1400
|
+
* - Has background (button-like): preserve all styles
|
|
1401
|
+
* - No background: strip link-indicator styles (color, text-decoration), keep the rest
|
|
1402
|
+
*/
|
|
1403
|
+
function processStylesForUnlink(styleString) {
|
|
1404
|
+
if (!styleString) return null;
|
|
1405
|
+
const style = parseStyleString(styleString);
|
|
1406
|
+
if (hasBackground(style)) return styleString;
|
|
1407
|
+
const filtered = [];
|
|
1408
|
+
for (let i = 0; i < style.length; i++) {
|
|
1409
|
+
const prop = style[i];
|
|
1410
|
+
if (LINK_INDICATOR_STYLES.includes(prop)) continue;
|
|
1411
|
+
const value = style.getPropertyValue(prop);
|
|
1412
|
+
if (value) filtered.push(`${prop}: ${value}`);
|
|
1413
|
+
}
|
|
1414
|
+
return filtered.length > 0 ? filtered.join("; ") : null;
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
//#endregion
|
|
1418
|
+
//#region src/extensions/link.tsx
|
|
1419
|
+
const Link = EmailMark.from(_tiptap_extension_link.default, ({ children, mark, style }) => {
|
|
1420
|
+
const linkMarkStyle = mark.attrs?.style ? inlineCssToJs(mark.attrs.style) : {};
|
|
1421
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_react_email_components.Link, {
|
|
1422
|
+
href: mark.attrs?.href ?? void 0,
|
|
1423
|
+
rel: mark.attrs?.rel ?? void 0,
|
|
1424
|
+
style: {
|
|
1425
|
+
...style,
|
|
1426
|
+
...linkMarkStyle
|
|
1427
|
+
},
|
|
1428
|
+
target: mark.attrs?.target ?? void 0,
|
|
1429
|
+
...mark.attrs?.["ses:no-track"] ? { "ses:no-track": mark.attrs["ses:no-track"] } : {},
|
|
1430
|
+
children
|
|
1431
|
+
});
|
|
1432
|
+
}).extend({
|
|
1433
|
+
parseHTML() {
|
|
1434
|
+
return [{
|
|
1435
|
+
tag: "a[target]:not([data-id=\"react-email-button\"])",
|
|
1436
|
+
getAttrs: (node) => {
|
|
1437
|
+
if (typeof node === "string") return false;
|
|
1438
|
+
const element = node;
|
|
1439
|
+
const attrs = {};
|
|
1440
|
+
Array.from(element.attributes).forEach((attr) => {
|
|
1441
|
+
attrs[attr.name] = attr.value;
|
|
1442
|
+
});
|
|
1443
|
+
return attrs;
|
|
1444
|
+
}
|
|
1445
|
+
}, {
|
|
1446
|
+
tag: "a[href]:not([data-id=\"react-email-button\"])",
|
|
1447
|
+
getAttrs: (node) => {
|
|
1448
|
+
if (typeof node === "string") return false;
|
|
1449
|
+
const element = node;
|
|
1450
|
+
const attrs = {};
|
|
1451
|
+
Array.from(element.attributes).forEach((attr) => {
|
|
1452
|
+
attrs[attr.name] = attr.value;
|
|
1453
|
+
});
|
|
1454
|
+
return attrs;
|
|
1455
|
+
}
|
|
1456
|
+
}];
|
|
1457
|
+
},
|
|
1458
|
+
addAttributes() {
|
|
1459
|
+
return {
|
|
1460
|
+
...this.parent?.(),
|
|
1461
|
+
"ses:no-track": {
|
|
1462
|
+
default: null,
|
|
1463
|
+
parseHTML: (element) => element.getAttribute("ses:no-track")
|
|
1464
|
+
}
|
|
1465
|
+
};
|
|
1466
|
+
},
|
|
1467
|
+
addCommands() {
|
|
1468
|
+
return {
|
|
1469
|
+
...this.parent?.(),
|
|
1470
|
+
unsetLink: () => ({ state, chain }) => {
|
|
1471
|
+
const { from } = state.selection;
|
|
1472
|
+
const linkStyle = state.doc.resolve(from).marks().find((m) => m.type.name === "link")?.attrs?.style ?? null;
|
|
1473
|
+
const preservedStyle = processStylesForUnlink(linkStyle);
|
|
1474
|
+
const shouldRemoveUnderline = preservedStyle !== linkStyle;
|
|
1475
|
+
if (preservedStyle) {
|
|
1476
|
+
const cmd = chain().extendMarkRange("link").unsetMark("link").setMark("preservedStyle", { style: preservedStyle });
|
|
1477
|
+
return shouldRemoveUnderline ? cmd.unsetMark("underline").run() : cmd.run();
|
|
1478
|
+
}
|
|
1479
|
+
return chain().extendMarkRange("link").unsetMark("link").unsetMark("underline").run();
|
|
1480
|
+
}
|
|
1481
|
+
};
|
|
1482
|
+
},
|
|
1483
|
+
addKeyboardShortcuts() {
|
|
1484
|
+
return { "Mod-k": () => {
|
|
1485
|
+
editorEventBus.dispatch("bubble-menu:add-link", void 0);
|
|
1486
|
+
return this.editor.chain().focus().toggleLink({ href: "" }).run();
|
|
1487
|
+
} };
|
|
1488
|
+
}
|
|
1489
|
+
});
|
|
1490
|
+
|
|
1188
1491
|
//#endregion
|
|
1189
1492
|
//#region src/extensions/list-item.tsx
|
|
1190
1493
|
const ListItem = EmailNode.from(_tiptap_extension_list_item.default, ({ children, node, style }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
|
|
@@ -1309,86 +1612,6 @@ const Placeholder = _tiptap_extension_placeholder.default.configure({
|
|
|
1309
1612
|
includeChildren: true
|
|
1310
1613
|
});
|
|
1311
1614
|
|
|
1312
|
-
//#endregion
|
|
1313
|
-
//#region src/extensions/preserved-style.tsx
|
|
1314
|
-
const PreservedStyle = EmailMark.create({
|
|
1315
|
-
name: "preservedStyle",
|
|
1316
|
-
addAttributes() {
|
|
1317
|
-
return { style: {
|
|
1318
|
-
default: null,
|
|
1319
|
-
parseHTML: (element) => element.getAttribute("style"),
|
|
1320
|
-
renderHTML: (attributes) => {
|
|
1321
|
-
if (!attributes.style) return {};
|
|
1322
|
-
return { style: attributes.style };
|
|
1323
|
-
}
|
|
1324
|
-
} };
|
|
1325
|
-
},
|
|
1326
|
-
parseHTML() {
|
|
1327
|
-
return [{
|
|
1328
|
-
tag: "span[style]",
|
|
1329
|
-
getAttrs: (element) => {
|
|
1330
|
-
if (typeof element === "string") return false;
|
|
1331
|
-
const style = element.getAttribute("style");
|
|
1332
|
-
if (style && hasPreservableStyles(style)) return { style };
|
|
1333
|
-
return false;
|
|
1334
|
-
}
|
|
1335
|
-
}];
|
|
1336
|
-
},
|
|
1337
|
-
renderHTML({ HTMLAttributes }) {
|
|
1338
|
-
return [
|
|
1339
|
-
"span",
|
|
1340
|
-
(0, _tiptap_core.mergeAttributes)(HTMLAttributes),
|
|
1341
|
-
0
|
|
1342
|
-
];
|
|
1343
|
-
},
|
|
1344
|
-
renderToReactEmail({ children, mark }) {
|
|
1345
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1346
|
-
style: mark.attrs?.style ? inlineCssToJs(mark.attrs.style) : void 0,
|
|
1347
|
-
children
|
|
1348
|
-
});
|
|
1349
|
-
}
|
|
1350
|
-
});
|
|
1351
|
-
const LINK_INDICATOR_STYLES = [
|
|
1352
|
-
"color",
|
|
1353
|
-
"text-decoration",
|
|
1354
|
-
"text-decoration-line",
|
|
1355
|
-
"text-decoration-color",
|
|
1356
|
-
"text-decoration-style"
|
|
1357
|
-
];
|
|
1358
|
-
function parseStyleString(styleString) {
|
|
1359
|
-
const temp = document.createElement("div");
|
|
1360
|
-
temp.style.cssText = styleString;
|
|
1361
|
-
return temp.style;
|
|
1362
|
-
}
|
|
1363
|
-
function hasBackground(style) {
|
|
1364
|
-
const bgColor = style.backgroundColor;
|
|
1365
|
-
const bg = style.background;
|
|
1366
|
-
if (bgColor && bgColor !== "transparent" && bgColor !== "rgba(0, 0, 0, 0)") return true;
|
|
1367
|
-
if (bg && bg !== "transparent" && bg !== "none" && bg !== "rgba(0, 0, 0, 0)") return true;
|
|
1368
|
-
return false;
|
|
1369
|
-
}
|
|
1370
|
-
function hasPreservableStyles(styleString) {
|
|
1371
|
-
return processStylesForUnlink(styleString) !== null;
|
|
1372
|
-
}
|
|
1373
|
-
/**
|
|
1374
|
-
* Processes styles when unlinking:
|
|
1375
|
-
* - Has background (button-like): preserve all styles
|
|
1376
|
-
* - No background: strip link-indicator styles (color, text-decoration), keep the rest
|
|
1377
|
-
*/
|
|
1378
|
-
function processStylesForUnlink(styleString) {
|
|
1379
|
-
if (!styleString) return null;
|
|
1380
|
-
const style = parseStyleString(styleString);
|
|
1381
|
-
if (hasBackground(style)) return styleString;
|
|
1382
|
-
const filtered = [];
|
|
1383
|
-
for (let i = 0; i < style.length; i++) {
|
|
1384
|
-
const prop = style[i];
|
|
1385
|
-
if (LINK_INDICATOR_STYLES.includes(prop)) continue;
|
|
1386
|
-
const value = style.getPropertyValue(prop);
|
|
1387
|
-
if (value) filtered.push(`${prop}: ${value}`);
|
|
1388
|
-
}
|
|
1389
|
-
return filtered.length > 0 ? filtered.join("; ") : null;
|
|
1390
|
-
}
|
|
1391
|
-
|
|
1392
1615
|
//#endregion
|
|
1393
1616
|
//#region src/extensions/preview-text.ts
|
|
1394
1617
|
const PreviewText = _tiptap_core.Node.create({
|
|
@@ -1980,44 +2203,13 @@ const ColumnsColumn = EmailNode.create({
|
|
|
1980
2203
|
|
|
1981
2204
|
//#endregion
|
|
1982
2205
|
//#region src/extensions/index.ts
|
|
1983
|
-
const
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
bold: false,
|
|
1991
|
-
italic: false,
|
|
1992
|
-
strike: false,
|
|
1993
|
-
code: false,
|
|
1994
|
-
paragraph: false,
|
|
1995
|
-
bulletList: false,
|
|
1996
|
-
orderedList: false,
|
|
1997
|
-
listItem: false,
|
|
1998
|
-
blockquote: false,
|
|
1999
|
-
hardBreak: false,
|
|
2000
|
-
gapcursor: false,
|
|
2001
|
-
codeBlock: false,
|
|
2002
|
-
horizontalRule: false,
|
|
2003
|
-
dropcursor: {
|
|
2004
|
-
color: "#61a8f8",
|
|
2005
|
-
class: "rounded-full animate-[fade-in_300ms_ease-in-out] !z-40",
|
|
2006
|
-
width: 4
|
|
2007
|
-
}
|
|
2008
|
-
}),
|
|
2009
|
-
CodeBlockPrism.configure({
|
|
2010
|
-
defaultLanguage: "javascript",
|
|
2011
|
-
HTMLAttributes: { class: "prism node-codeBlock" }
|
|
2012
|
-
}),
|
|
2013
|
-
Code.configure({ HTMLAttributes: {
|
|
2014
|
-
class: "node-inlineCode",
|
|
2015
|
-
spellcheck: "false"
|
|
2016
|
-
} }),
|
|
2017
|
-
Paragraph.configure({ HTMLAttributes: { class: "node-paragraph" } }),
|
|
2018
|
-
BulletList.configure({ HTMLAttributes: { class: "node-bulletList" } }),
|
|
2019
|
-
OrderedList.configure({ HTMLAttributes: { class: "node-orderedList" } }),
|
|
2020
|
-
Blockquote.configure({ HTMLAttributes: { class: "node-blockquote" } }),
|
|
2206
|
+
const starterKitExtensions = {
|
|
2207
|
+
CodeBlockPrism,
|
|
2208
|
+
Code,
|
|
2209
|
+
Paragraph,
|
|
2210
|
+
BulletList,
|
|
2211
|
+
OrderedList,
|
|
2212
|
+
Blockquote,
|
|
2021
2213
|
ListItem,
|
|
2022
2214
|
HardBreak,
|
|
2023
2215
|
Italic,
|
|
@@ -2025,6 +2217,9 @@ const coreExtensions = [
|
|
|
2025
2217
|
PreviewText,
|
|
2026
2218
|
Bold,
|
|
2027
2219
|
Strike,
|
|
2220
|
+
Heading,
|
|
2221
|
+
Divider,
|
|
2222
|
+
Link,
|
|
2028
2223
|
Sup,
|
|
2029
2224
|
Uppercase,
|
|
2030
2225
|
PreservedStyle,
|
|
@@ -2036,80 +2231,162 @@ const coreExtensions = [
|
|
|
2036
2231
|
Div,
|
|
2037
2232
|
Button,
|
|
2038
2233
|
Section,
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2234
|
+
GlobalContent,
|
|
2235
|
+
AlignmentAttribute,
|
|
2236
|
+
StyleAttribute,
|
|
2237
|
+
ClassAttribute,
|
|
2238
|
+
MaxNesting
|
|
2239
|
+
};
|
|
2240
|
+
const StarterKit = _tiptap_core.Extension.create({
|
|
2241
|
+
name: "reactEmailStarterKit",
|
|
2242
|
+
addOptions() {
|
|
2243
|
+
return {
|
|
2244
|
+
TiptapStarterKit: {},
|
|
2245
|
+
CodeBlockPrism: {
|
|
2246
|
+
defaultLanguage: "javascript",
|
|
2247
|
+
HTMLAttributes: { class: "prism node-codeBlock" }
|
|
2248
|
+
},
|
|
2249
|
+
Code: { HTMLAttributes: {
|
|
2250
|
+
class: "node-inlineCode",
|
|
2251
|
+
spellcheck: "false"
|
|
2252
|
+
} },
|
|
2253
|
+
Paragraph: { HTMLAttributes: { class: "node-paragraph" } },
|
|
2254
|
+
BulletList: { HTMLAttributes: { class: "node-bulletList" } },
|
|
2255
|
+
OrderedList: { HTMLAttributes: { class: "node-orderedList" } },
|
|
2256
|
+
Blockquote: { HTMLAttributes: { class: "node-blockquote" } },
|
|
2257
|
+
ListItem: {},
|
|
2258
|
+
HardBreak: {},
|
|
2259
|
+
Italic: {},
|
|
2260
|
+
Placeholder: {},
|
|
2261
|
+
PreviewText: {},
|
|
2262
|
+
Bold: {},
|
|
2263
|
+
Strike: {},
|
|
2264
|
+
Heading: {},
|
|
2265
|
+
Divider: {},
|
|
2266
|
+
Link: {},
|
|
2267
|
+
Sup: {},
|
|
2268
|
+
Uppercase: {},
|
|
2269
|
+
PreservedStyle: {},
|
|
2270
|
+
Table: {},
|
|
2271
|
+
TableRow: {},
|
|
2272
|
+
TableCell: {},
|
|
2273
|
+
TableHeader: {},
|
|
2274
|
+
Body: {},
|
|
2275
|
+
Div: {},
|
|
2276
|
+
Button: {},
|
|
2277
|
+
Section: {},
|
|
2278
|
+
GlobalContent: {},
|
|
2279
|
+
AlignmentAttribute: { types: [
|
|
2280
|
+
"heading",
|
|
2281
|
+
"paragraph",
|
|
2282
|
+
"image",
|
|
2283
|
+
"blockquote",
|
|
2284
|
+
"codeBlock",
|
|
2285
|
+
"bulletList",
|
|
2286
|
+
"orderedList",
|
|
2287
|
+
"listItem",
|
|
2288
|
+
"button",
|
|
2289
|
+
"youtube",
|
|
2290
|
+
"twitter",
|
|
2291
|
+
"table",
|
|
2292
|
+
"tableRow",
|
|
2293
|
+
"tableCell",
|
|
2294
|
+
"tableHeader",
|
|
2295
|
+
"columnsColumn"
|
|
2296
|
+
] },
|
|
2297
|
+
StyleAttribute: { types: [
|
|
2298
|
+
"heading",
|
|
2299
|
+
"paragraph",
|
|
2300
|
+
"image",
|
|
2301
|
+
"blockquote",
|
|
2302
|
+
"codeBlock",
|
|
2303
|
+
"bulletList",
|
|
2304
|
+
"orderedList",
|
|
2305
|
+
"listItem",
|
|
2306
|
+
"button",
|
|
2307
|
+
"youtube",
|
|
2308
|
+
"twitter",
|
|
2309
|
+
"horizontalRule",
|
|
2310
|
+
"footer",
|
|
2311
|
+
"section",
|
|
2312
|
+
"div",
|
|
2313
|
+
"body",
|
|
2314
|
+
"table",
|
|
2315
|
+
"tableRow",
|
|
2316
|
+
"tableCell",
|
|
2317
|
+
"tableHeader",
|
|
2318
|
+
"columnsColumn",
|
|
2319
|
+
"link"
|
|
2320
|
+
] },
|
|
2321
|
+
ClassAttribute: { types: [
|
|
2322
|
+
"heading",
|
|
2323
|
+
"paragraph",
|
|
2324
|
+
"image",
|
|
2325
|
+
"blockquote",
|
|
2326
|
+
"bulletList",
|
|
2327
|
+
"orderedList",
|
|
2328
|
+
"listItem",
|
|
2329
|
+
"button",
|
|
2330
|
+
"youtube",
|
|
2331
|
+
"twitter",
|
|
2332
|
+
"horizontalRule",
|
|
2333
|
+
"footer",
|
|
2334
|
+
"section",
|
|
2335
|
+
"div",
|
|
2336
|
+
"body",
|
|
2337
|
+
"table",
|
|
2338
|
+
"tableRow",
|
|
2339
|
+
"tableCell",
|
|
2340
|
+
"tableHeader",
|
|
2341
|
+
"columnsColumn",
|
|
2342
|
+
"link"
|
|
2343
|
+
] },
|
|
2344
|
+
MaxNesting: {
|
|
2345
|
+
maxDepth: 50,
|
|
2346
|
+
nodeTypes: [
|
|
2347
|
+
"section",
|
|
2348
|
+
"bulletList",
|
|
2349
|
+
"orderedList"
|
|
2350
|
+
]
|
|
2351
|
+
}
|
|
2352
|
+
};
|
|
2353
|
+
},
|
|
2354
|
+
addExtensions() {
|
|
2355
|
+
const extensions = [];
|
|
2356
|
+
if (this.options.TiptapStarterKit !== false) extensions.push(_tiptap_starter_kit.default.configure({
|
|
2357
|
+
undoRedo: false,
|
|
2358
|
+
heading: false,
|
|
2359
|
+
link: false,
|
|
2360
|
+
underline: false,
|
|
2361
|
+
trailingNode: false,
|
|
2362
|
+
bold: false,
|
|
2363
|
+
italic: false,
|
|
2364
|
+
strike: false,
|
|
2365
|
+
code: false,
|
|
2366
|
+
paragraph: false,
|
|
2367
|
+
bulletList: false,
|
|
2368
|
+
orderedList: false,
|
|
2369
|
+
listItem: false,
|
|
2370
|
+
blockquote: false,
|
|
2371
|
+
hardBreak: false,
|
|
2372
|
+
gapcursor: false,
|
|
2373
|
+
codeBlock: false,
|
|
2374
|
+
horizontalRule: false,
|
|
2375
|
+
dropcursor: {
|
|
2376
|
+
color: "#61a8f8",
|
|
2377
|
+
class: "rounded-full animate-[fade-in_300ms_ease-in-out] !z-40",
|
|
2378
|
+
width: 4
|
|
2379
|
+
},
|
|
2380
|
+
...this.options.TiptapStarterKit
|
|
2381
|
+
}));
|
|
2382
|
+
for (const [name, extension] of Object.entries(starterKitExtensions)) {
|
|
2383
|
+
const key = name;
|
|
2384
|
+
const extensionOptions = this.options[key];
|
|
2385
|
+
if (extensionOptions !== false) extensions.push(extension.configure(extensionOptions));
|
|
2386
|
+
}
|
|
2387
|
+
return extensions;
|
|
2388
|
+
}
|
|
2389
|
+
});
|
|
2113
2390
|
|
|
2114
2391
|
//#endregion
|
|
2115
2392
|
//#region src/core/create-drop-handler.ts
|
|
@@ -2268,13 +2545,14 @@ function useEditor({ content, extensions = [], onUpdate, onPaste, onUploadImage,
|
|
|
2268
2545
|
const [contentError, setContentError] = react.useState(null);
|
|
2269
2546
|
const isCollaborative = hasCollaborationExtension(extensions);
|
|
2270
2547
|
const effectiveExtensions = react.useMemo(() => [
|
|
2271
|
-
|
|
2548
|
+
StarterKit,
|
|
2272
2549
|
...isCollaborative ? [] : [_tiptap_extensions.UndoRedo],
|
|
2273
2550
|
...extensions
|
|
2274
2551
|
], [extensions, isCollaborative]);
|
|
2275
2552
|
const editor = (0, _tiptap_react.useEditor)({
|
|
2276
2553
|
content: isCollaborative ? void 0 : content,
|
|
2277
2554
|
extensions: effectiveExtensions,
|
|
2555
|
+
editable,
|
|
2278
2556
|
immediatelyRender: false,
|
|
2279
2557
|
enableContentCheck: true,
|
|
2280
2558
|
onContentError({ editor: editor$1, error, disableCollaboration }) {
|
|
@@ -3930,6 +4208,7 @@ exports.Div = Div;
|
|
|
3930
4208
|
exports.EmailNode = EmailNode;
|
|
3931
4209
|
exports.FOUR_COLUMNS = FOUR_COLUMNS;
|
|
3932
4210
|
exports.FourColumns = FourColumns;
|
|
4211
|
+
exports.GlobalContent = GlobalContent;
|
|
3933
4212
|
exports.H1 = H1;
|
|
3934
4213
|
exports.H2 = H2;
|
|
3935
4214
|
exports.H3 = H3;
|
|
@@ -3964,6 +4243,7 @@ exports.QUOTE = QUOTE;
|
|
|
3964
4243
|
exports.SECTION = SECTION;
|
|
3965
4244
|
exports.Section = Section;
|
|
3966
4245
|
exports.SlashCommand = SlashCommand;
|
|
4246
|
+
exports.StarterKit = StarterKit;
|
|
3967
4247
|
exports.Strike = Strike;
|
|
3968
4248
|
exports.StyleAttribute = StyleAttribute;
|
|
3969
4249
|
exports.Sup = Sup;
|
|
@@ -3978,12 +4258,12 @@ exports.ThreeColumns = ThreeColumns;
|
|
|
3978
4258
|
exports.TwoColumns = TwoColumns;
|
|
3979
4259
|
exports.Uppercase = Uppercase;
|
|
3980
4260
|
exports.composeReactEmail = composeReactEmail;
|
|
3981
|
-
exports.coreExtensions = coreExtensions;
|
|
3982
4261
|
exports.createSlashCommand = createSlashCommand;
|
|
3983
4262
|
exports.defaultSlashCommands = defaultSlashCommands;
|
|
3984
4263
|
exports.editorEventBus = editorEventBus;
|
|
3985
4264
|
exports.filterAndRankItems = filterAndRankItems;
|
|
3986
4265
|
exports.getColumnsDepth = getColumnsDepth;
|
|
4266
|
+
exports.getGlobalContent = getGlobalContent;
|
|
3987
4267
|
exports.isAtMaxColumnsDepth = isAtMaxColumnsDepth;
|
|
3988
4268
|
exports.isInsideNode = isInsideNode;
|
|
3989
4269
|
exports.processStylesForUnlink = processStylesForUnlink;
|