@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 CHANGED
@@ -26,7 +26,10 @@ __export(index_exports, {
26
26
  getConnectedToken: () => getConnectedToken,
27
27
  htmlToMarkdown: () => htmlToMarkdown,
28
28
  initInlineEdit: () => initInlineEdit,
29
- rescanFields: () => rescanFields
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
- linkDialog.style.top = `${rect.bottom + 8}px`;
514
- linkDialog.style.left = `${Math.min(Math.max(8, rect.left - 180), window.innerWidth - 400)}px`;
515
- linkDialog.style.display = "block";
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
- const ref = linkEditing?.getAttribute("data-cms-ref");
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.style.top = `${rect.bottom + 6}px`;
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 += serializeInlineNode(node);
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 += serializeInlineNode(child);
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 += inner.trim() ? `**${inner.trim()}**` : "";
1015
+ out += wrapEmphasis(inner, "**");
951
1016
  break;
952
1017
  case "em":
953
1018
  case "i":
954
- out += inner.trim() ? `*${inner.trim()}*` : "";
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
- rescanFields
1166
+ positionPopover,
1167
+ renderCurrentRefLine,
1168
+ rescanFields,
1169
+ resolveExistingRef
1102
1170
  });
1103
1171
  //# sourceMappingURL=index.cjs.map