website-highlighter 1.1.0 → 1.2.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.
@@ -1,4 +1,4 @@
1
- class y {
1
+ class M {
2
2
  /**
3
3
  * Calculates the Levenshtein distance for all substrings and returns their
4
4
  * distance and insertion-deletion offset.
@@ -10,13 +10,13 @@ class y {
10
10
  */
11
11
  getEditDistances(e, t) {
12
12
  var n = new Array(t.length + 1).fill([0, 0]);
13
- for (let s = 0; s < e.length; s++) {
14
- let l = [[s + 1, 0]];
13
+ for (let r = 0; r < e.length; r++) {
14
+ let a = [[r + 1, 0]];
15
15
  for (let o = 0; o < t.length; o++) {
16
- let r = e[s] != t[o], a = n[o + 1][0] + 1, h = l[o][0] + 1, d = n[o][0] + r, u = Math.min(a, Math.min(h, d)), c = [u, n[o][1]];
17
- a === u ? c[1] = n[o + 1][1] - 1 : h === u && (c[1] = l[o][1] + 1), l.push(c);
16
+ let s = e[r] != t[o], l = n[o + 1][0] + 1, c = a[o][0] + 1, d = n[o][0] + s, u = Math.min(l, Math.min(c, d)), h = [u, n[o][1]];
17
+ l === u ? h[1] = n[o + 1][1] - 1 : c === u && (h[1] = a[o][1] + 1), a.push(h);
18
18
  }
19
- n = l;
19
+ n = a;
20
20
  }
21
21
  return n;
22
22
  }
@@ -30,116 +30,134 @@ class y {
30
30
  * @return {array} Array of best substring matches.
31
31
  */
32
32
  getMatches(e, t) {
33
- let n = this.getEditDistances(e, t), s = [0], l = n[0][0];
34
- for (let r = 1; r < n.length; r++) {
35
- let a = n[r][0];
36
- a < l ? (s = [r], l = a) : a == l && s.push(r);
33
+ let n = this.getEditDistances(e, t), r = [0], a = n[0][0];
34
+ for (let s = 1; s < n.length; s++) {
35
+ let l = n[s][0];
36
+ l < a ? (r = [s], a = l) : l == a && r.push(s);
37
37
  }
38
38
  let o = [];
39
- for (let r of s) {
40
- let a = n[r], h = {
41
- distance: a[0],
42
- start: r - e.length - a[1],
39
+ for (let s of r) {
40
+ let l = n[s], c = {
41
+ distance: l[0],
42
+ start: s - e.length - l[1],
43
43
  //simplification of startPos = endPos − (needleLength + insertions − deletions)
44
- end: r
44
+ end: s
45
45
  };
46
- o.push(h);
46
+ o.push(c);
47
47
  }
48
48
  return o;
49
49
  }
50
50
  }
51
- function I(i, e) {
52
- return new y().getMatches(i, e);
51
+ function T(i, e) {
52
+ return new M().getMatches(i, e);
53
53
  }
54
- function M(i, e) {
55
- const t = I(i, e);
54
+ function b(i, e) {
55
+ const t = T(i, e);
56
56
  let n;
57
- for (const r of t)
58
- (n === void 0 || r.distance < n.distance) && (n = r);
59
- const s = Math.max(n.start, 0), l = Math.min(Math.max(n.end, s), e.length);
60
- return { value: e.slice(s, l), start: s, end: l, distance: n.distance };
57
+ for (const s of t)
58
+ (n === void 0 || s.distance < n.distance) && (n = s);
59
+ const r = Math.max(n.start, 0), a = Math.min(Math.max(n.end, r), e.length);
60
+ return { value: e.slice(r, a), start: r, end: a, distance: n.distance };
61
61
  }
62
- function T(i, e, t) {
62
+ function I(i, e, t) {
63
63
  const n = i.textContent ?? "";
64
64
  if (!Number.isInteger(e) || !Number.isInteger(t) || e < 0 || e >= t || t > n.length)
65
65
  throw new RangeError(
66
66
  `Invalid range [${e}, ${t}) for text length ${n.length}`
67
67
  );
68
- const s = i.ownerDocument, l = s.createTreeWalker(
68
+ const r = i.ownerDocument, a = r.createTreeWalker(
69
69
  i,
70
- s.defaultView.NodeFilter.SHOW_TEXT
70
+ r.defaultView.NodeFilter.SHOW_TEXT
71
71
  );
72
- let o = 0, r = null, a = 0, h = null, d = 0;
73
- for (let c = l.nextNode(); c; c = l.nextNode()) {
74
- const g = o + c.data.length;
75
- if (r === null && e >= o && e < g && (r = c, a = e - o), h === null && t > o && t <= g && (h = c, d = t - o), r && h)
72
+ let o = 0, s = null, l = 0, c = null, d = 0;
73
+ for (let h = a.nextNode(); h; h = a.nextNode()) {
74
+ const g = o + h.data.length;
75
+ if (s === null && e >= o && e < g && (s = h, l = e - o), c === null && t > o && t <= g && (c = h, d = t - o), s && c)
76
76
  break;
77
77
  o = g;
78
78
  }
79
- if (!r || !h)
79
+ if (!s || !c)
80
80
  throw new Error(
81
81
  "Could not map offsets to the DOM. The DOM may have changed."
82
82
  );
83
- const u = s.createRange();
84
- return u.setStart(r, a), u.setEnd(h, d), u;
83
+ const u = r.createRange();
84
+ return u.setStart(s, l), u.setEnd(c, d), u;
85
85
  }
86
86
  const f = "website-highlighter", w = `${f}:response`, m = 500;
87
- let H = 0;
88
- function S(i) {
87
+ let y = 0;
88
+ function H(i) {
89
89
  return new Promise((e) => globalThis.setTimeout(e, i));
90
90
  }
91
- function b(i, e, t) {
91
+ function S(i, e) {
92
+ const t = i.ownerDocument?.defaultView ?? window;
93
+ return t.MutationObserver ? new Promise((n) => {
94
+ let r;
95
+ const a = new t.MutationObserver(() => {
96
+ t.clearTimeout(r), a.disconnect(), n(!0);
97
+ });
98
+ r = t.setTimeout(() => {
99
+ a.disconnect(), n(!1);
100
+ }, e), a.observe(i, {
101
+ childList: !0,
102
+ characterData: !0,
103
+ subtree: !0
104
+ });
105
+ }) : H(e).then(() => !1);
106
+ }
107
+ function x(i, e, t) {
92
108
  const n = Math.max(i.length, e.length);
93
109
  return n === 0 ? 1 : (n - t) / n;
94
110
  }
95
111
  function p(i, e) {
96
- const t = e.textContent ?? "", { start: n, end: s, value: l, distance: o } = M(i, t), r = e.ownerDocument?.defaultView ?? window;
97
- if (!r.CSS?.highlights || !r.Highlight) throw new Error("This browser does not support the CSS Custom Highlight API.");
112
+ const t = e.textContent ?? "", { start: n, end: r, value: a, distance: o } = b(i, t), s = e.ownerDocument?.defaultView ?? window;
113
+ if (!s.CSS?.highlights || !s.Highlight) throw new Error("This browser does not support the CSS Custom Highlight API.");
98
114
  return {
99
115
  haystack: t,
100
- range: n < s ? T(e, n, s) : null,
101
- value: l,
102
- view: r,
103
- score: b(i, l, o)
116
+ range: n < r ? I(e, n, r) : null,
117
+ value: a,
118
+ view: s,
119
+ score: x(i, a, o)
104
120
  };
105
121
  }
106
122
  function E({ range: i, value: e, view: t }) {
107
123
  if (!i) throw new Error("Could not find text to highlight.");
108
124
  return t.CSS.highlights.set(f, new t.Highlight(i)), { range: i, value: e };
109
125
  }
110
- async function x(i, e, t, n, s) {
111
- let l = 0;
126
+ async function v(i, e, t, n, r) {
127
+ let a = 0;
112
128
  for (; ; ) {
113
129
  const o = p(i, e);
114
130
  if (o.score >= t) return E(o);
115
- for (; l < n && (await S(s), l += 1, (e.textContent ?? "") === o.haystack); )
116
- ;
117
- if (l >= n) throw new Error(`Could not find "${i}" with threshold ${t}. Best match was "${o.value}".`);
131
+ for (; a < n; ) {
132
+ const s = await S(e, r);
133
+ if (a += 1, s) break;
134
+ }
135
+ if (a >= n) throw new Error(`Could not find "${i}" with threshold ${t}. Best match was "${o.value}".`);
118
136
  }
119
137
  }
120
138
  function C(i, {
121
139
  root: e = document.body,
122
140
  threshold: t = 0,
123
141
  retries: n = 6,
124
- retryInterval: s = m
142
+ retryInterval: r = m
125
143
  } = {}) {
126
- return t > 0 ? x(i, e, t, n, s) : E(p(i, e));
144
+ return t > 0 ? v(i, e, t, n, r) : E(p(i, e));
127
145
  }
128
146
  function N(i, e, t = "*") {
129
147
  if (!i?.contentWindow) throw new TypeError("Expected an iframe with a contentWindow");
130
- const n = `${Date.now()}-${H++}`, s = i.contentWindow;
131
- let l;
148
+ const n = `${Date.now()}-${y++}`, r = i.contentWindow;
149
+ let a;
132
150
  function o() {
133
- s.postMessage({
151
+ r.postMessage({
134
152
  type: f,
135
153
  id: n,
136
154
  text: e
137
155
  }, t);
138
156
  }
139
- function r(a) {
140
- a.source === s && a.data?.type === w && a.data.id === n && (window.clearInterval(l), window.removeEventListener("message", r));
157
+ function s(l) {
158
+ l.source === r && l.data?.type === w && l.data.id === n && (window.clearInterval(a), window.removeEventListener("message", s));
141
159
  }
142
- window.addEventListener("message", r), o(), l = window.setInterval(o, m);
160
+ window.addEventListener("message", s), o(), a = window.setInterval(o, m);
143
161
  }
144
162
  if (typeof window < "u") {
145
163
  let i = function(t) {
@@ -1 +1 @@
1
- (function(c,f){typeof exports=="object"&&typeof module<"u"?f(exports):typeof define=="function"&&define.amd?define(["exports"],f):(c=typeof globalThis<"u"?globalThis:c||self,f(c.WebsiteHighlighter={}))})(this,(function(c){"use strict";class f{getEditDistances(t,e){var n=new Array(e.length+1).fill([0,0]);for(let r=0;r<t.length;r++){let l=[[r+1,0]];for(let o=0;o<e.length;o++){let s=t[r]!=e[o],a=n[o+1][0]+1,h=l[o][0]+1,w=n[o][0]+s,d=Math.min(a,Math.min(h,w)),u=[d,n[o][1]];a===d?u[1]=n[o+1][1]-1:h===d&&(u[1]=l[o][1]+1),l.push(u)}n=l}return n}getMatches(t,e){let n=this.getEditDistances(t,e),r=[0],l=n[0][0];for(let s=1;s<n.length;s++){let a=n[s][0];a<l?(r=[s],l=a):a==l&&r.push(s)}let o=[];for(let s of r){let a=n[s],h={distance:a[0],start:s-t.length-a[1],end:s};o.push(h)}return o}}function M(i,t){return new f().getMatches(i,t)}function b(i,t){const e=M(i,t);let n;for(const s of e)(n===void 0||s.distance<n.distance)&&(n=s);const r=Math.max(n.start,0),l=Math.min(Math.max(n.end,r),t.length);return{value:t.slice(r,l),start:r,end:l,distance:n.distance}}function S(i,t,e){const n=i.textContent??"";if(!Number.isInteger(t)||!Number.isInteger(e)||t<0||t>=e||e>n.length)throw new RangeError(`Invalid range [${t}, ${e}) for text length ${n.length}`);const r=i.ownerDocument,l=r.createTreeWalker(i,r.defaultView.NodeFilter.SHOW_TEXT);let o=0,s=null,a=0,h=null,w=0;for(let u=l.nextNode();u;u=l.nextNode()){const m=o+u.data.length;if(s===null&&t>=o&&t<m&&(s=u,a=t-o),h===null&&e>o&&e<=m&&(h=u,w=e-o),s&&h)break;o=m}if(!s||!h)throw new Error("Could not map offsets to the DOM. The DOM may have changed.");const d=r.createRange();return d.setStart(s,a),d.setEnd(h,w),d}const g="website-highlighter",p=`${g}:response`,y=500;let H=0;function x(i){return new Promise(t=>globalThis.setTimeout(t,i))}function C(i,t,e){const n=Math.max(i.length,t.length);return n===0?1:(n-e)/n}function E(i,t){const e=t.textContent??"",{start:n,end:r,value:l,distance:o}=b(i,e),s=t.ownerDocument?.defaultView??window;if(!s.CSS?.highlights||!s.Highlight)throw new Error("This browser does not support the CSS Custom Highlight API.");return{haystack:e,range:n<r?S(t,n,r):null,value:l,view:s,score:C(i,l,o)}}function T({range:i,value:t,view:e}){if(!i)throw new Error("Could not find text to highlight.");return e.CSS.highlights.set(g,new e.Highlight(i)),{range:i,value:t}}async function N(i,t,e,n,r){let l=0;for(;;){const o=E(i,t);if(o.score>=e)return T(o);for(;l<n&&(await x(r),l+=1,(t.textContent??"")===o.haystack););if(l>=n)throw new Error(`Could not find "${i}" with threshold ${e}. Best match was "${o.value}".`)}}function I(i,{root:t=document.body,threshold:e=0,retries:n=6,retryInterval:r=y}={}){return e>0?N(i,t,e,n,r):T(E(i,t))}function R(i,t,e="*"){if(!i?.contentWindow)throw new TypeError("Expected an iframe with a contentWindow");const n=`${Date.now()}-${H++}`,r=i.contentWindow;let l;function o(){r.postMessage({type:g,id:n,text:t},e)}function s(a){a.source===r&&a.data?.type===p&&a.data.id===n&&(window.clearInterval(l),window.removeEventListener("message",s))}window.addEventListener("message",s),o(),l=window.setInterval(o,y)}if(typeof window<"u"){let i=function(e){return e.origin==="null"?"*":e.origin},t=function(e){e.source?.postMessage({type:p,id:e.data.id},i(e))};window.addEventListener("message",e=>{e.data?.type===g&&(t(e),I(e.data.text,{threshold:.9}).catch(n=>console.error(n)))})}c.default=I,c.highlightInIframe=R,Object.defineProperties(c,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
1
+ (function(c,f){typeof exports=="object"&&typeof module<"u"?f(exports):typeof define=="function"&&define.amd?define(["exports"],f):(c=typeof globalThis<"u"?globalThis:c||self,f(c.WebsiteHighlighter={}))})(this,(function(c){"use strict";class f{getEditDistances(t,e){var n=new Array(e.length+1).fill([0,0]);for(let o=0;o<t.length;o++){let l=[[o+1,0]];for(let r=0;r<e.length;r++){let s=t[o]!=e[r],a=n[r+1][0]+1,u=l[r][0]+1,w=n[r][0]+s,d=Math.min(a,Math.min(u,w)),h=[d,n[r][1]];a===d?h[1]=n[r+1][1]-1:u===d&&(h[1]=l[r][1]+1),l.push(h)}n=l}return n}getMatches(t,e){let n=this.getEditDistances(t,e),o=[0],l=n[0][0];for(let s=1;s<n.length;s++){let a=n[s][0];a<l?(o=[s],l=a):a==l&&o.push(s)}let r=[];for(let s of o){let a=n[s],u={distance:a[0],start:s-t.length-a[1],end:s};r.push(u)}return r}}function y(i,t){return new f().getMatches(i,t)}function I(i,t){const e=y(i,t);let n;for(const s of e)(n===void 0||s.distance<n.distance)&&(n=s);const o=Math.max(n.start,0),l=Math.min(Math.max(n.end,o),t.length);return{value:t.slice(o,l),start:o,end:l,distance:n.distance}}function S(i,t,e){const n=i.textContent??"";if(!Number.isInteger(t)||!Number.isInteger(e)||t<0||t>=e||e>n.length)throw new RangeError(`Invalid range [${t}, ${e}) for text length ${n.length}`);const o=i.ownerDocument,l=o.createTreeWalker(i,o.defaultView.NodeFilter.SHOW_TEXT);let r=0,s=null,a=0,u=null,w=0;for(let h=l.nextNode();h;h=l.nextNode()){const m=r+h.data.length;if(s===null&&t>=r&&t<m&&(s=h,a=t-r),u===null&&e>r&&e<=m&&(u=h,w=e-r),s&&u)break;r=m}if(!s||!u)throw new Error("Could not map offsets to the DOM. The DOM may have changed.");const d=o.createRange();return d.setStart(s,a),d.setEnd(u,w),d}const g="website-highlighter",p=`${g}:response`,b=500;let H=0;function v(i){return new Promise(t=>globalThis.setTimeout(t,i))}function x(i,t){const e=i.ownerDocument?.defaultView??window;return e.MutationObserver?new Promise(n=>{let o;const l=new e.MutationObserver(()=>{e.clearTimeout(o),l.disconnect(),n(!0)});o=e.setTimeout(()=>{l.disconnect(),n(!1)},t),l.observe(i,{childList:!0,characterData:!0,subtree:!0})}):v(t).then(()=>!1)}function C(i,t,e){const n=Math.max(i.length,t.length);return n===0?1:(n-e)/n}function T(i,t){const e=t.textContent??"",{start:n,end:o,value:l,distance:r}=I(i,e),s=t.ownerDocument?.defaultView??window;if(!s.CSS?.highlights||!s.Highlight)throw new Error("This browser does not support the CSS Custom Highlight API.");return{haystack:e,range:n<o?S(t,n,o):null,value:l,view:s,score:C(i,l,r)}}function M({range:i,value:t,view:e}){if(!i)throw new Error("Could not find text to highlight.");return e.CSS.highlights.set(g,new e.Highlight(i)),{range:i,value:t}}async function O(i,t,e,n,o){let l=0;for(;;){const r=T(i,t);if(r.score>=e)return M(r);for(;l<n;){const s=await x(t,o);if(l+=1,s)break}if(l>=n)throw new Error(`Could not find "${i}" with threshold ${e}. Best match was "${r.value}".`)}}function E(i,{root:t=document.body,threshold:e=0,retries:n=6,retryInterval:o=b}={}){return e>0?O(i,t,e,n,o):M(T(i,t))}function N(i,t,e="*"){if(!i?.contentWindow)throw new TypeError("Expected an iframe with a contentWindow");const n=`${Date.now()}-${H++}`,o=i.contentWindow;let l;function r(){o.postMessage({type:g,id:n,text:t},e)}function s(a){a.source===o&&a.data?.type===p&&a.data.id===n&&(window.clearInterval(l),window.removeEventListener("message",s))}window.addEventListener("message",s),r(),l=window.setInterval(r,b)}if(typeof window<"u"){let i=function(e){return e.origin==="null"?"*":e.origin},t=function(e){e.source?.postMessage({type:p,id:e.data.id},i(e))};window.addEventListener("message",e=>{e.data?.type===g&&(t(e),E(e.data.text,{threshold:.9}).catch(n=>console.error(n)))})}c.default=E,c.highlightInIframe=N,Object.defineProperties(c,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "website-highlighter",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Fuzzy text matching and highlighting for DOM content.",
5
5
  "type": "module",
6
6
  "main": "./dist/website-highlighter.umd.cjs",