@devaccel-labs/comment-service 0.7.0 → 0.9.0
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/chunks/chunk-KKE43QYT.js +468 -0
- package/dist/chunks/runtime-2ZDPCFHS.js +3437 -0
- package/dist/react.d.ts +1 -1
- package/dist/react.js +68 -3766
- package/dist/types/compiler/annotate.d.ts +5 -2
- package/dist/types/react/index.d.ts +2 -1
- package/dist/types/react/loader.d.ts +10 -0
- package/dist/types/react/runtime-version.d.ts +7 -0
- package/dist/types/react/runtime.d.ts +7 -0
- package/dist/types/react/toolbar.d.ts +3 -2
- package/dist/vite.js +12 -4
- package/package.json +2 -2
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
// ../react/dist/runtime-version.js
|
|
2
|
+
var runtimeVersion = 1;
|
|
3
|
+
|
|
4
|
+
// ../core/dist/resolve.js
|
|
5
|
+
var norm = (value) => (value ?? "").replace(/\s+/g, " ").trim().toLowerCase();
|
|
6
|
+
var labelOf = (value) => norm(value.accName) || norm(value.text);
|
|
7
|
+
function isAncestorPath(ancestor, descendant) {
|
|
8
|
+
if (!ancestor || ancestor === descendant)
|
|
9
|
+
return false;
|
|
10
|
+
return descendant.startsWith(`${ancestor}/`);
|
|
11
|
+
}
|
|
12
|
+
function dropAncestors(candidates) {
|
|
13
|
+
return candidates.filter((candidate) => !candidates.some((other) => isAncestorPath(candidate.path, other.path)));
|
|
14
|
+
}
|
|
15
|
+
function finish(status, candidate, score, reason) {
|
|
16
|
+
if (candidate && !candidate.visible && (status === "pinned" || status === "drifted")) {
|
|
17
|
+
return { status: "hidden", key: candidate.key, score, reason: `hidden: ${reason}` };
|
|
18
|
+
}
|
|
19
|
+
return { status, key: candidate?.key ?? null, score, reason };
|
|
20
|
+
}
|
|
21
|
+
function sameExplicit(anchor, candidate) {
|
|
22
|
+
return anchor.explicit.some((expected) => candidate.explicit.some((actual) => actual.attr === expected.attr && actual.value === expected.value));
|
|
23
|
+
}
|
|
24
|
+
function sameComponent(anchor, candidate, requireFile) {
|
|
25
|
+
if (!anchor.component || !candidate.component)
|
|
26
|
+
return false;
|
|
27
|
+
if (anchor.component.name !== candidate.component.name)
|
|
28
|
+
return false;
|
|
29
|
+
if (requireFile) {
|
|
30
|
+
return Boolean(anchor.component.file) && anchor.component.file === candidate.component.file;
|
|
31
|
+
}
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
function sameRole(anchor, candidate) {
|
|
35
|
+
if (!anchor.role || !candidate.role)
|
|
36
|
+
return !anchor.role;
|
|
37
|
+
return anchor.role === candidate.role;
|
|
38
|
+
}
|
|
39
|
+
function sameLabel(anchor, candidate) {
|
|
40
|
+
const expected = labelOf(anchor);
|
|
41
|
+
if (!expected)
|
|
42
|
+
return false;
|
|
43
|
+
return expected === labelOf(candidate);
|
|
44
|
+
}
|
|
45
|
+
function unavailable(reason) {
|
|
46
|
+
return { status: "unavailable", key: null, score: 0, reason };
|
|
47
|
+
}
|
|
48
|
+
function resolveAnchor(anchor, candidates) {
|
|
49
|
+
const pool = candidates.filter((candidate) => candidate.route === anchor.route);
|
|
50
|
+
if (anchor.explicit.length > 0) {
|
|
51
|
+
const hits = dropAncestors(pool.filter((candidate) => sameExplicit(anchor, candidate)));
|
|
52
|
+
if (hits.length === 1)
|
|
53
|
+
return finish("pinned", hits[0], 100, "explicit id");
|
|
54
|
+
if (hits.length > 1) {
|
|
55
|
+
return { status: "ambiguous", key: null, score: 40, reason: "explicit id matches more than one element" };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const componentScoped = pool.filter((candidate) => sameComponent(anchor, candidate, true) && sameRole(anchor, candidate));
|
|
59
|
+
const labeled = dropAncestors(componentScoped.filter((candidate) => sameLabel(anchor, candidate)));
|
|
60
|
+
if (labeled.length === 1)
|
|
61
|
+
return finish("pinned", labeled[0], 100, "component file, role, and label");
|
|
62
|
+
if (labeled.length > 1) {
|
|
63
|
+
return {
|
|
64
|
+
status: "ambiguous",
|
|
65
|
+
key: null,
|
|
66
|
+
score: 50,
|
|
67
|
+
reason: "several elements in this component share the same label"
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
if (anchor.component?.file && anchor.component.name) {
|
|
71
|
+
const roots = pool.filter((candidate) => candidate.componentRoot && sameComponent(anchor, candidate, true));
|
|
72
|
+
if (roots.length === 1) {
|
|
73
|
+
const root = roots[0];
|
|
74
|
+
const inside = dropAncestors(pool.filter((candidate) => (candidate.path === root.path || isAncestorPath(root.path, candidate.path)) && sameRole(anchor, candidate)));
|
|
75
|
+
if (inside.length === 1) {
|
|
76
|
+
return finish("drifted", inside[0], 70, "same component and role, label changed");
|
|
77
|
+
}
|
|
78
|
+
const where2 = anchor.overlay ? ` Last seen in ${anchor.overlay.role} \u201C${anchor.overlay.name}\u201D.` : "";
|
|
79
|
+
return unavailable(`label no longer matches inside ${anchor.component.name}.${where2}`.trim());
|
|
80
|
+
}
|
|
81
|
+
if (roots.length === 0) {
|
|
82
|
+
const where2 = anchor.overlay ? ` Last seen in ${anchor.overlay.role} \u201C${anchor.overlay.name}\u201D.` : "";
|
|
83
|
+
return unavailable(`component ${anchor.component.name} is not on ${anchor.route}.${where2}`.trim());
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
status: "ambiguous",
|
|
87
|
+
key: null,
|
|
88
|
+
score: 45,
|
|
89
|
+
reason: "component is on the page more than once and the label no longer matches"
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
if (anchor.component?.name) {
|
|
93
|
+
const named = dropAncestors(pool.filter((candidate) => sameComponent(anchor, candidate, false) && sameRole(anchor, candidate) && sameLabel(anchor, candidate)));
|
|
94
|
+
if (named.length === 1)
|
|
95
|
+
return finish("pinned", named[0], 80, "component name and label");
|
|
96
|
+
if (named.length > 1) {
|
|
97
|
+
return { status: "ambiguous", key: null, score: 40, reason: "component name and label match more than one element" };
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const where = anchor.overlay ? ` It was inside ${anchor.overlay.role} \u201C${anchor.overlay.name}\u201D.` : "";
|
|
101
|
+
return unavailable(`no element on ${anchor.route} matches this comment.${where}`.trim());
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// ../react/dist/capture.js
|
|
105
|
+
var EXPLICIT = ["data-cs-anchor", "data-testid", "data-test", "id"];
|
|
106
|
+
function clip(value, max = 160) {
|
|
107
|
+
const text = (value ?? "").replace(/\s+/g, " ").trim();
|
|
108
|
+
return text ? text.slice(0, max) : null;
|
|
109
|
+
}
|
|
110
|
+
function usableExplicit(attr, value) {
|
|
111
|
+
if (!value || value.length > 200)
|
|
112
|
+
return false;
|
|
113
|
+
if (attr === "id" || attr === "data-testid" || attr === "data-test") {
|
|
114
|
+
if (value.startsWith(":") || value.startsWith("radix-") || value.startsWith("headlessui-"))
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
function domPath(element) {
|
|
120
|
+
const parts = [];
|
|
121
|
+
let current = element;
|
|
122
|
+
while (current && current !== current.ownerDocument.body) {
|
|
123
|
+
const parent = current.parentElement;
|
|
124
|
+
if (!parent)
|
|
125
|
+
break;
|
|
126
|
+
parts.push([...parent.children].indexOf(current));
|
|
127
|
+
current = parent;
|
|
128
|
+
}
|
|
129
|
+
return parts.reverse().join("/");
|
|
130
|
+
}
|
|
131
|
+
function intraPath(element, owner) {
|
|
132
|
+
if (!owner || owner === element)
|
|
133
|
+
return element === owner ? element.tagName.toLowerCase() : null;
|
|
134
|
+
const parts = [];
|
|
135
|
+
let current = element;
|
|
136
|
+
while (current && current !== owner) {
|
|
137
|
+
const parent = current.parentElement;
|
|
138
|
+
if (!parent)
|
|
139
|
+
break;
|
|
140
|
+
const same = [...parent.children].filter((child) => child.tagName === current.tagName);
|
|
141
|
+
const index = same.indexOf(current);
|
|
142
|
+
const tag = current.tagName.toLowerCase();
|
|
143
|
+
parts.push(same.length > 1 ? `${tag}[${index}]` : tag);
|
|
144
|
+
current = parent;
|
|
145
|
+
}
|
|
146
|
+
return parts.reverse().join("/") || null;
|
|
147
|
+
}
|
|
148
|
+
function elementText(element) {
|
|
149
|
+
let direct = "";
|
|
150
|
+
for (const node of element.childNodes) {
|
|
151
|
+
if (node.nodeType === Node.TEXT_NODE)
|
|
152
|
+
direct += node.textContent ?? "";
|
|
153
|
+
}
|
|
154
|
+
const own = clip(direct);
|
|
155
|
+
if (own)
|
|
156
|
+
return own;
|
|
157
|
+
const full = clip(element.textContent, 80);
|
|
158
|
+
if (full && element.children.length <= 3)
|
|
159
|
+
return full;
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
function labelFor(element) {
|
|
163
|
+
const aria = element.getAttribute("aria-label");
|
|
164
|
+
if (aria)
|
|
165
|
+
return clip(aria);
|
|
166
|
+
const labelledby = element.getAttribute("aria-labelledby");
|
|
167
|
+
if (labelledby) {
|
|
168
|
+
const text = labelledby.split(/\s+/).map((id) => element.ownerDocument.getElementById(id)?.textContent ?? "").join(" ");
|
|
169
|
+
const clipped = clip(text);
|
|
170
|
+
if (clipped)
|
|
171
|
+
return clipped;
|
|
172
|
+
}
|
|
173
|
+
if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {
|
|
174
|
+
if (element.labels?.[0]?.textContent)
|
|
175
|
+
return clip(element.labels[0].textContent);
|
|
176
|
+
if (element.placeholder)
|
|
177
|
+
return clip(element.placeholder);
|
|
178
|
+
}
|
|
179
|
+
if (element instanceof HTMLImageElement && element.alt)
|
|
180
|
+
return clip(element.alt);
|
|
181
|
+
return elementText(element);
|
|
182
|
+
}
|
|
183
|
+
function roleFor(element) {
|
|
184
|
+
const explicit = element.getAttribute("role");
|
|
185
|
+
if (explicit)
|
|
186
|
+
return explicit;
|
|
187
|
+
const tag = element.tagName.toLowerCase();
|
|
188
|
+
if (tag === "button")
|
|
189
|
+
return "button";
|
|
190
|
+
if (tag === "a" && element.hasAttribute("href"))
|
|
191
|
+
return "link";
|
|
192
|
+
if (tag === "textarea")
|
|
193
|
+
return "textbox";
|
|
194
|
+
if (tag === "select")
|
|
195
|
+
return "combobox";
|
|
196
|
+
if (tag === "dialog")
|
|
197
|
+
return "dialog";
|
|
198
|
+
if (/^h[1-6]$/.test(tag))
|
|
199
|
+
return "heading";
|
|
200
|
+
if (element instanceof HTMLInputElement)
|
|
201
|
+
return element.type === "checkbox" ? "checkbox" : "textbox";
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
function overlayFor(element) {
|
|
205
|
+
const node = element.closest("dialog,[role='dialog'],[role='alertdialog']");
|
|
206
|
+
if (!node)
|
|
207
|
+
return null;
|
|
208
|
+
const role = node.getAttribute("role") || (node.tagName === "DIALOG" ? "dialog" : "dialog");
|
|
209
|
+
return { role, name: labelFor(node) || "dialog" };
|
|
210
|
+
}
|
|
211
|
+
function fiberOf(element) {
|
|
212
|
+
const key2 = Object.keys(element).find((name) => name.startsWith("__reactFiber$") || name.startsWith("__reactInternalInstance$"));
|
|
213
|
+
return key2 ? element[key2] : void 0;
|
|
214
|
+
}
|
|
215
|
+
function fiberNames(element) {
|
|
216
|
+
const names = [];
|
|
217
|
+
let fiber = fiberOf(element);
|
|
218
|
+
for (let guard = 0; fiber && guard < 40; guard++) {
|
|
219
|
+
const type = fiber.type;
|
|
220
|
+
if (typeof type === "function") {
|
|
221
|
+
const fn = type;
|
|
222
|
+
const name = fn.displayName || fn.name;
|
|
223
|
+
if (name && !name.startsWith("_"))
|
|
224
|
+
names.push(name);
|
|
225
|
+
}
|
|
226
|
+
fiber = fiber.return ?? void 0;
|
|
227
|
+
}
|
|
228
|
+
return names.reverse();
|
|
229
|
+
}
|
|
230
|
+
function fiberStamps(element) {
|
|
231
|
+
const stamps = [];
|
|
232
|
+
let fiber = fiberOf(element);
|
|
233
|
+
for (let guard = 0; fiber && guard < 2e3; guard++) {
|
|
234
|
+
const props = fiber.memoizedProps;
|
|
235
|
+
const name = props && typeof props === "object" ? props["data-cs-cmp"] : void 0;
|
|
236
|
+
if (typeof name === "string" && name) {
|
|
237
|
+
const file = props?.["data-cs-file"];
|
|
238
|
+
stamps.push({ name, file: typeof file === "string" ? file : null });
|
|
239
|
+
}
|
|
240
|
+
fiber = fiber.return ?? void 0;
|
|
241
|
+
}
|
|
242
|
+
return stamps;
|
|
243
|
+
}
|
|
244
|
+
function bodyChild(element) {
|
|
245
|
+
let current = element;
|
|
246
|
+
while (current?.parentElement && current.parentElement !== current.ownerDocument.body)
|
|
247
|
+
current = current.parentElement;
|
|
248
|
+
return current?.parentElement ? current : null;
|
|
249
|
+
}
|
|
250
|
+
function obviouslyHidden(element) {
|
|
251
|
+
const dialog = element.closest("dialog");
|
|
252
|
+
if (dialog instanceof HTMLDialogElement && !dialog.open)
|
|
253
|
+
return true;
|
|
254
|
+
if (element.closest("[hidden]"))
|
|
255
|
+
return true;
|
|
256
|
+
let current = element;
|
|
257
|
+
while (current) {
|
|
258
|
+
if (current.getAttribute("aria-hidden") === "true")
|
|
259
|
+
return true;
|
|
260
|
+
current = current.parentElement;
|
|
261
|
+
}
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
function ownership(element) {
|
|
265
|
+
const stack = [];
|
|
266
|
+
let owner = null;
|
|
267
|
+
let current = element;
|
|
268
|
+
while (current) {
|
|
269
|
+
const name2 = current.getAttribute("data-cs-cmp");
|
|
270
|
+
if (name2) {
|
|
271
|
+
if (!owner)
|
|
272
|
+
owner = current;
|
|
273
|
+
stack.push(name2);
|
|
274
|
+
}
|
|
275
|
+
current = current.parentElement;
|
|
276
|
+
}
|
|
277
|
+
const top = bodyChild(element);
|
|
278
|
+
if (top && top !== element && (!owner || !top.contains(owner))) {
|
|
279
|
+
const stamps = fiberStamps(element);
|
|
280
|
+
if (stamps.length && (!owner || stamps[0].name !== owner.getAttribute("data-cs-cmp"))) {
|
|
281
|
+
return {
|
|
282
|
+
component: stamps[0],
|
|
283
|
+
stack: stamps.map((stamp) => stamp.name).reverse(),
|
|
284
|
+
componentRoot: false,
|
|
285
|
+
owner: top
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
if (owner) {
|
|
290
|
+
return {
|
|
291
|
+
component: { name: owner.getAttribute("data-cs-cmp") || "component", file: owner.getAttribute("data-cs-file") },
|
|
292
|
+
stack: stack.reverse(),
|
|
293
|
+
componentRoot: owner === element,
|
|
294
|
+
owner
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
const names = fiberNames(element);
|
|
298
|
+
const name = names.at(-1) ?? null;
|
|
299
|
+
return {
|
|
300
|
+
component: name ? { name, file: null } : null,
|
|
301
|
+
stack: names,
|
|
302
|
+
componentRoot: false,
|
|
303
|
+
owner: null
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
function candidateFromElement(element, route, key2) {
|
|
307
|
+
const owned = ownership(element);
|
|
308
|
+
const label = labelFor(element);
|
|
309
|
+
const explicit = EXPLICIT.flatMap((attr) => {
|
|
310
|
+
const value = element.getAttribute(attr);
|
|
311
|
+
return value && usableExplicit(attr, value) ? [{ attr, value }] : [];
|
|
312
|
+
});
|
|
313
|
+
return {
|
|
314
|
+
key: key2,
|
|
315
|
+
route,
|
|
316
|
+
visible: !obviouslyHidden(element),
|
|
317
|
+
path: domPath(element),
|
|
318
|
+
componentRoot: owned.componentRoot,
|
|
319
|
+
overlay: overlayFor(element),
|
|
320
|
+
explicit,
|
|
321
|
+
component: owned.component,
|
|
322
|
+
stack: owned.stack,
|
|
323
|
+
role: roleFor(element),
|
|
324
|
+
accName: label,
|
|
325
|
+
text: label,
|
|
326
|
+
tag: element.tagName.toLowerCase(),
|
|
327
|
+
intra: intraPath(element, owned.owner)
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
function captureAnchor(element, route = window.location.pathname) {
|
|
331
|
+
const candidate = candidateFromElement(element, route, "target");
|
|
332
|
+
return {
|
|
333
|
+
v: 1,
|
|
334
|
+
route,
|
|
335
|
+
overlay: candidate.overlay,
|
|
336
|
+
explicit: candidate.explicit,
|
|
337
|
+
component: candidate.component,
|
|
338
|
+
stack: candidate.stack,
|
|
339
|
+
role: candidate.role,
|
|
340
|
+
accName: candidate.accName,
|
|
341
|
+
text: candidate.text,
|
|
342
|
+
tag: candidate.tag,
|
|
343
|
+
intra: candidate.intra
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
function collectCandidates(route = window.location.pathname) {
|
|
347
|
+
const root = document.getElementById("cs-root");
|
|
348
|
+
const found = [];
|
|
349
|
+
const nodes = document.body?.querySelectorAll("*") ?? [];
|
|
350
|
+
let index = 0;
|
|
351
|
+
for (const element of nodes) {
|
|
352
|
+
if (root && (element === root || root.contains(element)))
|
|
353
|
+
continue;
|
|
354
|
+
const tag = element.tagName;
|
|
355
|
+
if (tag === "SCRIPT" || tag === "STYLE" || tag === "LINK" || tag === "META")
|
|
356
|
+
continue;
|
|
357
|
+
if (index > 8e3)
|
|
358
|
+
break;
|
|
359
|
+
found.push({ element, candidate: candidateFromElement(element, route, `e${index}`) });
|
|
360
|
+
index += 1;
|
|
361
|
+
}
|
|
362
|
+
return found;
|
|
363
|
+
}
|
|
364
|
+
function resolveInDocument(anchor, route = window.location.pathname) {
|
|
365
|
+
const found = collectCandidates(route);
|
|
366
|
+
const resolution = resolveAnchor(anchor, found.map((item) => item.candidate));
|
|
367
|
+
const element = found.find((item) => item.candidate.key === resolution.key)?.element ?? null;
|
|
368
|
+
return { resolution, element };
|
|
369
|
+
}
|
|
370
|
+
function elementAt(x, y) {
|
|
371
|
+
const root = document.getElementById("cs-root");
|
|
372
|
+
for (const element of document.elementsFromPoint(x, y)) {
|
|
373
|
+
if (element === document.body || element === document.documentElement)
|
|
374
|
+
continue;
|
|
375
|
+
if (root && (element === root || root.contains(element)))
|
|
376
|
+
continue;
|
|
377
|
+
const tag = element.tagName;
|
|
378
|
+
if (tag === "SCRIPT" || tag === "STYLE")
|
|
379
|
+
continue;
|
|
380
|
+
return element;
|
|
381
|
+
}
|
|
382
|
+
return null;
|
|
383
|
+
}
|
|
384
|
+
function describeElement(element) {
|
|
385
|
+
const name = ownership(element).component?.name;
|
|
386
|
+
const label = labelFor(element);
|
|
387
|
+
if (name && label)
|
|
388
|
+
return `${name} \u2014 ${label}`;
|
|
389
|
+
return name || label || element.tagName.toLowerCase();
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// ../react/dist/handoff.js
|
|
393
|
+
var key = "devaccel.comment.handoff";
|
|
394
|
+
var ttl = 30 * 60 * 1e3;
|
|
395
|
+
function readHandoff() {
|
|
396
|
+
try {
|
|
397
|
+
const value = JSON.parse(sessionStorage.getItem(key) ?? "null");
|
|
398
|
+
return value && Date.now() - value.at < ttl ? value : null;
|
|
399
|
+
} catch {
|
|
400
|
+
return null;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
function write(value) {
|
|
404
|
+
try {
|
|
405
|
+
if (value.invite || value.thread)
|
|
406
|
+
sessionStorage.setItem(key, JSON.stringify(value));
|
|
407
|
+
else
|
|
408
|
+
sessionStorage.removeItem(key);
|
|
409
|
+
} catch {
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
function linkParams() {
|
|
413
|
+
const url = new URL(window.location.href);
|
|
414
|
+
const hash = new URLSearchParams(url.hash.slice(1));
|
|
415
|
+
return {
|
|
416
|
+
url,
|
|
417
|
+
hash,
|
|
418
|
+
invite: url.searchParams.get("cs-invite") ?? hash.get("cs-invite"),
|
|
419
|
+
thread: url.searchParams.get("cs-thread") ?? hash.get("cs-thread")
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
function captureHandoff() {
|
|
423
|
+
if (typeof window === "undefined")
|
|
424
|
+
return;
|
|
425
|
+
const { invite, thread } = linkParams();
|
|
426
|
+
if (!invite && !thread)
|
|
427
|
+
return;
|
|
428
|
+
write({ ...readHandoff(), ...invite ? { invite } : {}, ...thread ? { thread } : {}, at: Date.now() });
|
|
429
|
+
}
|
|
430
|
+
function dropHandoff(part) {
|
|
431
|
+
const current = readHandoff();
|
|
432
|
+
if (!current)
|
|
433
|
+
return;
|
|
434
|
+
const { [part]: _dropped, ...rest } = current;
|
|
435
|
+
write(rest);
|
|
436
|
+
}
|
|
437
|
+
function stripHandoffFromUrl() {
|
|
438
|
+
const { url, hash } = linkParams();
|
|
439
|
+
const inQuery = url.searchParams.has("cs-invite") || url.searchParams.has("cs-thread");
|
|
440
|
+
const inHash = hash.has("cs-invite") || hash.has("cs-thread");
|
|
441
|
+
if (!inQuery && !inHash)
|
|
442
|
+
return;
|
|
443
|
+
url.searchParams.delete("cs-invite");
|
|
444
|
+
url.searchParams.delete("cs-thread");
|
|
445
|
+
if (inHash)
|
|
446
|
+
url.hash = "";
|
|
447
|
+
history.replaceState(history.state, "", url);
|
|
448
|
+
}
|
|
449
|
+
function linkWith(href, name, value) {
|
|
450
|
+
const url = new URL(href, window.location.origin);
|
|
451
|
+
url.searchParams.delete("cs-invite");
|
|
452
|
+
url.searchParams.delete("cs-thread");
|
|
453
|
+
url.hash = `${name}=${encodeURIComponent(value)}`;
|
|
454
|
+
return url.toString();
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
export {
|
|
458
|
+
captureAnchor,
|
|
459
|
+
resolveInDocument,
|
|
460
|
+
elementAt,
|
|
461
|
+
describeElement,
|
|
462
|
+
readHandoff,
|
|
463
|
+
captureHandoff,
|
|
464
|
+
dropHandoff,
|
|
465
|
+
stripHandoffFromUrl,
|
|
466
|
+
linkWith,
|
|
467
|
+
runtimeVersion
|
|
468
|
+
};
|