@broberg/cms-inline-edit 0.6.0 → 0.6.2
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 +35 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +35 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -31,6 +31,10 @@ function isExternalHost(raw, currentHost) {
|
|
|
31
31
|
return false;
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
|
+
function isDangerousUrl(raw) {
|
|
35
|
+
const v = (raw || "").replace(/[\u0000-\u0020]/g, "");
|
|
36
|
+
return /^(?:javascript|data|vbscript):/i.test(v);
|
|
37
|
+
}
|
|
34
38
|
|
|
35
39
|
// src/token-safe.ts
|
|
36
40
|
var TEXT_NODE = 3;
|
|
@@ -89,6 +93,7 @@ var DEFAULT_LABELS = {
|
|
|
89
93
|
linkNewTab: "\xC5bn i ny fane",
|
|
90
94
|
linkSchemeless: "<b>{v}</b> l\xE6ses som en side p\xE5 <b>dette</b> site \u2014 ikke som en adresse ude p\xE5 nettet.",
|
|
91
95
|
linkSchemelessFix: "Tilf\xF8j https://",
|
|
96
|
+
linkBlocked: "<b>{v}</b> kan ikke bruges som link \u2014 adresser af den type kan k\xF8re kode p\xE5 sitet.",
|
|
92
97
|
linkInsert: "Inds\xE6t link",
|
|
93
98
|
linkSave: "Gem \xE6ndring",
|
|
94
99
|
linkCancel: "Annull\xE9r",
|
|
@@ -291,10 +296,12 @@ function showIdlePill() {
|
|
|
291
296
|
removeIdlePill();
|
|
292
297
|
const wrap = document.createElement("div");
|
|
293
298
|
wrap.setAttribute("data-cms-inline-edit-idle", "");
|
|
299
|
+
wrap.setAttribute("data-testid", "inline-edit-idle");
|
|
294
300
|
wrap.style.cssText = "position:fixed;bottom:16px;left:16px;display:inline-flex;align-items:stretch;z-index:2147483647;box-shadow:0 4px 16px rgba(0,0,0,.3);border-radius:999px;overflow:hidden;";
|
|
295
301
|
const edit = document.createElement("button");
|
|
296
302
|
edit.type = "button";
|
|
297
303
|
edit.setAttribute("data-cms-inline-edit-enter", "");
|
|
304
|
+
edit.setAttribute("data-testid", "inline-edit-enter");
|
|
298
305
|
edit.style.cssText = "display:inline-flex;align-items:center;gap:7px;background:#1c2027;color:#fff;font:600 12px system-ui,sans-serif;padding:8px 14px;border:none;cursor:pointer;";
|
|
299
306
|
const editText = document.createElement("span");
|
|
300
307
|
editText.textContent = options.connectLabel;
|
|
@@ -303,6 +310,7 @@ function showIdlePill() {
|
|
|
303
310
|
const out = document.createElement("button");
|
|
304
311
|
out.type = "button";
|
|
305
312
|
out.setAttribute("data-cms-inline-edit-logout", "");
|
|
313
|
+
out.setAttribute("data-testid", "inline-edit-logout");
|
|
306
314
|
out.textContent = options.logoutLabel;
|
|
307
315
|
out.style.cssText = "background:#141821;color:#9aa4b2;font:600 11px system-ui,sans-serif;padding:8px 12px;border:none;border-left:1px solid rgba(255,255,255,.12);cursor:pointer;";
|
|
308
316
|
out.addEventListener("click", () => {
|
|
@@ -555,7 +563,7 @@ function renderLinkDialog() {
|
|
|
555
563
|
}
|
|
556
564
|
const existingRef = linkEditing?.getAttribute("data-cms-ref") ?? "";
|
|
557
565
|
const onPageTab = !editing || !!existingRef;
|
|
558
|
-
d.innerHTML = `<div style="display:flex;gap:4px;padding:8px 8px 0"><button type="button" data-testid="inline-link-tab-page" data-tab="page" style="${tabCss(onPageTab)}">${L.linkTabPage}</button><button type="button" data-testid="inline-link-tab-url" data-tab="url" style="${tabCss(!onPageTab)}">${L.linkTabUrl}</button></div><div style="padding:10px 12px 12px"><div data-pane="page" style="display:${onPageTab ? "block" : "none"}"><input data-testid="inline-link-search" data-role="search" placeholder="${L.linkSearch}" style="${fieldCss()}"><div data-role="current" data-testid="inline-link-current" style="display:none;margin-top:8px;padding:7px 10px;background:rgba(0,178,255,.08);border:1px solid rgba(0,178,255,.28);border-radius:8px;font-size:11.5px;color:#c9d1dd;line-height:1.45"></div><div data-role="list" data-testid="inline-link-list" style="margin-top:8px;max-height:196px;overflow-y:auto;border:1px solid #3a3f4a;border-radius:8px;background:#141821"></div></div><div data-pane="url" style="display:${onPageTab ? "none" : "block"}"><label style="${labelCss()}">${L.linkUrl}</label><input data-testid="inline-link-url" data-role="url" placeholder="https://\u2026" style="${fieldCss()}"><div data-role="schemeless" data-testid="inline-link-schemeless" style="
|
|
566
|
+
d.innerHTML = `<div style="display:flex;gap:4px;padding:8px 8px 0"><button type="button" data-testid="inline-link-tab-page" data-tab="page" style="${tabCss(onPageTab)}">${L.linkTabPage}</button><button type="button" data-testid="inline-link-tab-url" data-tab="url" style="${tabCss(!onPageTab)}">${L.linkTabUrl}</button></div><div style="padding:10px 12px 12px"><div data-pane="page" style="display:${onPageTab ? "block" : "none"}"><input data-testid="inline-link-search" data-role="search" placeholder="${L.linkSearch}" style="${fieldCss()}"><div data-role="current" data-testid="inline-link-current" style="display:none;margin-top:8px;padding:7px 10px;background:rgba(0,178,255,.08);border:1px solid rgba(0,178,255,.28);border-radius:8px;font-size:11.5px;color:#c9d1dd;line-height:1.45"></div><div data-role="list" data-testid="inline-link-list" style="margin-top:8px;max-height:196px;overflow-y:auto;border:1px solid #3a3f4a;border-radius:8px;background:#141821"></div></div><div data-pane="url" style="display:${onPageTab ? "none" : "block"}"><label style="${labelCss()}">${L.linkUrl}</label><input data-testid="inline-link-url" data-role="url" placeholder="https://\u2026" style="${fieldCss()}"><div data-role="schemeless" data-testid="inline-link-schemeless" style="${noticeCss("schemeless")}"><p data-role="schemeless-text" style="margin:0;font-size:11.5px;line-height:1.5"></p><button type="button" data-testid="inline-link-add-scheme" data-role="add-scheme" style="${btnCss(false)};margin-top:7px;height:26px;font-size:12px">${L.linkSchemelessFix}</button></div></div><label style="${labelCss()}">${L.linkText}</label><input data-testid="inline-link-text" data-role="text" placeholder="${L.linkTextAuto}" style="${fieldCss()}"><p data-role="hint" style="font-size:11.5px;color:#9aa3b2;margin:6px 0 0;line-height:1.5"></p><button type="button" data-role="newtab" data-testid="inline-link-newtab" aria-pressed="false" style="display:flex;align-items:center;gap:8px;margin-top:12px;background:none;border:none;padding:0;cursor:pointer;font-family:inherit;font-size:12.5px;color:#c9d1dd"><span data-role="newtab-box" style="${checkboxCss(false)}"></span><span>${L.linkNewTab}</span></button><div data-role="live" style="display:flex;gap:8px;margin-top:12px;padding:9px 10px;background:rgba(0,178,255,.08);border:1px solid rgba(0,178,255,.28);border-radius:8px"><p style="margin:0;font-size:11.5px;color:#c9d1dd;line-height:1.55">${L.linkLiveHint}</p></div><div style="display:flex;gap:8px;align-items:center;margin-top:14px"><div data-role="remove"></div><div style="flex:1"></div><button type="button" data-testid="inline-link-cancel" data-role="cancel" style="${btnCss(false)}">${L.linkCancel}</button><button type="button" data-testid="inline-link-submit" data-role="submit" style="${btnCss(true)}" disabled>${editing ? L.linkSave : L.linkInsert}</button></div></div>`;
|
|
559
567
|
const q = (role) => d.querySelector(`[data-role="${role}"]`);
|
|
560
568
|
const text = q("text");
|
|
561
569
|
const urlIn = q("url");
|
|
@@ -700,14 +708,29 @@ function syncLinkDialog() {
|
|
|
700
708
|
q("live").style.display = onPage ? "flex" : "none";
|
|
701
709
|
q("submit").disabled = onPage ? !linkPicked : !q("url").value.trim();
|
|
702
710
|
const raw = q("url").value;
|
|
703
|
-
const
|
|
704
|
-
|
|
705
|
-
|
|
711
|
+
const dangerous = !onPage && isDangerousUrl(raw);
|
|
712
|
+
const doubtful = !onPage && !dangerous && isSchemeless(raw);
|
|
713
|
+
const notice = q("schemeless");
|
|
714
|
+
const show = dangerous || doubtful;
|
|
715
|
+
if (dangerous) {
|
|
716
|
+
notice.setAttribute("style", noticeCss("blocked"));
|
|
717
|
+
notice.setAttribute("data-variant", "blocked");
|
|
718
|
+
q("schemeless-text").innerHTML = uiLabels.linkBlocked.replace(
|
|
719
|
+
"{v}",
|
|
720
|
+
escapeHtml(raw.trim())
|
|
721
|
+
);
|
|
722
|
+
q("submit").disabled = true;
|
|
723
|
+
} else if (doubtful) {
|
|
724
|
+
notice.setAttribute("style", noticeCss("schemeless"));
|
|
725
|
+
notice.setAttribute("data-variant", "schemeless");
|
|
706
726
|
q("schemeless-text").innerHTML = uiLabels.linkSchemeless.replace(
|
|
707
727
|
"{v}",
|
|
708
728
|
escapeHtml(raw.trim())
|
|
709
729
|
);
|
|
710
730
|
}
|
|
731
|
+
notice.style.display = show ? "block" : "none";
|
|
732
|
+
q("schemeless-text").style.color = dangerous ? "#f5c6c6" : "#e8d6b0";
|
|
733
|
+
q("add-scheme").style.display = doubtful ? "" : "none";
|
|
711
734
|
if (!onPage && !linkNewTabTouched) {
|
|
712
735
|
linkNewTab = isExternalHost(raw, typeof location !== "undefined" ? location.host : "");
|
|
713
736
|
}
|
|
@@ -732,6 +755,7 @@ function applyLink() {
|
|
|
732
755
|
const own = q("text").value.trim();
|
|
733
756
|
const href = onPage ? linkPicked?.path ?? "" : q("url").value.trim();
|
|
734
757
|
if (!href) return;
|
|
758
|
+
if (isDangerousUrl(href)) return;
|
|
735
759
|
const ref = onPage && linkPicked ? `${linkPicked.collection}:${linkPicked.slug}` : "";
|
|
736
760
|
const label = own || (onPage ? linkPicked?.title ?? href : href);
|
|
737
761
|
const applyTarget = (el) => setLinkTarget(el, linkNewTab);
|
|
@@ -773,6 +797,7 @@ function escapeHtml(v) {
|
|
|
773
797
|
return v.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
774
798
|
}
|
|
775
799
|
var tabCss = (on) => "flex:1;background:" + (on ? "#2a2f38" : "none") + ";border:1px solid " + (on ? "#3a3f4a" : "transparent") + ";color:" + (on ? "#fff" : "#9aa3b2") + ";height:32px;border-radius:7px;font-size:13px;cursor:pointer;font-weight:500;font-family:inherit;";
|
|
800
|
+
var noticeCss = (variant) => "display:none;margin-top:8px;padding:8px 10px;border-radius:8px;background:" + (variant === "blocked" ? "rgba(255,90,90,.10)" : "rgba(255,176,32,.10)") + ";border:1px solid " + (variant === "blocked" ? "rgba(255,90,90,.38)" : "rgba(255,176,32,.34)") + ";";
|
|
776
801
|
var checkboxCss = (on) => "width:16px;height:16px;flex:0 0 16px;border-radius:4px;box-sizing:border-box;display:inline-block;" + (on ? `background:#00b2ff;border:1px solid #00b2ff;background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><path d='M4 8.5l2.6 2.6L12 5.8' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/></svg>");background-size:100% 100%;` : "background:#141821;border:1px solid #3a3f4a;");
|
|
777
802
|
var fieldCss = () => "width:100%;background:#141821;border:1px solid #3a3f4a;color:#fff;height:34px;border-radius:7px;padding:0 10px;font-size:13.5px;outline:none;font-family:inherit;box-sizing:border-box;";
|
|
778
803
|
var labelCss = () => "font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:#9aa3b2;margin:12px 0 5px;display:block;";
|
|
@@ -1064,6 +1089,10 @@ function serializeInlineNode(child) {
|
|
|
1064
1089
|
break;
|
|
1065
1090
|
case "a": {
|
|
1066
1091
|
const href = el.getAttribute("href") || "";
|
|
1092
|
+
if (isDangerousUrl(href)) {
|
|
1093
|
+
out += inner;
|
|
1094
|
+
break;
|
|
1095
|
+
}
|
|
1067
1096
|
const extras = preservedLinkAttrs(el);
|
|
1068
1097
|
if (extras.length > 0) {
|
|
1069
1098
|
out += `<a ${[`href="${escapeAttr(href)}"`, ...extras].join(" ")}>${inner}</a>`;
|
|
@@ -1137,6 +1166,7 @@ function showPill(el, state) {
|
|
|
1137
1166
|
if (!pill) {
|
|
1138
1167
|
pill = document.createElement("span");
|
|
1139
1168
|
pill.setAttribute("data-cms-inline-edit-pill", "");
|
|
1169
|
+
pill.setAttribute("data-testid", "inline-edit-pill");
|
|
1140
1170
|
document.body.appendChild(pill);
|
|
1141
1171
|
pills.set(el, pill);
|
|
1142
1172
|
}
|
|
@@ -1164,6 +1194,7 @@ function showActiveBadge(options) {
|
|
|
1164
1194
|
const badge = document.createElement("button");
|
|
1165
1195
|
badge.type = "button";
|
|
1166
1196
|
badge.setAttribute("data-cms-inline-edit-badge", "");
|
|
1197
|
+
badge.setAttribute("data-testid", "inline-edit-badge");
|
|
1167
1198
|
badge.style.cssText = "position:fixed;bottom:16px;left:16px;display:inline-flex;align-items:center;gap:7px;background:#1c2027;color:#fff;font:600 12px system-ui,sans-serif;padding:8px 14px;border-radius:999px;z-index:2147483647;box-shadow:0 4px 16px rgba(0,0,0,.3);border:none;cursor:pointer;opacity:.9;transition:opacity .15s;";
|
|
1168
1199
|
const text = document.createElement("span");
|
|
1169
1200
|
text.textContent = options.disconnectLabel;
|