@broberg/cms-inline-edit 0.4.21 → 0.5.1
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/README.md +53 -0
- package/dist/index.cjs +318 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +318 -12
- package/dist/index.js.map +1 -1
- package/dist/server/index.cjs +29 -0
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +10 -1
- package/dist/server/index.d.ts +10 -1
- package/dist/server/index.js +28 -0
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -50,7 +50,27 @@ var DEFAULT_LABELS = {
|
|
|
50
50
|
done: "F\xE6rdig",
|
|
51
51
|
saving: "Gemmer\u2026",
|
|
52
52
|
saved: "Gemt \u2713",
|
|
53
|
-
error: "Fejl \u2014 pr\xF8v igen"
|
|
53
|
+
error: "Fejl \u2014 pr\xF8v igen",
|
|
54
|
+
link: "Link",
|
|
55
|
+
linkTabPage: "Side p\xE5 sitet",
|
|
56
|
+
linkTabUrl: "Fri adresse",
|
|
57
|
+
linkSearch: "S\xF8g efter en side\u2026",
|
|
58
|
+
linkText: "Linktekst",
|
|
59
|
+
linkTextAuto: "F\xF8lger sidens titel",
|
|
60
|
+
linkTextAutoHint: "<b>Tom = f\xF8lger sidens titel.</b> Omd\xF8bes siden, retter teksten sig selv. Skriver du din egen tekst, bliver den st\xE5ende.",
|
|
61
|
+
linkTextOwnHint: "Linket viser <b>din egen tekst</b>. Den bliver st\xE5ende, ogs\xE5 hvis siden omd\xF8bes.",
|
|
62
|
+
linkLiveHint: "Linket peger p\xE5 <b>siden</b> \u2014 ikke p\xE5 en adresse. Flyttes siden, eller f\xE5r den et nyt navn, retter linket sig selv.",
|
|
63
|
+
linkUrlHint: "En fri adresse peger pr\xE6cis d\xE9r, du skriver. Den f\xF8lger <b>ikke</b> med, hvis m\xE5let flytter sig.",
|
|
64
|
+
linkUrl: "Adresse",
|
|
65
|
+
linkInsert: "Inds\xE6t link",
|
|
66
|
+
linkSave: "Gem \xE6ndring",
|
|
67
|
+
linkCancel: "Annull\xE9r",
|
|
68
|
+
linkRemove: "Fjern link",
|
|
69
|
+
linkRemoveConfirm: "Fjern?",
|
|
70
|
+
linkYes: "Ja",
|
|
71
|
+
linkNo: "Nej",
|
|
72
|
+
linkEmpty: "Ingen sider fundet",
|
|
73
|
+
linkLoading: "Henter sider\u2026"
|
|
54
74
|
};
|
|
55
75
|
var uiLabels = DEFAULT_LABELS;
|
|
56
76
|
function resolveOptions(options) {
|
|
@@ -111,12 +131,18 @@ function getConnectedToken(options) {
|
|
|
111
131
|
captureTokenFromUrl(resolved);
|
|
112
132
|
const token = localStorage.getItem(resolved.storageKey);
|
|
113
133
|
if (!token) return null;
|
|
114
|
-
if (isExpired(token)) {
|
|
134
|
+
if (isExpired(token) || !isForThisSite(token, resolved.siteId)) {
|
|
115
135
|
localStorage.removeItem(resolved.storageKey);
|
|
116
136
|
return null;
|
|
117
137
|
}
|
|
118
138
|
return token;
|
|
119
139
|
}
|
|
140
|
+
function isForThisSite(token, siteId) {
|
|
141
|
+
const claims = decodeJwtPayload(token);
|
|
142
|
+
const site = claims?.site;
|
|
143
|
+
if (typeof site !== "string" || !site) return true;
|
|
144
|
+
return site === siteId;
|
|
145
|
+
}
|
|
120
146
|
function buildConnectUrl(options, returnUrl) {
|
|
121
147
|
const resolved = resolveOptions(options);
|
|
122
148
|
return `${resolved.cmsBaseUrl}/admin/inline-edit/connect?site=${encodeURIComponent(resolved.siteId)}&return=${encodeURIComponent(returnUrl)}`;
|
|
@@ -152,6 +178,7 @@ function isExpired(token) {
|
|
|
152
178
|
var SQUARE_PEN_SVG = '<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z"/></svg>';
|
|
153
179
|
var UL_SVG = '<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="8" x2="21" y1="6" y2="6"/><line x1="8" x2="21" y1="12" y2="12"/><line x1="8" x2="21" y1="18" y2="18"/><line x1="3" x2="3.01" y1="6" y2="6"/><line x1="3" x2="3.01" y1="12" y2="12"/><line x1="3" x2="3.01" y1="18" y2="18"/></svg>';
|
|
154
180
|
var OL_SVG = '<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="10" x2="21" y1="6" y2="6"/><line x1="10" x2="21" y1="12" y2="12"/><line x1="10" x2="21" y1="18" y2="18"/><path d="M4 6h1v4"/><path d="M4 10h2"/><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"/></svg>';
|
|
181
|
+
var LINK_SVG = '<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M10 13a5 5 0 0 0 7.5.5l3-3a5 5 0 0 0-7-7l-1.7 1.7"/><path d="M14 11a5 5 0 0 0-7.5-.5l-3 3a5 5 0 0 0 7 7l1.7-1.7"/></svg>';
|
|
155
182
|
function makeIcon() {
|
|
156
183
|
const icon = document.createElement("span");
|
|
157
184
|
icon.style.cssText = "display:inline-flex;line-height:0;flex:0 0 auto";
|
|
@@ -310,6 +337,7 @@ function deactivateRich() {
|
|
|
310
337
|
el.removeAttribute("contenteditable");
|
|
311
338
|
el.classList.remove("cms-rich-editing");
|
|
312
339
|
hideRichToolbar();
|
|
340
|
+
hideLinkDialog();
|
|
313
341
|
if (el.innerHTML !== originalHtml) {
|
|
314
342
|
const value = mode === "html" ? el.innerHTML : htmlToMarkdown(el.innerHTML);
|
|
315
343
|
void saveField(el, value, token, options);
|
|
@@ -355,6 +383,10 @@ function buildRichToolbar() {
|
|
|
355
383
|
t.appendChild(toolbarButton(UL_SVG, uiLabels.unorderedList, () => document.execCommand("insertUnorderedList")));
|
|
356
384
|
t.appendChild(toolbarButton(OL_SVG, uiLabels.orderedList, () => document.execCommand("insertOrderedList")));
|
|
357
385
|
t.appendChild(sep());
|
|
386
|
+
const linkBtn = toolbarButton(LINK_SVG, uiLabels.link, () => toggleLinkDialog(linkBtn));
|
|
387
|
+
linkBtn.setAttribute("data-testid", "inline-toolbar-link");
|
|
388
|
+
t.appendChild(linkBtn);
|
|
389
|
+
t.appendChild(sep());
|
|
358
390
|
const clrLabel = document.createElement("label");
|
|
359
391
|
clrLabel.style.cssText = "display:flex;align-items:center;gap:5px;color:#9aa4b2;font-size:12px;cursor:pointer;";
|
|
360
392
|
clrLabel.textContent = uiLabels.color;
|
|
@@ -388,6 +420,231 @@ var EMOJIS = "\u{1F600} \u{1F603} \u{1F604} \u{1F601} \u{1F606} \u{1F609} \u{1F6
|
|
|
388
420
|
);
|
|
389
421
|
var emojiPicker = null;
|
|
390
422
|
var savedRange = null;
|
|
423
|
+
var linkDialog = null;
|
|
424
|
+
var linkPages = null;
|
|
425
|
+
var linkPicked = null;
|
|
426
|
+
var linkEditing = null;
|
|
427
|
+
function hideLinkDialog() {
|
|
428
|
+
if (linkDialog) linkDialog.style.display = "none";
|
|
429
|
+
linkPicked = null;
|
|
430
|
+
linkEditing = null;
|
|
431
|
+
}
|
|
432
|
+
function anchorAtCaret() {
|
|
433
|
+
const sel = window.getSelection();
|
|
434
|
+
if (!sel || sel.rangeCount === 0) return null;
|
|
435
|
+
let node = sel.getRangeAt(0).startContainer;
|
|
436
|
+
while (node && node !== document.body) {
|
|
437
|
+
if (node.nodeType === Node.ELEMENT_NODE && node.tagName === "A") {
|
|
438
|
+
return node;
|
|
439
|
+
}
|
|
440
|
+
node = node.parentNode;
|
|
441
|
+
}
|
|
442
|
+
return null;
|
|
443
|
+
}
|
|
444
|
+
async function fetchLinkablePages() {
|
|
445
|
+
if (linkPages) return linkPages;
|
|
446
|
+
if (!richCtx) return [];
|
|
447
|
+
const { options, token } = richCtx;
|
|
448
|
+
const url = `${options.cmsBaseUrl}/api/inline-edit/pages?site=${encodeURIComponent(options.siteId)}`;
|
|
449
|
+
const res = await fetch(url, { headers: { Authorization: `Bearer ${token}` } });
|
|
450
|
+
if (!res.ok) throw new Error(`pages ${res.status}`);
|
|
451
|
+
const body = await res.json();
|
|
452
|
+
linkPages = body.pages ?? [];
|
|
453
|
+
return linkPages;
|
|
454
|
+
}
|
|
455
|
+
function toggleLinkDialog(anchor) {
|
|
456
|
+
if (linkDialog && linkDialog.style.display === "block") {
|
|
457
|
+
hideLinkDialog();
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
const sel = window.getSelection();
|
|
461
|
+
if (sel && sel.rangeCount > 0) savedRange = sel.getRangeAt(0).cloneRange();
|
|
462
|
+
linkEditing = anchorAtCaret();
|
|
463
|
+
if (!linkDialog) linkDialog = buildLinkDialog();
|
|
464
|
+
renderLinkDialog();
|
|
465
|
+
const rect = anchor.getBoundingClientRect();
|
|
466
|
+
linkDialog.style.top = `${rect.bottom + 8}px`;
|
|
467
|
+
linkDialog.style.left = `${Math.min(Math.max(8, rect.left - 180), window.innerWidth - 400)}px`;
|
|
468
|
+
linkDialog.style.display = "block";
|
|
469
|
+
}
|
|
470
|
+
function buildLinkDialog() {
|
|
471
|
+
const d = document.createElement("div");
|
|
472
|
+
d.setAttribute("data-cms-inline-edit-toolbar", "");
|
|
473
|
+
d.setAttribute("data-testid", "inline-link-dialog");
|
|
474
|
+
d.style.cssText = "position:fixed;z-index:2147483646;background:#1c2027;border:1px solid #3a3f4a;border-radius:10px;width:392px;display:none;box-shadow:0 8px 32px rgba(0,0,0,.5);font-family:system-ui,sans-serif;color:#fff;overflow:hidden;";
|
|
475
|
+
d.addEventListener("mousedown", (e) => {
|
|
476
|
+
const t = e.target;
|
|
477
|
+
if (t.tagName !== "INPUT") e.preventDefault();
|
|
478
|
+
e.stopPropagation();
|
|
479
|
+
});
|
|
480
|
+
document.body.appendChild(d);
|
|
481
|
+
return d;
|
|
482
|
+
}
|
|
483
|
+
function renderLinkDialog() {
|
|
484
|
+
const d = linkDialog;
|
|
485
|
+
if (!d) return;
|
|
486
|
+
const L = uiLabels;
|
|
487
|
+
const editing = !!linkEditing;
|
|
488
|
+
const existingRef = linkEditing?.getAttribute("data-cms-ref") ?? "";
|
|
489
|
+
const onPageTab = !editing || !!existingRef;
|
|
490
|
+
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="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><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><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>`;
|
|
491
|
+
const q = (role) => d.querySelector(`[data-role="${role}"]`);
|
|
492
|
+
const text = q("text");
|
|
493
|
+
const urlIn = q("url");
|
|
494
|
+
const search = q("search");
|
|
495
|
+
if (editing) {
|
|
496
|
+
text.value = linkEditing?.getAttribute("data-cms-ref-label") === "auto" ? "" : linkEditing?.textContent ?? "";
|
|
497
|
+
if (!existingRef) urlIn.value = linkEditing?.getAttribute("href") ?? "";
|
|
498
|
+
q("remove").appendChild(buildRemoveLink());
|
|
499
|
+
}
|
|
500
|
+
d.querySelectorAll("[data-tab]").forEach((btn) => {
|
|
501
|
+
btn.onclick = () => {
|
|
502
|
+
const page = btn.dataset.tab === "page";
|
|
503
|
+
d.querySelectorAll("[data-tab]").forEach((b) => {
|
|
504
|
+
b.setAttribute("style", tabCss(b.dataset.tab === "page" ? page : !page));
|
|
505
|
+
});
|
|
506
|
+
d.querySelector('[data-pane="page"]').style.display = page ? "block" : "none";
|
|
507
|
+
d.querySelector('[data-pane="url"]').style.display = page ? "none" : "block";
|
|
508
|
+
q("live").style.display = page ? "flex" : "none";
|
|
509
|
+
syncLinkDialog();
|
|
510
|
+
};
|
|
511
|
+
});
|
|
512
|
+
search.oninput = () => renderLinkList(search.value);
|
|
513
|
+
text.oninput = syncLinkDialog;
|
|
514
|
+
urlIn.oninput = syncLinkDialog;
|
|
515
|
+
q("cancel").onclick = hideLinkDialog;
|
|
516
|
+
q("submit").onclick = applyLink;
|
|
517
|
+
renderLinkList("");
|
|
518
|
+
syncLinkDialog();
|
|
519
|
+
}
|
|
520
|
+
function buildRemoveLink() {
|
|
521
|
+
const wrap = document.createElement("div");
|
|
522
|
+
const btn = document.createElement("button");
|
|
523
|
+
btn.type = "button";
|
|
524
|
+
btn.setAttribute("data-testid", "inline-link-remove");
|
|
525
|
+
btn.textContent = uiLabels.linkRemove;
|
|
526
|
+
btn.style.cssText = "background:none;border:none;color:#ff8a8a;font-size:12.5px;cursor:pointer;padding:0 2px;";
|
|
527
|
+
btn.onclick = () => {
|
|
528
|
+
wrap.innerHTML = `<span style="font-size:11.5px;color:#ff8a8a;font-weight:500;padding:0 2px">${uiLabels.linkRemoveConfirm}</span><button type="button" data-testid="inline-link-remove-yes" style="font-size:11px;padding:2px 8px;border-radius:4px;border:none;background:#c0392b;color:#fff;cursor:pointer;line-height:1.4;margin-left:6px">${uiLabels.linkYes}</button><button type="button" data-testid="inline-link-remove-no" style="font-size:11px;padding:2px 8px;border-radius:4px;border:1px solid #3a3f4a;background:none;color:#fff;cursor:pointer;line-height:1.4;margin-left:6px">${uiLabels.linkNo}</button>`;
|
|
529
|
+
wrap.querySelector('[data-testid="inline-link-remove-no"]').onclick = () => {
|
|
530
|
+
wrap.innerHTML = "";
|
|
531
|
+
wrap.appendChild(btn);
|
|
532
|
+
};
|
|
533
|
+
wrap.querySelector('[data-testid="inline-link-remove-yes"]').onclick = () => {
|
|
534
|
+
if (linkEditing) {
|
|
535
|
+
const parent = linkEditing.parentNode;
|
|
536
|
+
while (linkEditing.firstChild) parent?.insertBefore(linkEditing.firstChild, linkEditing);
|
|
537
|
+
parent?.removeChild(linkEditing);
|
|
538
|
+
}
|
|
539
|
+
hideLinkDialog();
|
|
540
|
+
};
|
|
541
|
+
};
|
|
542
|
+
wrap.appendChild(btn);
|
|
543
|
+
return wrap;
|
|
544
|
+
}
|
|
545
|
+
function renderLinkList(filter) {
|
|
546
|
+
const d = linkDialog;
|
|
547
|
+
if (!d) return;
|
|
548
|
+
const list = d.querySelector('[data-role="list"]');
|
|
549
|
+
if (!list) return;
|
|
550
|
+
const paint = (pages) => {
|
|
551
|
+
const f = filter.trim().toLowerCase();
|
|
552
|
+
const shown = pages.filter((p) => !f || `${p.title} ${p.path}`.toLowerCase().includes(f));
|
|
553
|
+
if (!shown.length) {
|
|
554
|
+
list.innerHTML = `<div style="padding:10px;font-size:12.5px;color:#9aa3b2">${uiLabels.linkEmpty}</div>`;
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
list.innerHTML = "";
|
|
558
|
+
shown.forEach((p) => {
|
|
559
|
+
const on = linkPicked?.collection === p.collection && linkPicked?.slug === p.slug;
|
|
560
|
+
const row = document.createElement("div");
|
|
561
|
+
row.setAttribute("data-testid", `inline-link-page-${p.collection}-${p.slug}`);
|
|
562
|
+
row.style.cssText = "display:flex;align-items:center;gap:10px;padding:8px 10px;cursor:pointer;border-bottom:1px solid #232833;" + (on ? "background:rgba(0,178,255,.14);" : "");
|
|
563
|
+
row.innerHTML = `<div style="min-width:0;flex:1"><div style="font-size:13.5px;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis">${escapeHtml(p.title)}</div><div style="font-size:11.5px;color:#9aa3b2;font-family:ui-monospace,Menlo,monospace;white-space:nowrap;overflow:hidden;text-overflow:ellipsis">${escapeHtml(p.path)}</div></div><span style="flex:none;font-size:10px;text-transform:uppercase;color:#9aa3b2;border:1px solid #3a3f4a;border-radius:4px;padding:2px 6px;white-space:nowrap">${escapeHtml(p.label)}</span>`;
|
|
564
|
+
row.onclick = () => {
|
|
565
|
+
linkPicked = p;
|
|
566
|
+
renderLinkList(filter);
|
|
567
|
+
syncLinkDialog();
|
|
568
|
+
};
|
|
569
|
+
list.appendChild(row);
|
|
570
|
+
});
|
|
571
|
+
};
|
|
572
|
+
if (linkPages) {
|
|
573
|
+
paint(linkPages);
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
list.innerHTML = `<div style="padding:10px;font-size:12.5px;color:#9aa3b2">${uiLabels.linkLoading}</div>`;
|
|
577
|
+
fetchLinkablePages().then((pages) => {
|
|
578
|
+
const ref = linkEditing?.getAttribute("data-cms-ref");
|
|
579
|
+
if (ref && !linkPicked) {
|
|
580
|
+
const [c, ...rest] = ref.split(":");
|
|
581
|
+
linkPicked = pages.find((p) => p.collection === c && p.slug === rest.join(":")) ?? null;
|
|
582
|
+
}
|
|
583
|
+
paint(pages);
|
|
584
|
+
syncLinkDialog();
|
|
585
|
+
}).catch(() => {
|
|
586
|
+
list.innerHTML = `<div style="padding:10px;font-size:12.5px;color:#ff8a8a">${uiLabels.error}</div>`;
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
function syncLinkDialog() {
|
|
590
|
+
const d = linkDialog;
|
|
591
|
+
if (!d) return;
|
|
592
|
+
const q = (role) => d.querySelector(`[data-role="${role}"]`);
|
|
593
|
+
const onPage = d.querySelector('[data-pane="page"]').style.display !== "none";
|
|
594
|
+
const own = q("text").value.trim();
|
|
595
|
+
q("hint").innerHTML = own ? uiLabels.linkTextOwnHint : onPage ? uiLabels.linkTextAutoHint : uiLabels.linkUrlHint;
|
|
596
|
+
q("live").style.display = onPage ? "flex" : "none";
|
|
597
|
+
q("submit").disabled = onPage ? !linkPicked : !q("url").value.trim();
|
|
598
|
+
}
|
|
599
|
+
function applyLink() {
|
|
600
|
+
const d = linkDialog;
|
|
601
|
+
if (!d || !richCtx) return;
|
|
602
|
+
const q = (role) => d.querySelector(`[data-role="${role}"]`);
|
|
603
|
+
const onPage = d.querySelector('[data-pane="page"]').style.display !== "none";
|
|
604
|
+
const own = q("text").value.trim();
|
|
605
|
+
const href = onPage ? linkPicked?.path ?? "" : q("url").value.trim();
|
|
606
|
+
if (!href) return;
|
|
607
|
+
const ref = onPage && linkPicked ? `${linkPicked.collection}:${linkPicked.slug}` : "";
|
|
608
|
+
const label = own || (onPage ? linkPicked?.title ?? href : href);
|
|
609
|
+
if (linkEditing) {
|
|
610
|
+
linkEditing.setAttribute("href", href);
|
|
611
|
+
if (ref) linkEditing.setAttribute("data-cms-ref", ref);
|
|
612
|
+
else linkEditing.removeAttribute("data-cms-ref");
|
|
613
|
+
if (ref && !own) linkEditing.setAttribute("data-cms-ref-label", "auto");
|
|
614
|
+
else linkEditing.removeAttribute("data-cms-ref-label");
|
|
615
|
+
linkEditing.textContent = label;
|
|
616
|
+
hideLinkDialog();
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
const a = document.createElement("a");
|
|
620
|
+
a.setAttribute("href", href);
|
|
621
|
+
if (ref) {
|
|
622
|
+
a.setAttribute("data-cms-ref", ref);
|
|
623
|
+
if (!own) a.setAttribute("data-cms-ref-label", "auto");
|
|
624
|
+
}
|
|
625
|
+
const sel = window.getSelection();
|
|
626
|
+
if (savedRange && sel) {
|
|
627
|
+
sel.removeAllRanges();
|
|
628
|
+
sel.addRange(savedRange);
|
|
629
|
+
const range = sel.getRangeAt(0);
|
|
630
|
+
a.textContent = own || range.toString() || label;
|
|
631
|
+
range.deleteContents();
|
|
632
|
+
range.insertNode(a);
|
|
633
|
+
sel.removeAllRanges();
|
|
634
|
+
} else {
|
|
635
|
+
a.textContent = label;
|
|
636
|
+
richCtx.el.appendChild(a);
|
|
637
|
+
}
|
|
638
|
+
savedRange = null;
|
|
639
|
+
hideLinkDialog();
|
|
640
|
+
}
|
|
641
|
+
function escapeHtml(v) {
|
|
642
|
+
return v.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
643
|
+
}
|
|
644
|
+
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;";
|
|
645
|
+
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;";
|
|
646
|
+
var labelCss = () => "font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:#9aa3b2;margin:12px 0 5px;display:block;";
|
|
647
|
+
var btnCss = (primary) => "height:33px;border-radius:7px;font-size:13px;cursor:pointer;padding:0 14px;font-weight:600;font-family:inherit;" + (primary ? "background:#00b2ff;color:#04121b;border:none;" : "background:none;border:1px solid #3a3f4a;color:#fff;font-weight:500;");
|
|
391
648
|
function toggleEmojiPicker(anchor) {
|
|
392
649
|
if (!emojiPicker) emojiPicker = buildEmojiPicker();
|
|
393
650
|
if (emojiPicker.style.display === "block") {
|
|
@@ -497,12 +754,44 @@ function reattachOrphanListItems(container) {
|
|
|
497
754
|
}
|
|
498
755
|
}
|
|
499
756
|
}
|
|
757
|
+
var BLOCK_TAGS = /* @__PURE__ */ new Set([
|
|
758
|
+
"h1",
|
|
759
|
+
"h2",
|
|
760
|
+
"h3",
|
|
761
|
+
"h4",
|
|
762
|
+
"h5",
|
|
763
|
+
"h6",
|
|
764
|
+
"p",
|
|
765
|
+
"div",
|
|
766
|
+
"ul",
|
|
767
|
+
"ol",
|
|
768
|
+
"li",
|
|
769
|
+
"blockquote",
|
|
770
|
+
"pre",
|
|
771
|
+
"hr",
|
|
772
|
+
"table"
|
|
773
|
+
]);
|
|
774
|
+
function isBlockNode(node) {
|
|
775
|
+
return node.nodeType === Node.ELEMENT_NODE && BLOCK_TAGS.has(node.tagName.toLowerCase());
|
|
776
|
+
}
|
|
500
777
|
function serializeBlockChildren(parent) {
|
|
501
778
|
const blocks = [];
|
|
502
|
-
|
|
503
|
-
|
|
779
|
+
let inlineRun = "";
|
|
780
|
+
const flushInline = () => {
|
|
781
|
+
const s = inlineRun.trim();
|
|
504
782
|
if (s) blocks.push(s);
|
|
783
|
+
inlineRun = "";
|
|
784
|
+
};
|
|
785
|
+
parent.childNodes.forEach((node) => {
|
|
786
|
+
if (isBlockNode(node)) {
|
|
787
|
+
flushInline();
|
|
788
|
+
const s = serializeBlock(node).trim();
|
|
789
|
+
if (s) blocks.push(s);
|
|
790
|
+
} else {
|
|
791
|
+
inlineRun += serializeInlineNode(node);
|
|
792
|
+
}
|
|
505
793
|
});
|
|
794
|
+
flushInline();
|
|
506
795
|
return blocks.join("\n\n");
|
|
507
796
|
}
|
|
508
797
|
function serializeBlock(node) {
|
|
@@ -576,14 +865,23 @@ function serializeList(listEl, ordered) {
|
|
|
576
865
|
});
|
|
577
866
|
return items.join("\n");
|
|
578
867
|
}
|
|
868
|
+
function escapeAttr(value) {
|
|
869
|
+
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<");
|
|
870
|
+
}
|
|
579
871
|
function serializeInline(node) {
|
|
580
872
|
let out = "";
|
|
581
873
|
node.childNodes.forEach((child) => {
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
874
|
+
out += serializeInlineNode(child);
|
|
875
|
+
});
|
|
876
|
+
return out;
|
|
877
|
+
}
|
|
878
|
+
function serializeInlineNode(child) {
|
|
879
|
+
if (child.nodeType === Node.TEXT_NODE) {
|
|
880
|
+
return (child.textContent ?? "").replace(/\s+/g, " ");
|
|
881
|
+
}
|
|
882
|
+
if (child.nodeType !== Node.ELEMENT_NODE) return "";
|
|
883
|
+
{
|
|
884
|
+
let out = "";
|
|
587
885
|
const el = child;
|
|
588
886
|
const tag = el.tagName.toLowerCase();
|
|
589
887
|
const inner = serializeInline(el);
|
|
@@ -604,7 +902,15 @@ function serializeInline(node) {
|
|
|
604
902
|
break;
|
|
605
903
|
case "a": {
|
|
606
904
|
const href = el.getAttribute("href") || "";
|
|
607
|
-
|
|
905
|
+
const ref = el.getAttribute("data-cms-ref");
|
|
906
|
+
if (ref) {
|
|
907
|
+
const attrs = [`href="${escapeAttr(href)}"`, `data-cms-ref="${escapeAttr(ref)}"`];
|
|
908
|
+
const label = el.getAttribute("data-cms-ref-label");
|
|
909
|
+
if (label) attrs.push(`data-cms-ref-label="${escapeAttr(label)}"`);
|
|
910
|
+
out += `<a ${attrs.join(" ")}>${inner}</a>`;
|
|
911
|
+
} else {
|
|
912
|
+
out += href ? `[${inner}](${href})` : inner;
|
|
913
|
+
}
|
|
608
914
|
break;
|
|
609
915
|
}
|
|
610
916
|
case "img": {
|
|
@@ -625,8 +931,8 @@ function serializeInline(node) {
|
|
|
625
931
|
default:
|
|
626
932
|
out += inner;
|
|
627
933
|
}
|
|
628
|
-
|
|
629
|
-
|
|
934
|
+
return out;
|
|
935
|
+
}
|
|
630
936
|
}
|
|
631
937
|
async function saveField(el, value, token, options) {
|
|
632
938
|
const collection = el.dataset.cmsCollection;
|