@malaya_jeeva/rich-text-editor 1.0.7 → 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/dist/index.js CHANGED
@@ -66,7 +66,7 @@ var PALETTE = [
66
66
  ];
67
67
  var CSS = `
68
68
  *{box-sizing:border-box;}
69
- .rte-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:1px;padding:4px 8px;background:#f8f8f8;border-bottom:1px solid #e0e0e0;}
69
+ .rte-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:1px;padding:4px 8px;background:#f8f8f8;border-bottom:1px solid #e0e0e0;position: sticky;top: 0;z-index: 9;}
70
70
  @media(prefers-color-scheme:dark){.rte-toolbar{background:#1e1e1e;border-color:#333;}}
71
71
  .rte-btn{background:transparent;border:none;border-radius:3px;cursor:pointer;height:30px;min-width:30px;padding:0 6px;color:#444;font-size:13px;font-weight:500;font-family:var(--font-sans);display:inline-flex;align-items:center;justify-content:center;user-select:none;white-space:nowrap;transition:background 0.1s;flex-shrink:0;}
72
72
  .rte-btn:hover{background:#e8e8e8;}.rte-btn.active{background:#d0e4ff;color:#1a5fb4;}
@@ -170,6 +170,12 @@ var CSS = `
170
170
  .rte-ie-apply{flex:1;height:26px;background:#1a6fc4;color:#fff;border:none;border-radius:4px;font-size:11px;font-weight:600;cursor:pointer;}
171
171
  .rte-ie-remove{flex:1;height:26px;background:#fdecea;color:#c0392b;border:1px solid #f5c6c2;border-radius:4px;font-size:11px;cursor:pointer;}
172
172
  .rte-handle{position:absolute;width:10px;height:10px;background:#fff;border:2px solid #1a5fb4;border-radius:2px;pointer-events:all;z-index:53;}
173
+ .customeditor {
174
+ max-height: 350px;
175
+ overflow-y: auto;
176
+ position: relative;
177
+ }
178
+
173
179
  `;
174
180
 
175
181
  // src/rte/utils.ts
@@ -218,7 +224,42 @@ function getColorAtCursor(editor) {
218
224
  }
219
225
  return "#000000";
220
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
+ }
221
261
  function prettifyHtml(html) {
262
+ const cleanHtml = sanitizeScriptTags(html);
222
263
  const INLINE = /* @__PURE__ */ new Set(["a", "b", "i", "u", "em", "strong", "span", "code", "br", "small", "sub", "sup"]);
223
264
  let indent = 0;
224
265
  const pad = () => " ".repeat(indent);
@@ -1201,8 +1242,8 @@ function RichTextEditor({ value, onChange, toolbar }) {
1201
1242
  else setLinkInfoFP(null);
1202
1243
  const txt = (_b = (_a2 = editorRef.current) == null ? void 0 : _a2.innerText) != null ? _b : "";
1203
1244
  setWords(txt.trim() ? txt.trim().split(/\s+/).length : 0);
1204
- onChange == null ? void 0 : onChange((_d = (_c = editorRef.current) == null ? void 0 : _c.innerHTML) != null ? _d : "");
1205
- }, [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]);
1206
1247
  const exec = (0, import_react5.useCallback)((cmd, val = null) => {
1207
1248
  var _a2;
1208
1249
  (_a2 = editorRef.current) == null ? void 0 : _a2.focus();
@@ -1443,7 +1484,7 @@ function RichTextEditor({ value, onChange, toolbar }) {
1443
1484
  setIsCode(true);
1444
1485
  };
1445
1486
  const toVisual = () => {
1446
- if (editorRef.current) editorRef.current.innerHTML = codeVal;
1487
+ if (editorRef.current) editorRef.current.innerHTML = sanitizeScriptTags(codeVal);
1447
1488
  setIsCode(false);
1448
1489
  refresh();
1449
1490
  };
@@ -1454,7 +1495,7 @@ function RichTextEditor({ value, onChange, toolbar }) {
1454
1495
  };
1455
1496
  (0, import_react5.useEffect)(() => {
1456
1497
  if (editorRef.current) {
1457
- editorRef.current.innerHTML = value != null ? value : "<p>Start writing here...</p>";
1498
+ editorRef.current.innerHTML = sanitizeScriptTags(value != null ? value : "<p>Start writing here...</p>");
1458
1499
  refresh();
1459
1500
  }
1460
1501
  }, []);
@@ -1464,7 +1505,7 @@ function RichTextEditor({ value, onChange, toolbar }) {
1464
1505
  const show = (key) => !toolbar || toolbar.includes(key);
1465
1506
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { padding: "1rem 0" }, children: [
1466
1507
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: CSS }),
1467
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { border: "1px solid #d8d8d8", borderRadius: 4, boxShadow: "0 1px 3px rgba(0,0,0,0.06)" }, children: [
1508
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "customeditor", style: { border: "1px solid #d8d8d8", borderRadius: 4, boxShadow: "0 1px 3px rgba(0,0,0,0.06)" }, children: [
1468
1509
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "rte-toolbar", children: [
1469
1510
  !isCode && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
1470
1511
  show("bold") && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { onClick: () => exec("bold"), title: "Bold (Ctrl+B)", active: fmt.bold, style: { fontWeight: 800, fontFamily: "Georgia,serif" }, children: "B" }),
package/dist/index.mjs CHANGED
@@ -45,7 +45,7 @@ var PALETTE = [
45
45
  ];
46
46
  var CSS = `
47
47
  *{box-sizing:border-box;}
48
- .rte-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:1px;padding:4px 8px;background:#f8f8f8;border-bottom:1px solid #e0e0e0;}
48
+ .rte-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:1px;padding:4px 8px;background:#f8f8f8;border-bottom:1px solid #e0e0e0;position: sticky;top: 0;z-index: 9;}
49
49
  @media(prefers-color-scheme:dark){.rte-toolbar{background:#1e1e1e;border-color:#333;}}
50
50
  .rte-btn{background:transparent;border:none;border-radius:3px;cursor:pointer;height:30px;min-width:30px;padding:0 6px;color:#444;font-size:13px;font-weight:500;font-family:var(--font-sans);display:inline-flex;align-items:center;justify-content:center;user-select:none;white-space:nowrap;transition:background 0.1s;flex-shrink:0;}
51
51
  .rte-btn:hover{background:#e8e8e8;}.rte-btn.active{background:#d0e4ff;color:#1a5fb4;}
@@ -149,6 +149,12 @@ var CSS = `
149
149
  .rte-ie-apply{flex:1;height:26px;background:#1a6fc4;color:#fff;border:none;border-radius:4px;font-size:11px;font-weight:600;cursor:pointer;}
150
150
  .rte-ie-remove{flex:1;height:26px;background:#fdecea;color:#c0392b;border:1px solid #f5c6c2;border-radius:4px;font-size:11px;cursor:pointer;}
151
151
  .rte-handle{position:absolute;width:10px;height:10px;background:#fff;border:2px solid #1a5fb4;border-radius:2px;pointer-events:all;z-index:53;}
152
+ .customeditor {
153
+ max-height: 350px;
154
+ overflow-y: auto;
155
+ position: relative;
156
+ }
157
+
152
158
  `;
153
159
 
154
160
  // src/rte/utils.ts
@@ -197,7 +203,42 @@ function getColorAtCursor(editor) {
197
203
  }
198
204
  return "#000000";
199
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
+ }
200
240
  function prettifyHtml(html) {
241
+ const cleanHtml = sanitizeScriptTags(html);
201
242
  const INLINE = /* @__PURE__ */ new Set(["a", "b", "i", "u", "em", "strong", "span", "code", "br", "small", "sub", "sup"]);
202
243
  let indent = 0;
203
244
  const pad = () => " ".repeat(indent);
@@ -1180,8 +1221,8 @@ function RichTextEditor({ value, onChange, toolbar }) {
1180
1221
  else setLinkInfoFP(null);
1181
1222
  const txt = (_b = (_a2 = editorRef.current) == null ? void 0 : _a2.innerText) != null ? _b : "";
1182
1223
  setWords(txt.trim() ? txt.trim().split(/\s+/).length : 0);
1183
- onChange == null ? void 0 : onChange((_d = (_c = editorRef.current) == null ? void 0 : _c.innerHTML) != null ? _d : "");
1184
- }, [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]);
1185
1226
  const exec = useCallback3((cmd, val = null) => {
1186
1227
  var _a2;
1187
1228
  (_a2 = editorRef.current) == null ? void 0 : _a2.focus();
@@ -1422,7 +1463,7 @@ function RichTextEditor({ value, onChange, toolbar }) {
1422
1463
  setIsCode(true);
1423
1464
  };
1424
1465
  const toVisual = () => {
1425
- if (editorRef.current) editorRef.current.innerHTML = codeVal;
1466
+ if (editorRef.current) editorRef.current.innerHTML = sanitizeScriptTags(codeVal);
1426
1467
  setIsCode(false);
1427
1468
  refresh();
1428
1469
  };
@@ -1433,7 +1474,7 @@ function RichTextEditor({ value, onChange, toolbar }) {
1433
1474
  };
1434
1475
  useEffect3(() => {
1435
1476
  if (editorRef.current) {
1436
- editorRef.current.innerHTML = value != null ? value : "<p>Start writing here...</p>";
1477
+ editorRef.current.innerHTML = sanitizeScriptTags(value != null ? value : "<p>Start writing here...</p>");
1437
1478
  refresh();
1438
1479
  }
1439
1480
  }, []);
@@ -1443,7 +1484,7 @@ function RichTextEditor({ value, onChange, toolbar }) {
1443
1484
  const show = (key) => !toolbar || toolbar.includes(key);
1444
1485
  return /* @__PURE__ */ jsxs6("div", { style: { padding: "1rem 0" }, children: [
1445
1486
  /* @__PURE__ */ jsx7("style", { children: CSS }),
1446
- /* @__PURE__ */ jsxs6("div", { style: { border: "1px solid #d8d8d8", borderRadius: 4, boxShadow: "0 1px 3px rgba(0,0,0,0.06)" }, children: [
1487
+ /* @__PURE__ */ jsxs6("div", { className: "customeditor", style: { border: "1px solid #d8d8d8", borderRadius: 4, boxShadow: "0 1px 3px rgba(0,0,0,0.06)" }, children: [
1447
1488
  /* @__PURE__ */ jsxs6("div", { className: "rte-toolbar", children: [
1448
1489
  !isCode && /* @__PURE__ */ jsxs6(Fragment4, { children: [
1449
1490
  show("bold") && /* @__PURE__ */ jsx7(Btn, { onClick: () => exec("bold"), title: "Bold (Ctrl+B)", active: fmt.bold, style: { fontWeight: 800, fontFamily: "Georgia,serif" }, children: "B" }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@malaya_jeeva/rich-text-editor",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "Custom React Rich Text Editor",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",