superdoc 2.23.1-next.6 → 2.23.1-next.7
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/collaboration-upgrade-engine.cjs +1 -1
- package/dist/collaboration-upgrade-engine.es.js +1 -1
- package/dist/style.css +68 -64
- package/dist/style.layered.css +68 -64
- package/dist/superdoc/src/components/CommentsLayer/comment-urls.d.ts +2 -0
- package/dist/superdoc.cjs +119 -34
- package/dist/superdoc.es.js +119 -34
- package/dist-cdn/style.layered.css +1 -1
- package/dist-cdn/superdoc.min.css +1 -1
- package/dist-cdn/superdoc.min.js +38 -38
- package/package.json +2 -2
package/dist/superdoc.es.js
CHANGED
|
@@ -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.
|
|
305
|
+
return "2.23.1-next.7";
|
|
306
306
|
} catch {
|
|
307
307
|
return "unknown";
|
|
308
308
|
}
|
|
@@ -13159,6 +13159,114 @@ 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
13271
|
var _hoisted_1$27 = [
|
|
13164
13272
|
"aria-label",
|
|
@@ -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(
|
|
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.
|
|
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),
|
|
@@ -14381,7 +14495,7 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
14381
14495
|
], 64))], 14, _hoisted_1$27)), [[_directive_click_outside, handleClickOutside]]);
|
|
14382
14496
|
};
|
|
14383
14497
|
}
|
|
14384
|
-
}, [["__scopeId", "data-v-
|
|
14498
|
+
}, [["__scopeId", "data-v-c189ab35"]]);
|
|
14385
14499
|
//#endregion
|
|
14386
14500
|
//#region src/components/CommentsLayer/commentsList/ReviewDirectoryListItem.vue
|
|
14387
14501
|
var _hoisted_1$26 = [
|
|
@@ -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
|
|
@@ -46401,7 +46486,7 @@ var SuperDoc = class extends import_eventemitter3.default {
|
|
|
46401
46486
|
}
|
|
46402
46487
|
this.userColorMap = /* @__PURE__ */ new Map();
|
|
46403
46488
|
this.colorIndex = 0;
|
|
46404
|
-
this.version = "2.23.1-next.
|
|
46489
|
+
this.version = "2.23.1-next.7";
|
|
46405
46490
|
this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
|
|
46406
46491
|
this.superdocId = config.superdocId || v4();
|
|
46407
46492
|
this.colors = this.config.colors ?? [];
|