@malaya_jeeva/rich-text-editor 1.0.8 → 1.0.10

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.js CHANGED
@@ -224,7 +224,42 @@ function getColorAtCursor(editor) {
224
224
  }
225
225
  return "#000000";
226
226
  }
227
+ function sanitizeScriptTags(html) {
228
+ const div = document.createElement("div");
229
+ div.innerHTML = html;
230
+ div.querySelectorAll("script").forEach((script) => script.remove());
231
+ const riskyAttrs = [
232
+ "onabort",
233
+ "onblur",
234
+ "onchange",
235
+ "onclick",
236
+ "ondblclick",
237
+ "onerror",
238
+ "onfocus",
239
+ "onkeydown",
240
+ "onkeypress",
241
+ "onkeyup",
242
+ "onload",
243
+ "onmousedown",
244
+ "onmousemove",
245
+ "onmouseout",
246
+ "onmouseover",
247
+ "onmouseup",
248
+ "onresize",
249
+ "onscroll",
250
+ "onselect",
251
+ "onsubmit",
252
+ "onunload"
253
+ ];
254
+ div.querySelectorAll("*").forEach((el) => {
255
+ riskyAttrs.forEach((attr) => {
256
+ if (el.hasAttribute(attr)) el.removeAttribute(attr);
257
+ });
258
+ });
259
+ return div.innerHTML;
260
+ }
227
261
  function prettifyHtml(html) {
262
+ const cleanHtml = sanitizeScriptTags(html);
228
263
  const INLINE = /* @__PURE__ */ new Set(["a", "b", "i", "u", "em", "strong", "span", "code", "br", "small", "sub", "sup"]);
229
264
  let indent = 0;
230
265
  const pad = () => " ".repeat(indent);
@@ -1207,16 +1242,28 @@ function RichTextEditor({ value, onChange, toolbar }) {
1207
1242
  else setLinkInfoFP(null);
1208
1243
  const txt = (_b = (_a2 = editorRef.current) == null ? void 0 : _a2.innerText) != null ? _b : "";
1209
1244
  setWords(txt.trim() ? txt.trim().split(/\s+/).length : 0);
1210
- onChange == null ? void 0 : onChange((_d = (_c = editorRef.current) == null ? void 0 : _c.innerHTML) != null ? _d : "");
1211
- }, [onChange, calcFloat, linkBar]);
1245
+ onChange == null ? void 0 : onChange(sanitizeScriptTags((_d = (_c = editorRef.current) == null ? void 0 : _c.innerHTML) != null ? _d : ""));
1246
+ }, [onChange, calcFloat, linkBar, sanitizeScriptTags]);
1247
+ const fixListInParagraph = (0, import_react5.useCallback)(() => {
1248
+ var _a2;
1249
+ (_a2 = editorRef.current) == null ? void 0 : _a2.querySelectorAll("p > ol, p > ul").forEach((list) => {
1250
+ var _a3;
1251
+ const p = list.parentElement;
1252
+ p.insertAdjacentElement("afterend", list);
1253
+ if (!((_a3 = p.textContent) == null ? void 0 : _a3.trim()) && !p.querySelector("img, br")) p.remove();
1254
+ });
1255
+ }, []);
1212
1256
  const exec = (0, import_react5.useCallback)((cmd, val = null) => {
1213
1257
  var _a2;
1214
1258
  (_a2 = editorRef.current) == null ? void 0 : _a2.focus();
1215
1259
  document.execCommand(cmd, false, val != null ? val : void 0);
1216
1260
  fixFontTags();
1217
1261
  fixListNesting();
1262
+ if (cmd === "insertUnorderedList" || cmd === "insertOrderedList") {
1263
+ fixListInParagraph();
1264
+ }
1218
1265
  refresh();
1219
- }, [fixFontTags, fixListNesting, refresh]);
1266
+ }, [fixFontTags, fixListNesting, fixListInParagraph, refresh]);
1220
1267
  const insertImage = (0, import_react5.useCallback)((src) => {
1221
1268
  var _a2;
1222
1269
  (_a2 = editorRef.current) == null ? void 0 : _a2.focus();
@@ -1263,6 +1310,16 @@ function RichTextEditor({ value, onChange, toolbar }) {
1263
1310
  var _a2, _b;
1264
1311
  clearSelection();
1265
1312
  clearImageSel();
1313
+ if (!e.ctrlKey && !e.metaKey && !e.altKey && e.key.length === 1) {
1314
+ const sel = window.getSelection();
1315
+ if (sel == null ? void 0 : sel.rangeCount) {
1316
+ const anchor = sel.anchorNode;
1317
+ const parent = (anchor == null ? void 0 : anchor.nodeType) === Node.TEXT_NODE ? anchor.parentElement : anchor;
1318
+ if (parent === editorRef.current) {
1319
+ document.execCommand("formatBlock", false, fmt.block || "p");
1320
+ }
1321
+ }
1322
+ }
1266
1323
  if (e.key === "Tab") {
1267
1324
  e.preventDefault();
1268
1325
  const cell = getCurrentCell();
@@ -1294,7 +1351,7 @@ function RichTextEditor({ value, onChange, toolbar }) {
1294
1351
  exec("underline");
1295
1352
  }
1296
1353
  }
1297
- }, [exec, clearSelection, clearImageSel]);
1354
+ }, [exec, clearSelection, clearImageSel, fmt.block]);
1298
1355
  const insertTable = (rows, cols) => {
1299
1356
  var _a2;
1300
1357
  (_a2 = editorRef.current) == null ? void 0 : _a2.focus();
@@ -1449,7 +1506,7 @@ function RichTextEditor({ value, onChange, toolbar }) {
1449
1506
  setIsCode(true);
1450
1507
  };
1451
1508
  const toVisual = () => {
1452
- if (editorRef.current) editorRef.current.innerHTML = codeVal;
1509
+ if (editorRef.current) editorRef.current.innerHTML = sanitizeScriptTags(codeVal);
1453
1510
  setIsCode(false);
1454
1511
  refresh();
1455
1512
  };
@@ -1460,7 +1517,8 @@ function RichTextEditor({ value, onChange, toolbar }) {
1460
1517
  };
1461
1518
  (0, import_react5.useEffect)(() => {
1462
1519
  if (editorRef.current) {
1463
- editorRef.current.innerHTML = value != null ? value : "<p>Start writing here...</p>";
1520
+ document.execCommand("defaultParagraphSeparator", false, "p");
1521
+ editorRef.current.innerHTML = sanitizeScriptTags(value != null ? value : "<p>Start writing here...</p>");
1464
1522
  refresh();
1465
1523
  }
1466
1524
  }, []);
package/dist/index.mjs CHANGED
@@ -203,7 +203,42 @@ function getColorAtCursor(editor) {
203
203
  }
204
204
  return "#000000";
205
205
  }
206
+ function sanitizeScriptTags(html) {
207
+ const div = document.createElement("div");
208
+ div.innerHTML = html;
209
+ div.querySelectorAll("script").forEach((script) => script.remove());
210
+ const riskyAttrs = [
211
+ "onabort",
212
+ "onblur",
213
+ "onchange",
214
+ "onclick",
215
+ "ondblclick",
216
+ "onerror",
217
+ "onfocus",
218
+ "onkeydown",
219
+ "onkeypress",
220
+ "onkeyup",
221
+ "onload",
222
+ "onmousedown",
223
+ "onmousemove",
224
+ "onmouseout",
225
+ "onmouseover",
226
+ "onmouseup",
227
+ "onresize",
228
+ "onscroll",
229
+ "onselect",
230
+ "onsubmit",
231
+ "onunload"
232
+ ];
233
+ div.querySelectorAll("*").forEach((el) => {
234
+ riskyAttrs.forEach((attr) => {
235
+ if (el.hasAttribute(attr)) el.removeAttribute(attr);
236
+ });
237
+ });
238
+ return div.innerHTML;
239
+ }
206
240
  function prettifyHtml(html) {
241
+ const cleanHtml = sanitizeScriptTags(html);
207
242
  const INLINE = /* @__PURE__ */ new Set(["a", "b", "i", "u", "em", "strong", "span", "code", "br", "small", "sub", "sup"]);
208
243
  let indent = 0;
209
244
  const pad = () => " ".repeat(indent);
@@ -1186,16 +1221,28 @@ function RichTextEditor({ value, onChange, toolbar }) {
1186
1221
  else setLinkInfoFP(null);
1187
1222
  const txt = (_b = (_a2 = editorRef.current) == null ? void 0 : _a2.innerText) != null ? _b : "";
1188
1223
  setWords(txt.trim() ? txt.trim().split(/\s+/).length : 0);
1189
- onChange == null ? void 0 : onChange((_d = (_c = editorRef.current) == null ? void 0 : _c.innerHTML) != null ? _d : "");
1190
- }, [onChange, calcFloat, linkBar]);
1224
+ onChange == null ? void 0 : onChange(sanitizeScriptTags((_d = (_c = editorRef.current) == null ? void 0 : _c.innerHTML) != null ? _d : ""));
1225
+ }, [onChange, calcFloat, linkBar, sanitizeScriptTags]);
1226
+ const fixListInParagraph = useCallback3(() => {
1227
+ var _a2;
1228
+ (_a2 = editorRef.current) == null ? void 0 : _a2.querySelectorAll("p > ol, p > ul").forEach((list) => {
1229
+ var _a3;
1230
+ const p = list.parentElement;
1231
+ p.insertAdjacentElement("afterend", list);
1232
+ if (!((_a3 = p.textContent) == null ? void 0 : _a3.trim()) && !p.querySelector("img, br")) p.remove();
1233
+ });
1234
+ }, []);
1191
1235
  const exec = useCallback3((cmd, val = null) => {
1192
1236
  var _a2;
1193
1237
  (_a2 = editorRef.current) == null ? void 0 : _a2.focus();
1194
1238
  document.execCommand(cmd, false, val != null ? val : void 0);
1195
1239
  fixFontTags();
1196
1240
  fixListNesting();
1241
+ if (cmd === "insertUnorderedList" || cmd === "insertOrderedList") {
1242
+ fixListInParagraph();
1243
+ }
1197
1244
  refresh();
1198
- }, [fixFontTags, fixListNesting, refresh]);
1245
+ }, [fixFontTags, fixListNesting, fixListInParagraph, refresh]);
1199
1246
  const insertImage = useCallback3((src) => {
1200
1247
  var _a2;
1201
1248
  (_a2 = editorRef.current) == null ? void 0 : _a2.focus();
@@ -1242,6 +1289,16 @@ function RichTextEditor({ value, onChange, toolbar }) {
1242
1289
  var _a2, _b;
1243
1290
  clearSelection();
1244
1291
  clearImageSel();
1292
+ if (!e.ctrlKey && !e.metaKey && !e.altKey && e.key.length === 1) {
1293
+ const sel = window.getSelection();
1294
+ if (sel == null ? void 0 : sel.rangeCount) {
1295
+ const anchor = sel.anchorNode;
1296
+ const parent = (anchor == null ? void 0 : anchor.nodeType) === Node.TEXT_NODE ? anchor.parentElement : anchor;
1297
+ if (parent === editorRef.current) {
1298
+ document.execCommand("formatBlock", false, fmt.block || "p");
1299
+ }
1300
+ }
1301
+ }
1245
1302
  if (e.key === "Tab") {
1246
1303
  e.preventDefault();
1247
1304
  const cell = getCurrentCell();
@@ -1273,7 +1330,7 @@ function RichTextEditor({ value, onChange, toolbar }) {
1273
1330
  exec("underline");
1274
1331
  }
1275
1332
  }
1276
- }, [exec, clearSelection, clearImageSel]);
1333
+ }, [exec, clearSelection, clearImageSel, fmt.block]);
1277
1334
  const insertTable = (rows, cols) => {
1278
1335
  var _a2;
1279
1336
  (_a2 = editorRef.current) == null ? void 0 : _a2.focus();
@@ -1428,7 +1485,7 @@ function RichTextEditor({ value, onChange, toolbar }) {
1428
1485
  setIsCode(true);
1429
1486
  };
1430
1487
  const toVisual = () => {
1431
- if (editorRef.current) editorRef.current.innerHTML = codeVal;
1488
+ if (editorRef.current) editorRef.current.innerHTML = sanitizeScriptTags(codeVal);
1432
1489
  setIsCode(false);
1433
1490
  refresh();
1434
1491
  };
@@ -1439,7 +1496,8 @@ function RichTextEditor({ value, onChange, toolbar }) {
1439
1496
  };
1440
1497
  useEffect3(() => {
1441
1498
  if (editorRef.current) {
1442
- editorRef.current.innerHTML = value != null ? value : "<p>Start writing here...</p>";
1499
+ document.execCommand("defaultParagraphSeparator", false, "p");
1500
+ editorRef.current.innerHTML = sanitizeScriptTags(value != null ? value : "<p>Start writing here...</p>");
1443
1501
  refresh();
1444
1502
  }
1445
1503
  }, []);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@malaya_jeeva/rich-text-editor",
3
- "version": "1.0.8",
3
+ "version": "1.0.10",
4
4
  "description": "Custom React Rich Text Editor",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",