website-highlighter 1.1.0 → 1.3.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/README.md +22 -4
- package/dist/website-highlighter.js +189 -89
- package/dist/website-highlighter.umd.cjs +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ Import the default function and pass the text you want to find. The library find
|
|
|
16
16
|
import WebsiteHighlighter from 'website-highlighter'
|
|
17
17
|
|
|
18
18
|
const article = document.querySelector('article')
|
|
19
|
-
const { range, value } = WebsiteHighlighter('custom highlight api', {
|
|
19
|
+
const { range, value } = await WebsiteHighlighter('custom highlight api', {
|
|
20
20
|
root: article
|
|
21
21
|
})
|
|
22
22
|
|
|
@@ -36,7 +36,19 @@ Add styles for the highlight name:
|
|
|
36
36
|
If no root is passed, the library searches `document.body`.
|
|
37
37
|
|
|
38
38
|
```js
|
|
39
|
-
WebsiteHighlighter('some text on the page')
|
|
39
|
+
await WebsiteHighlighter('some text on the page')
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## CDN Usage
|
|
43
|
+
|
|
44
|
+
The browser bundle can be loaded from a CDN as a single file. Fuzzy matching uses an inline Blob worker when the browser allows it, so you do not need to host a separate worker script.
|
|
45
|
+
|
|
46
|
+
```html
|
|
47
|
+
<script type="module">
|
|
48
|
+
import WebsiteHighlighter from 'https://cdn.example.com/website-highlighter.js'
|
|
49
|
+
|
|
50
|
+
await WebsiteHighlighter('some text on the page')
|
|
51
|
+
</script>
|
|
40
52
|
```
|
|
41
53
|
|
|
42
54
|
## Iframe Usage
|
|
@@ -71,14 +83,20 @@ highlightInIframe(iframe, 'text inside the iframe', 'https://example.com')
|
|
|
71
83
|
|
|
72
84
|
### `WebsiteHighlighter(text, options)`
|
|
73
85
|
|
|
74
|
-
Finds the best fuzzy match for `text`, applies the `website-highlighter` custom highlight, and
|
|
86
|
+
Finds the best fuzzy match for `text`, applies the `website-highlighter` custom highlight, and resolves to `{ range, value }`.
|
|
75
87
|
|
|
76
88
|
- `text`: string to search for.
|
|
77
89
|
- `options.root`: optional DOM node to search. Defaults to `document.body`.
|
|
78
|
-
- `options.threshold`: optional minimum match score from `0` to `1`. When greater than `0`, the function
|
|
90
|
+
- `options.threshold`: optional minimum match score from `0` to `1`. When greater than `0`, the function retries until the threshold is met or retries are exhausted.
|
|
79
91
|
- `options.retries`: optional retry count. Defaults to `6`.
|
|
80
92
|
- `options.retryInterval`: optional retry delay in milliseconds. Defaults to `500`.
|
|
81
93
|
|
|
94
|
+
Fuzzy matching runs in a worker when the browser allows it. If worker creation is unavailable or blocked, the library falls back to synchronous matching on the main thread.
|
|
95
|
+
|
|
96
|
+
### `getMatcherMode()`
|
|
97
|
+
|
|
98
|
+
Returns `'worker'` or `'sync'` for the most recent match. This is intended for diagnostics and demos.
|
|
99
|
+
|
|
82
100
|
### `highlightInIframe(iframe, text, targetOrigin)`
|
|
83
101
|
|
|
84
102
|
Posts a highlight request to an iframe.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
class
|
|
1
|
+
class I {
|
|
2
2
|
/**
|
|
3
3
|
* Calculates the Levenshtein distance for all substrings and returns their
|
|
4
4
|
* distance and insertion-deletion offset.
|
|
@@ -9,16 +9,16 @@ class y {
|
|
|
9
9
|
* @return {array} Array of all substring matches in pairs [distance, offset]
|
|
10
10
|
*/
|
|
11
11
|
getEditDistances(e, t) {
|
|
12
|
-
var
|
|
13
|
-
for (let
|
|
14
|
-
let
|
|
15
|
-
for (let
|
|
16
|
-
let
|
|
17
|
-
|
|
12
|
+
var r = new Array(t.length + 1).fill([0, 0]);
|
|
13
|
+
for (let i = 0; i < e.length; i++) {
|
|
14
|
+
let o = [[i + 1, 0]];
|
|
15
|
+
for (let s = 0; s < t.length; s++) {
|
|
16
|
+
let a = e[i] != t[s], l = r[s + 1][0] + 1, c = o[s][0] + 1, g = r[s][0] + a, f = Math.min(l, Math.min(c, g)), d = [f, r[s][1]];
|
|
17
|
+
l === f ? d[1] = r[s + 1][1] - 1 : c === f && (d[1] = o[s][1] + 1), o.push(d);
|
|
18
18
|
}
|
|
19
|
-
|
|
19
|
+
r = o;
|
|
20
20
|
}
|
|
21
|
-
return
|
|
21
|
+
return r;
|
|
22
22
|
}
|
|
23
23
|
/**
|
|
24
24
|
* Search haystack for all instances of needle and returns an array of
|
|
@@ -30,131 +30,231 @@ class y {
|
|
|
30
30
|
* @return {array} Array of best substring matches.
|
|
31
31
|
*/
|
|
32
32
|
getMatches(e, t) {
|
|
33
|
-
let
|
|
34
|
-
for (let
|
|
35
|
-
let
|
|
36
|
-
|
|
33
|
+
let r = this.getEditDistances(e, t), i = [0], o = r[0][0];
|
|
34
|
+
for (let a = 1; a < r.length; a++) {
|
|
35
|
+
let l = r[a][0];
|
|
36
|
+
l < o ? (i = [a], o = l) : l == o && i.push(a);
|
|
37
37
|
}
|
|
38
|
-
let
|
|
39
|
-
for (let
|
|
40
|
-
let
|
|
41
|
-
distance:
|
|
42
|
-
start:
|
|
38
|
+
let s = [];
|
|
39
|
+
for (let a of i) {
|
|
40
|
+
let l = r[a], c = {
|
|
41
|
+
distance: l[0],
|
|
42
|
+
start: a - e.length - l[1],
|
|
43
43
|
//simplification of startPos = endPos − (needleLength + insertions − deletions)
|
|
44
|
-
end:
|
|
44
|
+
end: a
|
|
45
45
|
};
|
|
46
|
-
|
|
46
|
+
s.push(c);
|
|
47
47
|
}
|
|
48
|
-
return
|
|
48
|
+
return s;
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
|
-
function
|
|
52
|
-
return new
|
|
51
|
+
function T(n, e) {
|
|
52
|
+
return new I().getMatches(n, e);
|
|
53
53
|
}
|
|
54
|
-
function
|
|
55
|
-
const t =
|
|
56
|
-
let
|
|
57
|
-
for (const
|
|
58
|
-
(
|
|
59
|
-
const
|
|
60
|
-
return { value: e.slice(
|
|
54
|
+
function x(n, e) {
|
|
55
|
+
const t = T(n, e);
|
|
56
|
+
let r;
|
|
57
|
+
for (const a of t)
|
|
58
|
+
(r === void 0 || a.distance < r.distance) && (r = a);
|
|
59
|
+
const i = Math.max(r.start, 0), o = Math.min(Math.max(r.end, i), e.length);
|
|
60
|
+
return { value: e.slice(i, o), start: i, end: o, distance: r.distance };
|
|
61
61
|
}
|
|
62
|
-
function
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
const y = `(function(){"use strict";class h{getEditDistances(s,i){var t=new Array(i.length+1).fill([0,0]);for(let e=0;e<s.length;e++){let r=[[e+1,0]];for(let l=0;l<i.length;l++){let n=s[e]!=i[l],a=t[l+1][0]+1,o=r[l][0]+1,m=t[l][0]+n,u=Math.min(a,Math.min(o,m)),f=[u,t[l][1]];a===u?f[1]=t[l+1][1]-1:o===u&&(f[1]=r[l][1]+1),r.push(f)}t=r}return t}getMatches(s,i){let t=this.getEditDistances(s,i),e=[0],r=t[0][0];for(let n=1;n<t.length;n++){let a=t[n][0];a<r?(e=[n],r=a):a==r&&e.push(n)}let l=[];for(let n of e){let a=t[n],o={distance:a[0],start:n-s.length-a[1],end:n};l.push(o)}return l}}function g(c,s){return new h().getMatches(c,s)}function d(c,s){const i=g(c,s);let t;for(const n of i)(t===void 0||n.distance<t.distance)&&(t=n);const e=Math.max(t.start,0),r=Math.min(Math.max(t.end,e),s.length);return{value:s.slice(e,r),start:e,end:r,distance:t.distance}}self.addEventListener("message",c=>{const{id:s,query:i,source:t}=c.data;try{self.postMessage({id:s,result:d(i,t)})}catch(e){self.postMessage({id:s,error:e instanceof Error?e.message:String(e)})}})})();
|
|
63
|
+
`, E = typeof self < "u" && self.Blob && new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);", y], { type: "text/javascript;charset=utf-8" });
|
|
64
|
+
function W(n) {
|
|
65
|
+
let e;
|
|
66
|
+
try {
|
|
67
|
+
if (e = E && (self.URL || self.webkitURL).createObjectURL(E), !e) throw "";
|
|
68
|
+
const t = new Worker(e, {
|
|
69
|
+
name: n?.name
|
|
70
|
+
});
|
|
71
|
+
return t.addEventListener("error", () => {
|
|
72
|
+
(self.URL || self.webkitURL).revokeObjectURL(e);
|
|
73
|
+
}), t;
|
|
74
|
+
} catch {
|
|
75
|
+
return new Worker(
|
|
76
|
+
"data:text/javascript;charset=utf-8," + encodeURIComponent(y),
|
|
77
|
+
{
|
|
78
|
+
name: n?.name
|
|
79
|
+
}
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
let u, S = 0, p = !1, M = "sync";
|
|
84
|
+
const h = /* @__PURE__ */ new Map();
|
|
85
|
+
function H(n) {
|
|
86
|
+
for (const { reject: e } of h.values())
|
|
87
|
+
e(n);
|
|
88
|
+
h.clear();
|
|
89
|
+
}
|
|
90
|
+
function b(n) {
|
|
91
|
+
p = !0, u && (u.terminate(), u = void 0), H(n);
|
|
92
|
+
}
|
|
93
|
+
function C() {
|
|
94
|
+
if (!(p || typeof Worker > "u")) {
|
|
95
|
+
if (u) return u;
|
|
96
|
+
try {
|
|
97
|
+
u = new W();
|
|
98
|
+
} catch {
|
|
99
|
+
p = !0;
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
return u.addEventListener("message", (n) => {
|
|
103
|
+
const e = h.get(n.data?.id);
|
|
104
|
+
e && (h.delete(n.data.id), n.data.error ? e.reject(new Error(n.data.error)) : e.resolve(n.data.result));
|
|
105
|
+
}), u.addEventListener("error", (n) => {
|
|
106
|
+
b(n.error ?? new Error(n.message || "Worker matcher failed."));
|
|
107
|
+
}), u.addEventListener("messageerror", () => {
|
|
108
|
+
b(new Error("Worker matcher could not deserialize a message."));
|
|
109
|
+
}), u;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function O(n, e) {
|
|
113
|
+
const t = C();
|
|
114
|
+
if (!t) return;
|
|
115
|
+
const r = S++;
|
|
116
|
+
return new Promise((i, o) => {
|
|
117
|
+
h.set(r, { resolve: i, reject: o });
|
|
118
|
+
try {
|
|
119
|
+
t.postMessage({ id: r, query: n, source: e });
|
|
120
|
+
} catch (s) {
|
|
121
|
+
h.delete(r), o(s);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
function D() {
|
|
126
|
+
return M;
|
|
127
|
+
}
|
|
128
|
+
async function U(n, e) {
|
|
129
|
+
const t = O(n, e);
|
|
130
|
+
if (t)
|
|
131
|
+
try {
|
|
132
|
+
const r = await t;
|
|
133
|
+
return M = "worker", r;
|
|
134
|
+
} catch (r) {
|
|
135
|
+
b(r);
|
|
136
|
+
}
|
|
137
|
+
return M = "sync", x(n, e);
|
|
138
|
+
}
|
|
139
|
+
function j(n, e, t) {
|
|
140
|
+
const r = n.textContent ?? "";
|
|
141
|
+
if (!Number.isInteger(e) || !Number.isInteger(t) || e < 0 || e >= t || t > r.length)
|
|
65
142
|
throw new RangeError(
|
|
66
|
-
`Invalid range [${e}, ${t}) for text length ${
|
|
143
|
+
`Invalid range [${e}, ${t}) for text length ${r.length}`
|
|
67
144
|
);
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
145
|
+
const i = n.ownerDocument, o = i.createTreeWalker(
|
|
146
|
+
n,
|
|
147
|
+
i.defaultView.NodeFilter.SHOW_TEXT
|
|
71
148
|
);
|
|
72
|
-
let
|
|
73
|
-
for (let
|
|
74
|
-
const
|
|
75
|
-
if (
|
|
149
|
+
let s = 0, a = null, l = 0, c = null, g = 0;
|
|
150
|
+
for (let d = o.nextNode(); d; d = o.nextNode()) {
|
|
151
|
+
const m = s + d.data.length;
|
|
152
|
+
if (a === null && e >= s && e < m && (a = d, l = e - s), c === null && t > s && t <= m && (c = d, g = t - s), a && c)
|
|
76
153
|
break;
|
|
77
|
-
|
|
154
|
+
s = m;
|
|
78
155
|
}
|
|
79
|
-
if (!
|
|
156
|
+
if (!a || !c)
|
|
80
157
|
throw new Error(
|
|
81
158
|
"Could not map offsets to the DOM. The DOM may have changed."
|
|
82
159
|
);
|
|
83
|
-
const
|
|
84
|
-
return
|
|
160
|
+
const f = i.createRange();
|
|
161
|
+
return f.setStart(a, l), f.setEnd(c, g), f;
|
|
162
|
+
}
|
|
163
|
+
const w = "website-highlighter", k = `${w}:response`, R = 500;
|
|
164
|
+
let N = 0;
|
|
165
|
+
function $(n) {
|
|
166
|
+
return new Promise((e) => globalThis.setTimeout(e, n));
|
|
85
167
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
168
|
+
function q(n, e) {
|
|
169
|
+
const t = n.ownerDocument?.defaultView ?? window;
|
|
170
|
+
return t.MutationObserver ? new Promise((r) => {
|
|
171
|
+
let i;
|
|
172
|
+
const o = new t.MutationObserver(() => {
|
|
173
|
+
t.clearTimeout(i), o.disconnect(), r(!0);
|
|
174
|
+
});
|
|
175
|
+
i = t.setTimeout(() => {
|
|
176
|
+
o.disconnect(), r(!1);
|
|
177
|
+
}, e), o.observe(n, {
|
|
178
|
+
childList: !0,
|
|
179
|
+
characterData: !0,
|
|
180
|
+
subtree: !0
|
|
181
|
+
});
|
|
182
|
+
}) : $(e).then(() => !1);
|
|
90
183
|
}
|
|
91
|
-
function
|
|
92
|
-
const
|
|
93
|
-
return
|
|
184
|
+
function P(n, e, t) {
|
|
185
|
+
const r = Math.max(n.length, e.length);
|
|
186
|
+
return r === 0 ? 1 : (r - t) / r;
|
|
94
187
|
}
|
|
95
|
-
function
|
|
96
|
-
const t = e.textContent ?? "",
|
|
188
|
+
async function L(n, e) {
|
|
189
|
+
const t = e.textContent ?? "", r = e.ownerDocument?.defaultView ?? window;
|
|
97
190
|
if (!r.CSS?.highlights || !r.Highlight) throw new Error("This browser does not support the CSS Custom Highlight API.");
|
|
191
|
+
const { start: i, end: o, value: s, distance: a } = await U(n, t);
|
|
98
192
|
return {
|
|
99
193
|
haystack: t,
|
|
100
|
-
range:
|
|
101
|
-
value:
|
|
194
|
+
range: i < o ? j(e, i, o) : null,
|
|
195
|
+
value: s,
|
|
102
196
|
view: r,
|
|
103
|
-
score:
|
|
197
|
+
score: P(n, s, a)
|
|
104
198
|
};
|
|
105
199
|
}
|
|
106
|
-
function
|
|
107
|
-
if (!
|
|
108
|
-
return t.CSS.highlights.set(
|
|
200
|
+
function v({ range: n, value: e, view: t }) {
|
|
201
|
+
if (!n) throw new Error("Could not find text to highlight.");
|
|
202
|
+
return t.CSS.highlights.set(w, new t.Highlight(n)), { range: n, value: e };
|
|
109
203
|
}
|
|
110
|
-
async function
|
|
111
|
-
let
|
|
204
|
+
async function _(n, e, t, r, i) {
|
|
205
|
+
let o = 0;
|
|
112
206
|
for (; ; ) {
|
|
113
|
-
const
|
|
114
|
-
if (
|
|
115
|
-
for (;
|
|
116
|
-
;
|
|
117
|
-
|
|
207
|
+
const s = await L(n, e);
|
|
208
|
+
if (s.score >= t) return v(s);
|
|
209
|
+
for (; o < r; ) {
|
|
210
|
+
const a = await q(e, i);
|
|
211
|
+
if (o += 1, a) break;
|
|
212
|
+
}
|
|
213
|
+
if (o >= r) throw new Error(`Could not find "${n}" with threshold ${t}. Best match was "${s.value}".`);
|
|
118
214
|
}
|
|
119
215
|
}
|
|
120
|
-
function
|
|
216
|
+
function A() {
|
|
217
|
+
return D();
|
|
218
|
+
}
|
|
219
|
+
async function z(n, {
|
|
121
220
|
root: e = document.body,
|
|
122
221
|
threshold: t = 0,
|
|
123
|
-
retries:
|
|
124
|
-
retryInterval:
|
|
222
|
+
retries: r = 6,
|
|
223
|
+
retryInterval: i = R
|
|
125
224
|
} = {}) {
|
|
126
|
-
return t > 0 ?
|
|
127
|
-
}
|
|
128
|
-
function
|
|
129
|
-
if (!
|
|
130
|
-
const
|
|
131
|
-
let
|
|
132
|
-
function
|
|
133
|
-
|
|
134
|
-
type:
|
|
135
|
-
id:
|
|
225
|
+
return t > 0 ? _(n, e, t, r, i) : v(await L(n, e));
|
|
226
|
+
}
|
|
227
|
+
function F(n, e, t = "*") {
|
|
228
|
+
if (!n?.contentWindow) throw new TypeError("Expected an iframe with a contentWindow");
|
|
229
|
+
const r = `${Date.now()}-${N++}`, i = n.contentWindow;
|
|
230
|
+
let o;
|
|
231
|
+
function s() {
|
|
232
|
+
i.postMessage({
|
|
233
|
+
type: w,
|
|
234
|
+
id: r,
|
|
136
235
|
text: e
|
|
137
236
|
}, t);
|
|
138
237
|
}
|
|
139
|
-
function
|
|
140
|
-
|
|
238
|
+
function a(l) {
|
|
239
|
+
l.source === i && l.data?.type === k && l.data.id === r && (window.clearInterval(o), window.removeEventListener("message", a));
|
|
141
240
|
}
|
|
142
|
-
window.addEventListener("message",
|
|
241
|
+
window.addEventListener("message", a), s(), o = window.setInterval(s, R);
|
|
143
242
|
}
|
|
144
243
|
if (typeof window < "u") {
|
|
145
|
-
let
|
|
244
|
+
let n = function(t) {
|
|
146
245
|
return t.origin === "null" ? "*" : t.origin;
|
|
147
246
|
}, e = function(t) {
|
|
148
247
|
t.source?.postMessage({
|
|
149
|
-
type:
|
|
248
|
+
type: k,
|
|
150
249
|
id: t.data.id
|
|
151
|
-
},
|
|
250
|
+
}, n(t));
|
|
152
251
|
};
|
|
153
252
|
window.addEventListener("message", (t) => {
|
|
154
|
-
t.data?.type ===
|
|
253
|
+
t.data?.type === w && (e(t), z(t.data.text, { threshold: 0.9 }).catch((r) => console.error(r)));
|
|
155
254
|
});
|
|
156
255
|
}
|
|
157
256
|
export {
|
|
158
|
-
|
|
159
|
-
|
|
257
|
+
z as default,
|
|
258
|
+
A as getMatcherMode,
|
|
259
|
+
F as highlightInIframe
|
|
160
260
|
};
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
(function(
|
|
1
|
+
(function(f,w){typeof exports=="object"&&typeof module<"u"?w(exports):typeof define=="function"&&define.amd?define(["exports"],w):(f=typeof globalThis<"u"?globalThis:f||self,w(f.WebsiteHighlighter={}))})(this,(function(f){"use strict";class w{getEditDistances(e,t){var r=new Array(t.length+1).fill([0,0]);for(let s=0;s<e.length;s++){let o=[[s+1,0]];for(let i=0;i<t.length;i++){let a=e[s]!=t[i],l=r[i+1][0]+1,u=o[i][0]+1,p=r[i][0]+a,h=Math.min(l,Math.min(u,p)),d=[h,r[i][1]];l===h?d[1]=r[i+1][1]-1:u===h&&(d[1]=o[i][1]+1),o.push(d)}r=o}return r}getMatches(e,t){let r=this.getEditDistances(e,t),s=[0],o=r[0][0];for(let a=1;a<r.length;a++){let l=r[a][0];l<o?(s=[a],o=l):l==o&&s.push(a)}let i=[];for(let a of s){let l=r[a],u={distance:l[0],start:a-e.length-l[1],end:a};i.push(u)}return i}}function x(n,e){return new w().getMatches(n,e)}function S(n,e){const t=x(n,e);let r;for(const a of t)(r===void 0||a.distance<r.distance)&&(r=a);const s=Math.max(r.start,0),o=Math.min(Math.max(r.end,s),e.length);return{value:e.slice(s,o),start:s,end:o,distance:r.distance}}const k=`(function(){"use strict";class h{getEditDistances(s,i){var t=new Array(i.length+1).fill([0,0]);for(let e=0;e<s.length;e++){let r=[[e+1,0]];for(let l=0;l<i.length;l++){let n=s[e]!=i[l],a=t[l+1][0]+1,o=r[l][0]+1,m=t[l][0]+n,u=Math.min(a,Math.min(o,m)),f=[u,t[l][1]];a===u?f[1]=t[l+1][1]-1:o===u&&(f[1]=r[l][1]+1),r.push(f)}t=r}return t}getMatches(s,i){let t=this.getEditDistances(s,i),e=[0],r=t[0][0];for(let n=1;n<t.length;n++){let a=t[n][0];a<r?(e=[n],r=a):a==r&&e.push(n)}let l=[];for(let n of e){let a=t[n],o={distance:a[0],start:n-s.length-a[1],end:n};l.push(o)}return l}}function g(c,s){return new h().getMatches(c,s)}function d(c,s){const i=g(c,s);let t;for(const n of i)(t===void 0||n.distance<t.distance)&&(t=n);const e=Math.max(t.start,0),r=Math.min(Math.max(t.end,e),s.length);return{value:s.slice(e,r),start:e,end:r,distance:t.distance}}self.addEventListener("message",c=>{const{id:s,query:i,source:t}=c.data;try{self.postMessage({id:s,result:d(i,t)})}catch(e){self.postMessage({id:s,error:e instanceof Error?e.message:String(e)})}})})();
|
|
2
|
+
`,R=typeof self<"u"&&self.Blob&&new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);",k],{type:"text/javascript;charset=utf-8"});function H(n){let e;try{if(e=R&&(self.URL||self.webkitURL).createObjectURL(R),!e)throw"";const t=new Worker(e,{name:n?.name});return t.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(e)}),t}catch{return new Worker("data:text/javascript;charset=utf-8,"+encodeURIComponent(k),{name:n?.name})}}let c,O=0,M=!1,b="sync";const g=new Map;function C(n){for(const{reject:e}of g.values())e(n);g.clear()}function y(n){M=!0,c&&(c.terminate(),c=void 0),C(n)}function j(){if(!(M||typeof Worker>"u")){if(c)return c;try{c=new H}catch{M=!0;return}return c.addEventListener("message",n=>{const e=g.get(n.data?.id);e&&(g.delete(n.data.id),n.data.error?e.reject(new Error(n.data.error)):e.resolve(n.data.result))}),c.addEventListener("error",n=>{y(n.error??new Error(n.message||"Worker matcher failed."))}),c.addEventListener("messageerror",()=>{y(new Error("Worker matcher could not deserialize a message."))}),c}}function D(n,e){const t=j();if(!t)return;const r=O++;return new Promise((s,o)=>{g.set(r,{resolve:s,reject:o});try{t.postMessage({id:r,query:n,source:e})}catch(i){g.delete(r),o(i)}})}function U(){return b}async function N(n,e){const t=D(n,e);if(t)try{const r=await t;return b="worker",r}catch(r){y(r)}return b="sync",S(n,e)}function P(n,e,t){const r=n.textContent??"";if(!Number.isInteger(e)||!Number.isInteger(t)||e<0||e>=t||t>r.length)throw new RangeError(`Invalid range [${e}, ${t}) for text length ${r.length}`);const s=n.ownerDocument,o=s.createTreeWalker(n,s.defaultView.NodeFilter.SHOW_TEXT);let i=0,a=null,l=0,u=null,p=0;for(let d=o.nextNode();d;d=o.nextNode()){const E=i+d.data.length;if(a===null&&e>=i&&e<E&&(a=d,l=e-i),u===null&&t>i&&t<=E&&(u=d,p=t-i),a&&u)break;i=E}if(!a||!u)throw new Error("Could not map offsets to the DOM. The DOM may have changed.");const h=s.createRange();return h.setStart(a,l),h.setEnd(u,p),h}const m="website-highlighter",v=`${m}:response`,L=500;let $=0;function q(n){return new Promise(e=>globalThis.setTimeout(e,n))}function _(n,e){const t=n.ownerDocument?.defaultView??window;return t.MutationObserver?new Promise(r=>{let s;const o=new t.MutationObserver(()=>{t.clearTimeout(s),o.disconnect(),r(!0)});s=t.setTimeout(()=>{o.disconnect(),r(!1)},e),o.observe(n,{childList:!0,characterData:!0,subtree:!0})}):q(e).then(()=>!1)}function z(n,e,t){const r=Math.max(n.length,e.length);return r===0?1:(r-t)/r}async function T(n,e){const t=e.textContent??"",r=e.ownerDocument?.defaultView??window;if(!r.CSS?.highlights||!r.Highlight)throw new Error("This browser does not support the CSS Custom Highlight API.");const{start:s,end:o,value:i,distance:a}=await N(n,t);return{haystack:t,range:s<o?P(e,s,o):null,value:i,view:r,score:z(n,i,a)}}function I({range:n,value:e,view:t}){if(!n)throw new Error("Could not find text to highlight.");return t.CSS.highlights.set(m,new t.Highlight(n)),{range:n,value:e}}async function A(n,e,t,r,s){let o=0;for(;;){const i=await T(n,e);if(i.score>=t)return I(i);for(;o<r;){const a=await _(e,s);if(o+=1,a)break}if(o>=r)throw new Error(`Could not find "${n}" with threshold ${t}. Best match was "${i.value}".`)}}function F(){return U()}async function W(n,{root:e=document.body,threshold:t=0,retries:r=6,retryInterval:s=L}={}){return t>0?A(n,e,t,r,s):I(await T(n,e))}function B(n,e,t="*"){if(!n?.contentWindow)throw new TypeError("Expected an iframe with a contentWindow");const r=`${Date.now()}-${$++}`,s=n.contentWindow;let o;function i(){s.postMessage({type:m,id:r,text:e},t)}function a(l){l.source===s&&l.data?.type===v&&l.data.id===r&&(window.clearInterval(o),window.removeEventListener("message",a))}window.addEventListener("message",a),i(),o=window.setInterval(i,L)}if(typeof window<"u"){let n=function(t){return t.origin==="null"?"*":t.origin},e=function(t){t.source?.postMessage({type:v,id:t.data.id},n(t))};window.addEventListener("message",t=>{t.data?.type===m&&(e(t),W(t.data.text,{threshold:.9}).catch(r=>console.error(r)))})}f.default=W,f.getMatcherMode=F,f.highlightInIframe=B,Object.defineProperties(f,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
|