@broberg/cms-inline-edit 0.5.4 → 0.5.5
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 +87 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +47 -1
- package/dist/index.d.ts +47 -1
- package/dist/index.js +83 -18
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -26,7 +26,10 @@ __export(index_exports, {
|
|
|
26
26
|
getConnectedToken: () => getConnectedToken,
|
|
27
27
|
htmlToMarkdown: () => htmlToMarkdown,
|
|
28
28
|
initInlineEdit: () => initInlineEdit,
|
|
29
|
-
|
|
29
|
+
positionPopover: () => positionPopover,
|
|
30
|
+
renderCurrentRefLine: () => renderCurrentRefLine,
|
|
31
|
+
rescanFields: () => rescanFields,
|
|
32
|
+
resolveExistingRef: () => resolveExistingRef
|
|
30
33
|
});
|
|
31
34
|
module.exports = __toCommonJS(index_exports);
|
|
32
35
|
|
|
@@ -102,7 +105,8 @@ var DEFAULT_LABELS = {
|
|
|
102
105
|
linkYes: "Ja",
|
|
103
106
|
linkNo: "Nej",
|
|
104
107
|
linkEmpty: "Ingen sider fundet",
|
|
105
|
-
linkLoading: "Henter sider\u2026"
|
|
108
|
+
linkLoading: "Henter sider\u2026",
|
|
109
|
+
linkCurrent: "Linker til"
|
|
106
110
|
};
|
|
107
111
|
var uiLabels = DEFAULT_LABELS;
|
|
108
112
|
function resolveOptions(options) {
|
|
@@ -499,6 +503,22 @@ async function fetchLinkablePages() {
|
|
|
499
503
|
linkPages = body.pages ?? [];
|
|
500
504
|
return linkPages;
|
|
501
505
|
}
|
|
506
|
+
function positionPopover(el, rect, gap, width) {
|
|
507
|
+
const MARGIN = 8;
|
|
508
|
+
const vh = window.innerHeight;
|
|
509
|
+
const vw = window.innerWidth;
|
|
510
|
+
el.style.maxHeight = `${Math.max(120, vh - MARGIN * 2)}px`;
|
|
511
|
+
el.style.overflowY = "auto";
|
|
512
|
+
el.style.display = "block";
|
|
513
|
+
const h = el.getBoundingClientRect().height || el.offsetHeight || 0;
|
|
514
|
+
let top = rect.bottom + gap;
|
|
515
|
+
if (top + h > vh - MARGIN) {
|
|
516
|
+
const above = rect.top - gap - h;
|
|
517
|
+
top = above >= MARGIN ? above : vh - MARGIN - h;
|
|
518
|
+
}
|
|
519
|
+
el.style.top = `${Math.max(MARGIN, top)}px`;
|
|
520
|
+
el.style.left = `${Math.max(MARGIN, Math.min(rect.left, vw - width - MARGIN))}px`;
|
|
521
|
+
}
|
|
502
522
|
function toggleLinkDialog(anchor) {
|
|
503
523
|
if (linkDialog && linkDialog.style.display === "block") {
|
|
504
524
|
hideLinkDialog();
|
|
@@ -510,9 +530,12 @@ function toggleLinkDialog(anchor) {
|
|
|
510
530
|
if (!linkDialog) linkDialog = buildLinkDialog();
|
|
511
531
|
renderLinkDialog();
|
|
512
532
|
const rect = anchor.getBoundingClientRect();
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
533
|
+
positionPopover(
|
|
534
|
+
linkDialog,
|
|
535
|
+
{ top: rect.top, bottom: rect.bottom, left: rect.left - 180 },
|
|
536
|
+
8,
|
|
537
|
+
392
|
|
538
|
+
);
|
|
516
539
|
}
|
|
517
540
|
function buildLinkDialog() {
|
|
518
541
|
const d = document.createElement("div");
|
|
@@ -534,7 +557,7 @@ function renderLinkDialog() {
|
|
|
534
557
|
const editing = !!linkEditing;
|
|
535
558
|
const existingRef = linkEditing?.getAttribute("data-cms-ref") ?? "";
|
|
536
559
|
const onPageTab = !editing || !!existingRef;
|
|
537
|
-
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>`;
|
|
560
|
+
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><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>`;
|
|
538
561
|
const q = (role) => d.querySelector(`[data-role="${role}"]`);
|
|
539
562
|
const text = q("text");
|
|
540
563
|
const urlIn = q("url");
|
|
@@ -589,6 +612,28 @@ function buildRemoveLink() {
|
|
|
589
612
|
wrap.appendChild(btn);
|
|
590
613
|
return wrap;
|
|
591
614
|
}
|
|
615
|
+
function resolveExistingRef(ref, pages) {
|
|
616
|
+
if (!ref) return null;
|
|
617
|
+
const [collection, ...rest] = ref.split(":");
|
|
618
|
+
const slug = rest.join(":");
|
|
619
|
+
if (!collection || !slug) return null;
|
|
620
|
+
return pages.find((p) => p.collection === collection && p.slug === slug) ?? null;
|
|
621
|
+
}
|
|
622
|
+
function renderCurrentRefLine(box, ref, pages) {
|
|
623
|
+
if (!ref) {
|
|
624
|
+
box.style.display = "none";
|
|
625
|
+
box.innerHTML = "";
|
|
626
|
+
return;
|
|
627
|
+
}
|
|
628
|
+
const label = escapeHtml(uiLabels.linkCurrent);
|
|
629
|
+
const page = resolveExistingRef(ref, pages);
|
|
630
|
+
box.style.display = "block";
|
|
631
|
+
box.innerHTML = page ? `${label}: <strong>${escapeHtml(page.title)}</strong> <span style="color:#9aa3b2;font-family:ui-monospace,Menlo,monospace">${escapeHtml(page.path)}</span>` : `${label}: <span style="font-family:ui-monospace,Menlo,monospace">${escapeHtml(ref)}</span>`;
|
|
632
|
+
}
|
|
633
|
+
function paintCurrentRef(pages) {
|
|
634
|
+
const box = linkDialog?.querySelector('[data-role="current"]');
|
|
635
|
+
if (box) renderCurrentRefLine(box, linkEditing?.getAttribute("data-cms-ref"), pages ?? []);
|
|
636
|
+
}
|
|
592
637
|
function renderLinkList(filter) {
|
|
593
638
|
const d = linkDialog;
|
|
594
639
|
if (!d) return;
|
|
@@ -614,19 +659,21 @@ function renderLinkList(filter) {
|
|
|
614
659
|
syncLinkDialog();
|
|
615
660
|
};
|
|
616
661
|
list.appendChild(row);
|
|
662
|
+
if (on) row.scrollIntoView?.({ block: "nearest" });
|
|
617
663
|
});
|
|
618
664
|
};
|
|
665
|
+
const preselect = (pages) => {
|
|
666
|
+
if (!linkPicked) linkPicked = resolveExistingRef(linkEditing?.getAttribute("data-cms-ref"), pages);
|
|
667
|
+
paintCurrentRef(pages);
|
|
668
|
+
};
|
|
619
669
|
if (linkPages) {
|
|
670
|
+
preselect(linkPages);
|
|
620
671
|
paint(linkPages);
|
|
621
672
|
return;
|
|
622
673
|
}
|
|
623
674
|
list.innerHTML = `<div style="padding:10px;font-size:12.5px;color:#9aa3b2">${uiLabels.linkLoading}</div>`;
|
|
624
675
|
fetchLinkablePages().then((pages) => {
|
|
625
|
-
|
|
626
|
-
if (ref && !linkPicked) {
|
|
627
|
-
const [c, ...rest] = ref.split(":");
|
|
628
|
-
linkPicked = pages.find((p) => p.collection === c && p.slug === rest.join(":")) ?? null;
|
|
629
|
-
}
|
|
676
|
+
preselect(pages);
|
|
630
677
|
paint(pages);
|
|
631
678
|
syncLinkDialog();
|
|
632
679
|
}).catch(() => {
|
|
@@ -701,9 +748,7 @@ function toggleEmojiPicker(anchor) {
|
|
|
701
748
|
const sel = window.getSelection();
|
|
702
749
|
if (sel && sel.rangeCount > 0) savedRange = sel.getRangeAt(0).cloneRange();
|
|
703
750
|
const rect = anchor.getBoundingClientRect();
|
|
704
|
-
emojiPicker
|
|
705
|
-
emojiPicker.style.left = `${Math.min(rect.left, window.innerWidth - 240)}px`;
|
|
706
|
-
emojiPicker.style.display = "block";
|
|
751
|
+
positionPopover(emojiPicker, rect, 6, 230);
|
|
707
752
|
}
|
|
708
753
|
function hideEmojiPicker() {
|
|
709
754
|
if (emojiPicker) emojiPicker.style.display = "none";
|
|
@@ -836,7 +881,7 @@ function serializeBlockChildren(parent) {
|
|
|
836
881
|
const s = serializeBlock(node).trim();
|
|
837
882
|
if (s) blocks.push(s);
|
|
838
883
|
} else {
|
|
839
|
-
inlineRun
|
|
884
|
+
inlineRun = joinInline(inlineRun, serializeInlineNode(node));
|
|
840
885
|
}
|
|
841
886
|
});
|
|
842
887
|
flushInline();
|
|
@@ -927,10 +972,30 @@ function preservedLinkAttrs(el) {
|
|
|
927
972
|
}
|
|
928
973
|
return out;
|
|
929
974
|
}
|
|
975
|
+
var HARD_BREAK = " \n";
|
|
976
|
+
function edgeWhitespace(ws) {
|
|
977
|
+
if (!ws) return "";
|
|
978
|
+
return /\n/.test(ws) ? HARD_BREAK : " ";
|
|
979
|
+
}
|
|
980
|
+
function wrapEmphasis(inner, delimiter) {
|
|
981
|
+
const core = inner.trim();
|
|
982
|
+
if (!core) return "";
|
|
983
|
+
const lead = edgeWhitespace(inner.slice(0, inner.length - inner.trimStart().length));
|
|
984
|
+
const trail = edgeWhitespace(inner.slice(inner.trimEnd().length));
|
|
985
|
+
return lead + delimiter + core + delimiter + trail;
|
|
986
|
+
}
|
|
987
|
+
function joinInline(out, piece) {
|
|
988
|
+
if (!piece) return out;
|
|
989
|
+
const outTail = /\s*$/.exec(out)[0];
|
|
990
|
+
const pieceHead = /^\s*/.exec(piece)[0];
|
|
991
|
+
if (!outTail || !pieceHead) return out + piece;
|
|
992
|
+
const merged = /\n/.test(outTail + pieceHead) ? HARD_BREAK : " ";
|
|
993
|
+
return out.slice(0, out.length - outTail.length) + merged + piece.slice(pieceHead.length);
|
|
994
|
+
}
|
|
930
995
|
function serializeInline(node) {
|
|
931
996
|
let out = "";
|
|
932
997
|
node.childNodes.forEach((child) => {
|
|
933
|
-
out
|
|
998
|
+
out = joinInline(out, serializeInlineNode(child));
|
|
934
999
|
});
|
|
935
1000
|
return out;
|
|
936
1001
|
}
|
|
@@ -947,11 +1012,11 @@ function serializeInlineNode(child) {
|
|
|
947
1012
|
switch (tag) {
|
|
948
1013
|
case "strong":
|
|
949
1014
|
case "b":
|
|
950
|
-
out +=
|
|
1015
|
+
out += wrapEmphasis(inner, "**");
|
|
951
1016
|
break;
|
|
952
1017
|
case "em":
|
|
953
1018
|
case "i":
|
|
954
|
-
out +=
|
|
1019
|
+
out += wrapEmphasis(inner, "*");
|
|
955
1020
|
break;
|
|
956
1021
|
case "code":
|
|
957
1022
|
out += "`" + inner + "`";
|
|
@@ -1098,6 +1163,9 @@ function injectStyles() {
|
|
|
1098
1163
|
getConnectedToken,
|
|
1099
1164
|
htmlToMarkdown,
|
|
1100
1165
|
initInlineEdit,
|
|
1101
|
-
|
|
1166
|
+
positionPopover,
|
|
1167
|
+
renderCurrentRefLine,
|
|
1168
|
+
rescanFields,
|
|
1169
|
+
resolveExistingRef
|
|
1102
1170
|
});
|
|
1103
1171
|
//# sourceMappingURL=index.cjs.map
|