superdoc 2.23.1-next.6 → 2.23.1-next.8

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.
@@ -302,7 +302,7 @@ var awarenessStatesToArray = (context, states) => {
302
302
  var DEFAULT_ENDPOINT = "https://ingest.superdoc.dev/v1/collect";
303
303
  function getSuperdocVersion() {
304
304
  try {
305
- return "2.23.1-next.6";
305
+ return "2.23.1-next.8";
306
306
  } catch {
307
307
  return "unknown";
308
308
  }
@@ -12200,7 +12200,7 @@ function useUiFontFamily() {
12200
12200
  }
12201
12201
  //#endregion
12202
12202
  //#region src/components/CommentsLayer/CommentsDropdown.vue
12203
- var _hoisted_1$32 = { class: "comments-dropdown" };
12203
+ var _hoisted_1$31 = { class: "comments-dropdown" };
12204
12204
  var _hoisted_2$25 = ["onClick"];
12205
12205
  var _hoisted_3$21 = {
12206
12206
  key: 0,
@@ -12331,7 +12331,7 @@ var CommentsDropdown_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
12331
12331
  window.removeEventListener("scroll", updateMenuPosition, true);
12332
12332
  });
12333
12333
  return (_ctx, _cache) => {
12334
- return openBlock(), createElementBlock("div", _hoisted_1$32, [createElementVNode("div", {
12334
+ return openBlock(), createElementBlock("div", _hoisted_1$31, [createElementVNode("div", {
12335
12335
  ref_key: "triggerRef",
12336
12336
  ref: triggerRef,
12337
12337
  class: "comments-dropdown__trigger",
@@ -12360,7 +12360,7 @@ var CommentsDropdown_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
12360
12360
  }, [["__scopeId", "data-v-7eced80a"]]);
12361
12361
  //#endregion
12362
12362
  //#region src/components/CommentsLayer/InternalDropdown.vue
12363
- var _hoisted_1$31 = { class: "sd-comment-option" };
12363
+ var _hoisted_1$30 = { class: "sd-comment-option" };
12364
12364
  var _hoisted_2$24 = ["innerHTML"];
12365
12365
  var _hoisted_3$20 = { class: "sd-option-state" };
12366
12366
  var _hoisted_4$12 = ["innerHTML"];
@@ -12431,7 +12431,7 @@ var InternalDropdown_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
12431
12431
  disabled: __props.isDisabled,
12432
12432
  "content-style": { fontFamily: unref(uiFontFamily) }
12433
12433
  }, {
12434
- default: withCtx(() => [createElementVNode("div", _hoisted_1$31, [
12434
+ default: withCtx(() => [createElementVNode("div", _hoisted_1$30, [
12435
12435
  createElementVNode("div", {
12436
12436
  class: "sd-active-icon",
12437
12437
  innerHTML: activeIcon.value
@@ -12596,7 +12596,7 @@ var isAllowed = (permission, role, isInternal, context = {}) => {
12596
12596
  };
12597
12597
  //#endregion
12598
12598
  //#region src/components/general/Avatar.vue
12599
- var _hoisted_1$30 = { class: "user-container" };
12599
+ var _hoisted_1$29 = { class: "user-container" };
12600
12600
  var _hoisted_2$23 = ["src"];
12601
12601
  var _hoisted_3$19 = {
12602
12602
  key: 1,
@@ -12619,7 +12619,7 @@ var Avatar_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
12619
12619
  return email?.substring(0, 1)?.toUpperCase() || null;
12620
12620
  };
12621
12621
  return (_ctx, _cache) => {
12622
- return openBlock(), createElementBlock("div", _hoisted_1$30, [__props.user.image ? (openBlock(), createElementBlock("img", {
12622
+ return openBlock(), createElementBlock("div", _hoisted_1$29, [__props.user.image ? (openBlock(), createElementBlock("img", {
12623
12623
  key: 0,
12624
12624
  class: "user-bg",
12625
12625
  src: __props.user.image.startsWith("http") ? __props.user.image : `data:image/png;base64,${__props.user.image}`
@@ -12629,7 +12629,7 @@ var Avatar_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
12629
12629
  }, [["__scopeId", "data-v-c95b2073"]]);
12630
12630
  //#endregion
12631
12631
  //#region src/components/CommentsLayer/CommentHeader.vue
12632
- var _hoisted_1$29 = { class: "card-section comment-header" };
12632
+ var _hoisted_1$28 = { class: "card-section comment-header" };
12633
12633
  var _hoisted_2$22 = { class: "comment-header-left" };
12634
12634
  var _hoisted_3$18 = { class: "user-info" };
12635
12635
  var _hoisted_4$11 = { class: "user-name" };
@@ -12889,7 +12889,7 @@ var CommentHeader_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
12889
12889
  return user;
12890
12890
  });
12891
12891
  return (_ctx, _cache) => {
12892
- return openBlock(), createElementBlock("div", _hoisted_1$29, [createElementVNode("div", _hoisted_2$22, [createVNode(Avatar_default, {
12892
+ return openBlock(), createElementBlock("div", _hoisted_1$28, [createElementVNode("div", _hoisted_2$22, [createVNode(Avatar_default, {
12893
12893
  user: getCurrentUser.value,
12894
12894
  class: "avatar"
12895
12895
  }, null, 8, ["user"]), createElementVNode("div", _hoisted_3$18, [createElementVNode("div", _hoisted_4$11, [createTextVNode(toDisplayString(getCurrentUser.value.name), 1), isImported.value ? (openBlock(), createElementBlock("span", _hoisted_5$9, "IMPORTED")) : createCommentVNode("", true)]), props.comment.createdTime ? (openBlock(), createElementBlock("div", _hoisted_6$8, toDisplayString(unref(formatDate)(props.comment.createdTime)), 1)) : createCommentVNode("", true)])]), createElementVNode("div", { class: normalizeClass(["overflow-menu", { "is-visible": props.isActive }]) }, [
@@ -12940,7 +12940,7 @@ var CommentHeader_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
12940
12940
  }, [["__scopeId", "data-v-f2f11c96"]]);
12941
12941
  //#endregion
12942
12942
  //#region src/components/CommentsLayer/CommentInput.vue
12943
- var _hoisted_1$28 = { class: "input-section" };
12943
+ var _hoisted_1$27 = { class: "input-section" };
12944
12944
  var _hoisted_2$21 = { class: "comment-composer" };
12945
12945
  var _hoisted_3$17 = [
12946
12946
  "aria-expanded",
@@ -13114,7 +13114,7 @@ var CommentInput_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
13114
13114
  watch$1(currentCommentText, scheduleInputHeightSync);
13115
13115
  __expose({ focus });
13116
13116
  return (_ctx, _cache) => {
13117
- return openBlock(), createElementBlock("div", _hoisted_1$28, [__props.includeHeader ? (openBlock(), createBlock(CommentHeader_default, {
13117
+ return openBlock(), createElementBlock("div", _hoisted_1$27, [__props.includeHeader ? (openBlock(), createBlock(CommentHeader_default, {
13118
13118
  key: 0,
13119
13119
  config: __props.config,
13120
13120
  comment: __props.comment,
@@ -13159,8 +13159,116 @@ var CommentInput_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
13159
13159
  }
13160
13160
  }, [["__scopeId", "data-v-0720a671"]]);
13161
13161
  //#endregion
13162
+ //#region src/internal/toolbar/built-in/url-safety.js
13163
+ /**
13164
+ * Minimal href sanitizer for the built-in link popover.
13165
+ *
13166
+ * The v1 toolbar used the shared `@superdoc/url-validation` package, which is not
13167
+ * a resolvable runtime dependency of the published `superdoc` ES build. This
13168
+ * keeps the same fail-closed posture (only known-safe schemes pass) without
13169
+ * pulling in that package: dangerous schemes (`javascript:`, `data:`,
13170
+ * `vbscript:`) return `null`, mirroring the v1 contract that callers treat a
13171
+ * `null` result as an invalid URL.
13172
+ */
13173
+ var SAFE_SCHEME = /^(https?|mailto|tel):/i;
13174
+ var DANGEROUS_SCHEME = /^(javascript|data|vbscript):/i;
13175
+ var HAS_SCHEME = /^[a-z][a-z0-9+.-]*:/i;
13176
+ /**
13177
+ * Validate and normalize an href. Returns `{ href }` for safe values, or `null`.
13178
+ * @param {string} value
13179
+ * @returns {{ href: string }|null}
13180
+ */
13181
+ function sanitizeHref(value) {
13182
+ if (typeof value !== "string") return null;
13183
+ const trimmed = value.trim();
13184
+ if (!trimmed) return null;
13185
+ if (trimmed.startsWith("#")) return { href: trimmed };
13186
+ if (DANGEROUS_SCHEME.test(trimmed)) return null;
13187
+ if (HAS_SCHEME.test(trimmed)) return SAFE_SCHEME.test(trimmed) ? { href: trimmed } : null;
13188
+ return { href: trimmed };
13189
+ }
13190
+ //#endregion
13191
+ //#region src/components/CommentsLayer/comment-urls.js
13192
+ function isAbsoluteWebUrl(value) {
13193
+ if (!/^https?:\/\/[^\s/?#\\]+/i.test(value) || /[\s\\]/u.test(value)) return false;
13194
+ try {
13195
+ const url = new URL(value);
13196
+ return (url.protocol === "https:" || url.protocol === "http:") && Boolean(url.hostname);
13197
+ } catch {
13198
+ return false;
13199
+ }
13200
+ }
13201
+ function trimUrlPunctuation(value) {
13202
+ const closingDelimiter = {
13203
+ "(": ")",
13204
+ "[": "]",
13205
+ "{": "}"
13206
+ };
13207
+ const balance = {
13208
+ ")": 0,
13209
+ "]": 0,
13210
+ "}": 0
13211
+ };
13212
+ for (const character of value) {
13213
+ const close = closingDelimiter[character];
13214
+ if (close) balance[close] += 1;
13215
+ else if (Object.hasOwn(balance, character)) balance[character] -= 1;
13216
+ }
13217
+ let end = value.length;
13218
+ while (end > 0) {
13219
+ const character = value[end - 1];
13220
+ if (".,!?;:".includes(character)) end -= 1;
13221
+ else if (balance[character] < 0) {
13222
+ balance[character] += 1;
13223
+ end -= 1;
13224
+ } else break;
13225
+ }
13226
+ return value.slice(0, end);
13227
+ }
13228
+ function configureLink(link, href) {
13229
+ link.setAttribute("href", href);
13230
+ link.setAttribute("target", "_blank");
13231
+ link.setAttribute("rel", "noopener noreferrer");
13232
+ }
13233
+ /** Render links without rewriting stored comment HTML or its rich-text structure. */
13234
+ function renderCommentHtml(value) {
13235
+ if (typeof value !== "string") return "";
13236
+ if (typeof document === "undefined") return value;
13237
+ const template = document.createElement("template");
13238
+ template.innerHTML = value;
13239
+ for (const link of template.content.querySelectorAll("a")) {
13240
+ const safe = sanitizeHref(link.getAttribute("href"));
13241
+ if (safe && (isAbsoluteWebUrl(safe.href) || /^(mailto|tel):\S+$/i.test(safe.href))) configureLink(link, safe.href);
13242
+ else link.replaceWith(...link.childNodes);
13243
+ }
13244
+ const walker = document.createTreeWalker(template.content, NodeFilter.SHOW_TEXT);
13245
+ const textNodes = [];
13246
+ while (walker.nextNode()) textNodes.push(walker.currentNode);
13247
+ for (const node of textNodes) {
13248
+ if (node.parentElement?.closest("a, script, style, textarea, code, pre")) continue;
13249
+ const text = node.textContent;
13250
+ const fragment = document.createDocumentFragment();
13251
+ let end = 0;
13252
+ for (const match of text.matchAll(/(^|[\s([{])(https?:\/\/[^\s<>"']+)/gi)) {
13253
+ const href = trimUrlPunctuation(match[2]);
13254
+ if (!isAbsoluteWebUrl(href)) continue;
13255
+ const start = match.index + match[1].length;
13256
+ fragment.append(document.createTextNode(text.slice(end, start)));
13257
+ const link = document.createElement("a");
13258
+ configureLink(link, href);
13259
+ link.textContent = href;
13260
+ fragment.append(link);
13261
+ end = start + href.length;
13262
+ }
13263
+ if (end === 0) continue;
13264
+ fragment.append(document.createTextNode(text.slice(end)));
13265
+ node.replaceWith(fragment);
13266
+ }
13267
+ return template.innerHTML;
13268
+ }
13269
+ //#endregion
13162
13270
  //#region src/components/CommentsLayer/CommentDialog.vue
13163
- var _hoisted_1$27 = [
13271
+ var _hoisted_1$26 = [
13164
13272
  "aria-label",
13165
13273
  "data-comment-instance-id",
13166
13274
  "data-comment-thread-id",
@@ -13540,6 +13648,12 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
13540
13648
  return a.createdTime - b.createdTime;
13541
13649
  });
13542
13650
  });
13651
+ const renderedCommentTexts = computed$1(() => new Map(comments.value.map((comment) => [comment.commentId, renderCommentHtml(comment.commentText)])));
13652
+ const handleDialogClick = (event) => {
13653
+ if (event.target instanceof Element && event.target.closest(".comment a[href]")) return;
13654
+ event.preventDefault();
13655
+ return setFocus();
13656
+ };
13543
13657
  const dialogAccessibleLabel = computed$1(() => {
13544
13658
  if (props.comment.trackedChangeLabel) return props.comment.trackedChangeLabel;
13545
13659
  if (props.comment.trackedChange) return "Tracked change discussion";
@@ -14168,7 +14282,7 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
14168
14282
  "is-active": isDialogActive.value || isPendingNewComment.value,
14169
14283
  "is-resolved": props.comment.resolvedTime
14170
14284
  }]),
14171
- onClick: withModifiers(setFocus, ["stop", "prevent"]),
14285
+ onClick: withModifiers(handleDialogClick, ["stop"]),
14172
14286
  style: normalizeStyle(getSidebarCommentStyle.value),
14173
14287
  ref_key: "commentDialogElement",
14174
14288
  ref: commentDialogElement,
@@ -14305,7 +14419,7 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
14305
14419
  class: normalizeClass(["comment", index === 0 ? bodyOverflowClass.value : void 0]),
14306
14420
  ref_for: true,
14307
14421
  ref: index === 0 ? setParentBodyRef : void 0,
14308
- innerHTML: comment.commentText
14422
+ innerHTML: renderedCommentTexts.value.get(comment.commentId)
14309
14423
  }, null, 10, _hoisted_38)) : unref(isDebugging) && !isEditingThisComment.value(comment) ? (openBlock(), createElementBlock("div", _hoisted_39, toDisplayString(unref(editorCommentPositions)[comment.importedId !== void 0 ? comment.importedId : comment.commentId]?.bounds), 1)) : (openBlock(), createElementBlock("div", _hoisted_40, [createElementVNode("div", _hoisted_41, [createVNode(CommentInput_default, {
14310
14424
  ref_for: true,
14311
14425
  ref: setEditCommentInputRef(comment.commentId),
@@ -14378,13 +14492,13 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
14378
14492
  disabled: !hasTextContent.value || isV2WriteDisabled.value || isSubmittingReply.value,
14379
14493
  "data-disabled-reason": v2ReplyDisabledReason.value
14380
14494
  }, " Reply ", 10, _hoisted_53)])]))], 64)) : createCommentVNode("", true)
14381
- ], 64))], 14, _hoisted_1$27)), [[_directive_click_outside, handleClickOutside]]);
14495
+ ], 64))], 14, _hoisted_1$26)), [[_directive_click_outside, handleClickOutside]]);
14382
14496
  };
14383
14497
  }
14384
- }, [["__scopeId", "data-v-dcbcc0d4"]]);
14498
+ }, [["__scopeId", "data-v-c189ab35"]]);
14385
14499
  //#endregion
14386
14500
  //#region src/components/CommentsLayer/commentsList/ReviewDirectoryListItem.vue
14387
- var _hoisted_1$26 = [
14501
+ var _hoisted_1$25 = [
14388
14502
  "tabindex",
14389
14503
  "aria-posinset",
14390
14504
  "aria-setsize",
@@ -14522,13 +14636,13 @@ var ReviewDirectoryListItem_default = /*#__PURE__*/ _plugin_vue_export_helper_de
14522
14636
  "floating-page-index",
14523
14637
  "floating-position-entry",
14524
14638
  "is-floating-instance-active"
14525
- ])) : createCommentVNode("", true)], 44, _hoisted_1$26);
14639
+ ])) : createCommentVNode("", true)], 44, _hoisted_1$25);
14526
14640
  };
14527
14641
  }
14528
14642
  }, [["__scopeId", "data-v-29650a06"]]);
14529
14643
  //#endregion
14530
14644
  //#region src/components/CommentsLayer/commentsList/commentsList.vue
14531
- var _hoisted_1$25 = ["aria-busy"];
14645
+ var _hoisted_1$24 = ["aria-busy"];
14532
14646
  var _hoisted_2$19 = { key: 0 };
14533
14647
  var _hoisted_3$15 = { key: 1 };
14534
14648
  var REPEATED_HEADER_FOOTER_STORY_TYPE = "headerFooterPart";
@@ -14689,7 +14803,7 @@ var commentsList_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
14689
14803
  "total",
14690
14804
  "tab-index"
14691
14805
  ]);
14692
- }), 128))])) : createCommentVNode("", true)], 8, _hoisted_1$25);
14806
+ }), 128))])) : createCommentVNode("", true)], 8, _hoisted_1$24);
14693
14807
  };
14694
14808
  }
14695
14809
  }, [["__scopeId", "data-v-89244745"]]);
@@ -15158,7 +15272,7 @@ var resolveRemovedReviewCardContinuityTarget = ({ previousIds, currentIds, remov
15158
15272
  };
15159
15273
  //#endregion
15160
15274
  //#region src/components/CommentsLayer/FloatingComments.vue
15161
- var _hoisted_1$24 = [
15275
+ var _hoisted_1$23 = [
15162
15276
  "data-comment-id",
15163
15277
  "data-comment-instance-id",
15164
15278
  "data-comment-thread-id",
@@ -16028,14 +16142,14 @@ var FloatingComments_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
16028
16142
  "floating-page-index",
16029
16143
  "floating-position-entry",
16030
16144
  "is-floating-instance-active"
16031
- ])) : createCommentVNode("", true)], 14, _hoisted_1$24);
16145
+ ])) : createCommentVNode("", true)], 14, _hoisted_1$23);
16032
16146
  }), 128))], 4)], 36);
16033
16147
  };
16034
16148
  }
16035
16149
  }, [["__scopeId", "data-v-15b59a51"]]);
16036
16150
  //#endregion
16037
16151
  //#region src/components/CommentsLayer/PdfCommentsLayer.vue
16038
- var _hoisted_1$23 = {
16152
+ var _hoisted_1$22 = {
16039
16153
  class: "superdoc__pdf-comments-layer pdf-comments-layer",
16040
16154
  "aria-hidden": "false"
16041
16155
  };
@@ -16141,7 +16255,7 @@ var PdfCommentsLayer_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
16141
16255
  emit("anchor-activate", anchor.commentId);
16142
16256
  };
16143
16257
  return (_ctx, _cache) => {
16144
- return openBlock(), createElementBlock("div", _hoisted_1$23, [(openBlock(true), createElementBlock(Fragment, null, renderList(pdfCommentAnchors.value, (anchor) => {
16258
+ return openBlock(), createElementBlock("div", _hoisted_1$22, [(openBlock(true), createElementBlock(Fragment, null, renderList(pdfCommentAnchors.value, (anchor) => {
16145
16259
  return openBlock(), createElementBlock("div", {
16146
16260
  key: anchor.commentId,
16147
16261
  class: "sd-comment-anchor sd-highlight",
@@ -16310,7 +16424,7 @@ var useWhiteboard = ({ proxy, layers, documents, modules }) => {
16310
16424
  };
16311
16425
  //#endregion
16312
16426
  //#region src/components/Whiteboard/WhiteboardPage.vue
16313
- var _hoisted_1$22 = ["data-page-index"];
16427
+ var _hoisted_1$21 = ["data-page-index"];
16314
16428
  var WhiteboardPage_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
16315
16429
  __name: "WhiteboardPage",
16316
16430
  props: {
@@ -16442,7 +16556,7 @@ var WhiteboardPage_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
16442
16556
  height: (__props.pageSize?.height ?? __props.page.size?.height) + "px",
16443
16557
  transform: `translate(${__props.pageOffset?.left ?? 0}px, ${__props.pageOffset?.top ?? 0}px)`
16444
16558
  })
16445
- }, null, 44, _hoisted_1$22);
16559
+ }, null, 44, _hoisted_1$21);
16446
16560
  };
16447
16561
  }
16448
16562
  }, [["__scopeId", "data-v-c876c9b5"]]);
@@ -16517,7 +16631,7 @@ var WhiteboardLayer_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
16517
16631
  }, [["__scopeId", "data-v-54546c3d"]]);
16518
16632
  //#endregion
16519
16633
  //#region src/components/HtmlViewer/HtmlViewer.vue
16520
- var _hoisted_1$21 = { class: "superdoc-html-viewer" };
16634
+ var _hoisted_1$20 = { class: "superdoc-html-viewer" };
16521
16635
  var _hoisted_2$17 = { class: "superdoc-html-viewer__document" };
16522
16636
  var _hoisted_3$14 = ["innerHTML"];
16523
16637
  var HtmlViewer_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
@@ -16567,7 +16681,7 @@ var HtmlViewer_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
16567
16681
  initViewer();
16568
16682
  });
16569
16683
  return (_ctx, _cache) => {
16570
- return openBlock(), createElementBlock("div", _hoisted_1$21, [createElementVNode("div", _hoisted_2$17, [createElementVNode("div", {
16684
+ return openBlock(), createElementBlock("div", _hoisted_1$20, [createElementVNode("div", _hoisted_2$17, [createElementVNode("div", {
16571
16685
  class: "superdoc-html-viewer__content",
16572
16686
  innerHTML: documentContent.value,
16573
16687
  onMouseup: handleSelectionChange
@@ -18607,35 +18721,6 @@ function shouldHandleFindShortcut(event, { focusInside, owner }) {
18607
18721
  return (!active || active === document.body || active === document.documentElement) && ownsAmbientFindShortcut(owner);
18608
18722
  }
18609
18723
  //#endregion
18610
- //#region src/internal/toolbar/built-in/url-safety.js
18611
- /**
18612
- * Minimal href sanitizer for the built-in link popover.
18613
- *
18614
- * The v1 toolbar used the shared `@superdoc/url-validation` package, which is not
18615
- * a resolvable runtime dependency of the published `superdoc` ES build. This
18616
- * keeps the same fail-closed posture (only known-safe schemes pass) without
18617
- * pulling in that package: dangerous schemes (`javascript:`, `data:`,
18618
- * `vbscript:`) return `null`, mirroring the v1 contract that callers treat a
18619
- * `null` result as an invalid URL.
18620
- */
18621
- var SAFE_SCHEME = /^(https?|mailto|tel):/i;
18622
- var DANGEROUS_SCHEME = /^(javascript|data|vbscript):/i;
18623
- var HAS_SCHEME = /^[a-z][a-z0-9+.-]*:/i;
18624
- /**
18625
- * Validate and normalize an href. Returns `{ href }` for safe values, or `null`.
18626
- * @param {string} value
18627
- * @returns {{ href: string }|null}
18628
- */
18629
- function sanitizeHref(value) {
18630
- if (typeof value !== "string") return null;
18631
- const trimmed = value.trim();
18632
- if (!trimmed) return null;
18633
- if (trimmed.startsWith("#")) return { href: trimmed };
18634
- if (DANGEROUS_SCHEME.test(trimmed)) return null;
18635
- if (HAS_SCHEME.test(trimmed)) return SAFE_SCHEME.test(trimmed) ? { href: trimmed } : null;
18636
- return { href: trimmed };
18637
- }
18638
- //#endregion
18639
18724
  //#region ../../shared/common/icons/bold-solid.svg?raw
18640
18725
  var bold_solid_default = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 384 512\"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d=\"M0 64C0 46.3 14.3 32 32 32l48 0 16 0 128 0c70.7 0 128 57.3 128 128c0 31.3-11.3 60.1-30 82.3c37.1 22.4 62 63.1 62 109.7c0 70.7-57.3 128-128 128L96 480l-16 0-48 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l16 0 0-160L48 96 32 96C14.3 96 0 81.7 0 64zM224 224c35.3 0 64-28.7 64-64s-28.7-64-64-64L112 96l0 128 112 0zM112 288l0 128 144 0c35.3 0 64-28.7 64-64s-28.7-64-64-64l-32 0-112 0z\"/></svg>";
18641
18726
  //#endregion
@@ -18858,7 +18943,7 @@ var toolbarIcons = {
18858
18943
  };
18859
18944
  //#endregion
18860
18945
  //#region src/internal/toolbar/built-in/LinkInput.vue
18861
- var _hoisted_1$20 = {
18946
+ var _hoisted_1$19 = {
18862
18947
  key: 0,
18863
18948
  class: "link-title"
18864
18949
  };
@@ -19101,7 +19186,7 @@ var LinkInput_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
19101
19186
  if (props.goToAnchor) props.goToAnchor(anchorUrl);
19102
19187
  };
19103
19188
  return (_ctx, _cache) => {
19104
- return openBlock(), createElementBlock("div", { class: normalizeClass(["link-input-ctn", { "high-contrast": unref(isHighContrastMode) }]) }, [isAnchor.value ? (openBlock(), createElementBlock("div", _hoisted_1$20, "Page anchor")) : isViewingMode.value ? (openBlock(), createElementBlock("div", _hoisted_2$16, "Link details")) : isEditing.value ? (openBlock(), createElementBlock("div", _hoisted_3$13, "Edit link")) : (openBlock(), createElementBlock("div", _hoisted_4$8, "Add link")), __props.showInput && !isAnchor.value ? (openBlock(), createElementBlock("div", _hoisted_5$6, [
19189
+ return openBlock(), createElementBlock("div", { class: normalizeClass(["link-input-ctn", { "high-contrast": unref(isHighContrastMode) }]) }, [isAnchor.value ? (openBlock(), createElementBlock("div", _hoisted_1$19, "Page anchor")) : isViewingMode.value ? (openBlock(), createElementBlock("div", _hoisted_2$16, "Link details")) : isEditing.value ? (openBlock(), createElementBlock("div", _hoisted_3$13, "Edit link")) : (openBlock(), createElementBlock("div", _hoisted_4$8, "Add link")), __props.showInput && !isAnchor.value ? (openBlock(), createElementBlock("div", _hoisted_5$6, [
19105
19190
  createElementVNode("div", _hoisted_6$5, [_cache[5] || (_cache[5] = createElementVNode("div", { class: "input-icon text-input-icon" }, "T", -1)), withDirectives(createElementVNode("input", {
19106
19191
  type: "text",
19107
19192
  name: "text",
@@ -21474,7 +21559,7 @@ var FOCUSABLE_SELECTOR = [
21474
21559
  ].join(", ");
21475
21560
  //#endregion
21476
21561
  //#region src/components/surfaces/SurfaceDialog.vue
21477
- var _hoisted_1$19 = ["aria-labelledby", "aria-label"];
21562
+ var _hoisted_1$18 = ["aria-labelledby", "aria-label"];
21478
21563
  var _hoisted_2$15 = ["id"];
21479
21564
  var _hoisted_3$12 = { class: "sd-surface-dialog__content" };
21480
21565
  var SurfaceDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
@@ -21622,13 +21707,13 @@ var SurfaceDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
21622
21707
  "render",
21623
21708
  "resolve",
21624
21709
  "close"
21625
- ])) : __props.surface.component ? (openBlock(), createBlock(resolveDynamicComponent(__props.surface.component), normalizeProps(mergeProps({ key: 1 }, mergedComponentProps.value)), null, 16)) : createCommentVNode("", true)])], 12, _hoisted_1$19)], 32);
21710
+ ])) : __props.surface.component ? (openBlock(), createBlock(resolveDynamicComponent(__props.surface.component), normalizeProps(mergeProps({ key: 1 }, mergedComponentProps.value)), null, 16)) : createCommentVNode("", true)])], 12, _hoisted_1$18)], 32);
21626
21711
  };
21627
21712
  }
21628
21713
  }, [["__scopeId", "data-v-582b6534"]]);
21629
21714
  //#endregion
21630
21715
  //#region src/components/surfaces/SurfaceFloating.vue
21631
- var _hoisted_1$18 = ["aria-labelledby", "aria-label"];
21716
+ var _hoisted_1$17 = ["aria-labelledby", "aria-label"];
21632
21717
  var _hoisted_2$14 = ["id"];
21633
21718
  var _hoisted_3$11 = { class: "sd-surface-floating__content" };
21634
21719
  var SurfaceFloating_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
@@ -21776,7 +21861,7 @@ var SurfaceFloating_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
21776
21861
  "render",
21777
21862
  "resolve",
21778
21863
  "close"
21779
- ])) : __props.surface.component ? (openBlock(), createBlock(resolveDynamicComponent(__props.surface.component), normalizeProps(mergeProps({ key: 1 }, mergedComponentProps.value)), null, 16)) : createCommentVNode("", true)])], 14, _hoisted_1$18);
21864
+ ])) : __props.surface.component ? (openBlock(), createBlock(resolveDynamicComponent(__props.surface.component), normalizeProps(mergeProps({ key: 1 }, mergedComponentProps.value)), null, 16)) : createCommentVNode("", true)])], 14, _hoisted_1$17);
21780
21865
  };
21781
21866
  }
21782
21867
  }, [["__scopeId", "data-v-cd2be5db"]]);
@@ -22004,7 +22089,7 @@ var SurfaceHost_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
22004
22089
  }, [["__scopeId", "data-v-dad99b67"]]);
22005
22090
  //#endregion
22006
22091
  //#region src/SuperDoc.vue
22007
- var _hoisted_1$17 = ["innerHTML"];
22092
+ var _hoisted_1$16 = ["innerHTML"];
22008
22093
  var _hoisted_2$13 = { class: "superdoc__document document" };
22009
22094
  var _hoisted_3$10 = { class: "floating-comments" };
22010
22095
  var TRACKED_CHANGE_CARRIERS_RESTAMPED_EVENT = "superdoc:v2-tracked-change-carriers-restamped";
@@ -24452,7 +24537,7 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
24452
24537
  }, [createElementVNode("div", {
24453
24538
  class: "superdoc__tools-icon",
24454
24539
  innerHTML: unref(superdocIcons).comment
24455
- }, null, 8, _hoisted_1$17)], 32)], 4)) : createCommentVNode("", true), createElementVNode("div", _hoisted_2$13, [
24540
+ }, null, 8, _hoisted_1$16)], 32)], 4)) : createCommentVNode("", true), createElementVNode("div", _hoisted_2$13, [
24456
24541
  isCommentsEnabled.value ? (openBlock(), createElementBlock("div", {
24457
24542
  key: 0,
24458
24543
  class: "superdoc__selection-layer selection-layer",
@@ -39148,7 +39233,7 @@ var throttle = (func, wait, options) => {
39148
39233
  };
39149
39234
  //#endregion
39150
39235
  //#region src/internal/toolbar/built-in/ToolbarButtonIcon.vue
39151
- var _hoisted_1$16 = { class: "sd-toolbar-icon" };
39236
+ var _hoisted_1$15 = { class: "sd-toolbar-icon" };
39152
39237
  var _hoisted_2$12 = ["innerHTML"];
39153
39238
  var ToolbarButtonIcon_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
39154
39239
  __name: "ToolbarButtonIcon",
@@ -39176,7 +39261,7 @@ var ToolbarButtonIcon_default = /*#__PURE__*/ _plugin_vue_export_helper_default(
39176
39261
  return ["color", "highlight"].includes(props.name);
39177
39262
  });
39178
39263
  return (_ctx, _cache) => {
39179
- return openBlock(), createElementBlock("div", _hoisted_1$16, [createElementVNode("div", {
39264
+ return openBlock(), createElementBlock("div", _hoisted_1$15, [createElementVNode("div", {
39180
39265
  class: normalizeClass(["sd-toolbar-icon__icon", [`sd-toolbar-icon__icon--${props.name}`]]),
39181
39266
  innerHTML: __props.icon
39182
39267
  }, null, 10, _hoisted_2$12), hasColorBar.value ? (openBlock(), createElementBlock("div", {
@@ -39189,7 +39274,7 @@ var ToolbarButtonIcon_default = /*#__PURE__*/ _plugin_vue_export_helper_default(
39189
39274
  }, [["__scopeId", "data-v-65ecd5b1"]]);
39190
39275
  //#endregion
39191
39276
  //#region src/internal/toolbar/built-in/ToolbarButton.vue
39192
- var _hoisted_1$15 = [
39277
+ var _hoisted_1$14 = [
39193
39278
  "role",
39194
39279
  "aria-label",
39195
39280
  "aria-disabled"
@@ -39483,13 +39568,13 @@ var ToolbarButton_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
39483
39568
  }, null, 12, _hoisted_10$1)) : createCommentVNode("", true)
39484
39569
  ], 64)),
39485
39570
  createElementVNode("div", _hoisted_11$1, toDisplayString(`${unref(attributes).ariaLabel} ${unref(active) ? "selected" : "unset"}`), 1)
39486
- ], 10, _hoisted_2$11)], 46, _hoisted_1$15);
39571
+ ], 10, _hoisted_2$11)], 46, _hoisted_1$14);
39487
39572
  };
39488
39573
  }
39489
39574
  }, [["__scopeId", "data-v-96796456"]]);
39490
39575
  //#endregion
39491
39576
  //#region src/internal/toolbar/built-in/ToolbarSeparator.vue
39492
- var _hoisted_1$14 = {
39577
+ var _hoisted_1$13 = {
39493
39578
  class: "toolbar-separator",
39494
39579
  role: "separator",
39495
39580
  "aria-label": "Toolbar separator"
@@ -39508,7 +39593,7 @@ var ToolbarSeparator_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
39508
39593
  return "var(--sd-ui-border, #dbdbdb)";
39509
39594
  };
39510
39595
  return (_ctx, _cache) => {
39511
- return openBlock(), createElementBlock("div", _hoisted_1$14, [createElementVNode("div", {
39596
+ return openBlock(), createElementBlock("div", _hoisted_1$13, [createElementVNode("div", {
39512
39597
  class: "separator-inner",
39513
39598
  style: normalizeStyle({ backgroundColor: getSeparatorColor() })
39514
39599
  }, null, 4)]);
@@ -39517,7 +39602,7 @@ var ToolbarSeparator_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
39517
39602
  }, [["__scopeId", "data-v-cb82253a"]]);
39518
39603
  //#endregion
39519
39604
  //#region src/internal/toolbar/built-in/ToolbarDropdown.vue
39520
- var _hoisted_1$13 = { class: "toolbar-dropdown" };
39605
+ var _hoisted_1$12 = { class: "toolbar-dropdown" };
39521
39606
  var _hoisted_2$10 = ["onClick"];
39522
39607
  var _hoisted_3$8 = {
39523
39608
  key: 0,
@@ -39872,7 +39957,7 @@ var ToolbarDropdown_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
39872
39957
  window.removeEventListener("scroll", updateMenuPosition, true);
39873
39958
  });
39874
39959
  return (_ctx, _cache) => {
39875
- return openBlock(), createElementBlock("div", _hoisted_1$13, [createElementVNode("div", {
39960
+ return openBlock(), createElementBlock("div", _hoisted_1$12, [createElementVNode("div", {
39876
39961
  ref_key: "triggerRef",
39877
39962
  ref: triggerRef,
39878
39963
  class: "toolbar-dropdown-trigger",
@@ -40135,7 +40220,7 @@ var normalizeCustomFontSize = (value) => {
40135
40220
  };
40136
40221
  //#endregion
40137
40222
  //#region src/internal/toolbar/built-in/ToolbarComboBox.vue
40138
- var _hoisted_1$12 = ["data-item"];
40223
+ var _hoisted_1$11 = ["data-item"];
40139
40224
  var _hoisted_2$9 = [
40140
40225
  "id",
40141
40226
  "value",
@@ -40646,7 +40731,7 @@ var ToolbarComboBox_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
40646
40731
  }), [createElementVNode("span", _hoisted_7$1, toDisplayString(option.label), 1)], 16, _hoisted_6$3);
40647
40732
  }), 128))], 14, _hoisted_5$4)) : createCommentVNode("", true)])),
40648
40733
  createElementVNode("span", _hoisted_8$1, toDisplayString(appliedLabel.value), 1)
40649
- ], 14, _hoisted_1$12);
40734
+ ], 14, _hoisted_1$11);
40650
40735
  };
40651
40736
  }
40652
40737
  }, [["__scopeId", "data-v-e288ef9f"]]);
@@ -40734,7 +40819,6 @@ var _sfc_main$13 = {
40734
40819
  };
40735
40820
  //#endregion
40736
40821
  //#region src/internal/toolbar/built-in/SdTooltip.vue
40737
- var _hoisted_1$11 = ["data-placement"];
40738
40822
  var AUTO_HIDE_DELAY = 2500;
40739
40823
  var SdTooltip_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ Object.assign({ inheritAttrs: false }, {
40740
40824
  __name: "SdTooltip",
@@ -40770,7 +40854,6 @@ var SdTooltip_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PU
40770
40854
  top: "0px",
40771
40855
  left: "0px"
40772
40856
  });
40773
- const placement = ref("top");
40774
40857
  let closeTimeout = null;
40775
40858
  let openTimeout = null;
40776
40859
  let autoHideTimeout = null;
@@ -40808,48 +40891,17 @@ var SdTooltip_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PU
40808
40891
  close();
40809
40892
  }, AUTO_HIDE_DELAY);
40810
40893
  };
40811
- const getElementSize = (element, dimension) => {
40812
- const styles = window.getComputedStyle(element);
40813
- const size = parseFloat(styles[dimension]);
40814
- if (!Number.isFinite(size)) return dimension === "width" ? element.offsetWidth : element.offsetHeight;
40815
- if (styles.boxSizing === "border-box") return size;
40816
- return (dimension === "width" ? [
40817
- "paddingLeft",
40818
- "paddingRight",
40819
- "borderLeftWidth",
40820
- "borderRightWidth"
40821
- ] : [
40822
- "paddingTop",
40823
- "paddingBottom",
40824
- "borderTopWidth",
40825
- "borderBottomWidth"
40826
- ]).reduce((total, property) => total + (parseFloat(styles[property]) || 0), size);
40827
- };
40828
40894
  const updatePosition = () => {
40829
40895
  if (!triggerRef.value || !contentRef.value) return;
40830
40896
  const triggerRect = triggerRef.value.getBoundingClientRect();
40831
- const contentWidth = getElementSize(contentRef.value, "width");
40832
- const contentHeight = getElementSize(contentRef.value, "height");
40897
+ const contentWidth = contentRef.value.offsetWidth;
40898
+ const contentHeight = contentRef.value.offsetHeight;
40833
40899
  const viewportWidth = window.innerWidth || document.documentElement.clientWidth || 0;
40834
- const viewportHeight = document.documentElement.clientHeight || window.innerHeight || 0;
40835
40900
  const gutter = 8;
40836
- const offset = 10;
40837
40901
  let left = triggerRect.left + triggerRect.width / 2 - contentWidth / 2;
40838
40902
  left = Math.max(gutter, Math.min(left, viewportWidth - contentWidth - gutter));
40839
- const topAbove = triggerRect.top - contentHeight - offset;
40840
- const topBelow = triggerRect.bottom + offset;
40841
- const fitsAbove = topAbove >= gutter;
40842
- const fitsBelow = topBelow + contentHeight <= viewportHeight - gutter;
40843
- const availableAbove = triggerRect.top - offset;
40844
- const availableBelow = viewportHeight - triggerRect.bottom - offset;
40845
- if (fitsAbove) placement.value = "top";
40846
- else if (fitsBelow) placement.value = "bottom";
40847
- else placement.value = availableAbove >= availableBelow ? "top" : "bottom";
40848
- const desiredTop = placement.value === "top" ? topAbove : topBelow;
40849
- const minTop = Math.min(gutter, Math.max(0, viewportHeight - contentHeight));
40850
- const maxTop = Math.max(minTop, viewportHeight - contentHeight - gutter);
40851
40903
  position.value = {
40852
- top: `${Math.max(minTop, Math.min(desiredTop, maxTop))}px`,
40904
+ top: `${triggerRect.top - contentHeight - 10}px`,
40853
40905
  left: `${left}px`
40854
40906
  };
40855
40907
  };
@@ -40960,18 +41012,17 @@ var SdTooltip_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PU
40960
41012
  ref: contentRef,
40961
41013
  class: normalizeClass(mergedContentClass.value),
40962
41014
  style: normalizeStyle(contentStyle.value),
40963
- "data-placement": placement.value,
40964
41015
  onMouseenter: handleContentMouseEnter,
40965
41016
  onMouseleave: handleContentMouseLeave
40966
41017
  }, [_cache[0] || (_cache[0] = createElementVNode("span", {
40967
41018
  class: "sd-tooltip-arrow",
40968
41019
  "aria-hidden": "true"
40969
- }, null, -1)), renderSlot(_ctx.$slots, "default", {}, void 0, true)], 46, _hoisted_1$11)) : createCommentVNode("", true)]),
41020
+ }, null, -1)), renderSlot(_ctx.$slots, "default", {}, void 0, true)], 38)) : createCommentVNode("", true)]),
40970
41021
  _: 3
40971
41022
  }, 8, ["css"])]))], 64);
40972
41023
  };
40973
41024
  }
40974
- }), [["__scopeId", "data-v-44bd03f9"]]);
41025
+ }), [["__scopeId", "data-v-1449088a"]]);
40975
41026
  //#endregion
40976
41027
  //#region src/internal/toolbar/built-in/ButtonGroup.vue
40977
41028
  var _hoisted_1$10 = [
@@ -46401,7 +46452,7 @@ var SuperDoc = class extends import_eventemitter3.default {
46401
46452
  }
46402
46453
  this.userColorMap = /* @__PURE__ */ new Map();
46403
46454
  this.colorIndex = 0;
46404
- this.version = "2.23.1-next.6";
46455
+ this.version = "2.23.1-next.8";
46405
46456
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
46406
46457
  this.superdocId = config.superdocId || v4();
46407
46458
  this.colors = this.config.colors ?? [];