@panda-lingo/goldendict 0.1.3 → 0.1.5

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/index.js CHANGED
@@ -1,11 +1,11 @@
1
- class q extends Error {
1
+ class M extends Error {
2
2
  status;
3
3
  body;
4
4
  constructor(e, o, t) {
5
5
  super(e), this.name = "DictionaryApiError", this.status = o, this.body = t;
6
6
  }
7
7
  }
8
- function L(i) {
8
+ function B(i) {
9
9
  const e = i.trim() || "/api/v1";
10
10
  return e.length > 1 ? e.replace(/\/+$/, "") : e;
11
11
  }
@@ -25,7 +25,7 @@ function y(i) {
25
25
  ...i.wordCount !== void 0 ? { wordCount: i.wordCount } : {}
26
26
  };
27
27
  }
28
- async function B(i) {
28
+ async function $(i) {
29
29
  const e = await i.text();
30
30
  if (e)
31
31
  try {
@@ -40,7 +40,7 @@ class v {
40
40
  headers;
41
41
  credentials;
42
42
  constructor(e = {}) {
43
- this.baseUrl = L(e.baseUrl ?? "/api/v1");
43
+ this.baseUrl = B(e.baseUrl ?? "/api/v1");
44
44
  const o = e.fetch ?? globalThis.fetch;
45
45
  if (!o)
46
46
  throw new TypeError("A fetch implementation is required");
@@ -84,6 +84,28 @@ class v {
84
84
  lookupTimeMs: r.lookupTimeMs ?? 0
85
85
  };
86
86
  }
87
+ async suggestions(e, o = {}) {
88
+ const t = e.trim();
89
+ if (!t)
90
+ throw new TypeError("Suggestion prefix must not be empty");
91
+ const n = o.limit ?? 20;
92
+ if (!Number.isInteger(n) || n < 1 || n > 100)
93
+ throw new RangeError("Suggestion limit must be an integer between 1 and 100");
94
+ const a = new URLSearchParams({
95
+ prefix: t,
96
+ limit: String(n)
97
+ });
98
+ o.dictionaryIds?.length && a.set("dictionary_ids", o.dictionaryIds.join(","));
99
+ const r = await this.request(
100
+ `/suggestions?${a.toString()}`,
101
+ { signal: o.signal }
102
+ );
103
+ return {
104
+ prefix: r.prefix ?? t,
105
+ suggestions: r.suggestions ?? [],
106
+ lookupTimeMs: r.lookupTimeMs ?? 0
107
+ };
108
+ }
87
109
  async request(e, o = {}) {
88
110
  const t = await this.fetchImpl(`${this.baseUrl}${e}`, {
89
111
  ...o,
@@ -94,12 +116,12 @@ class v {
94
116
  ...this.headers,
95
117
  ...o.headers
96
118
  }
97
- }), n = await B(t);
119
+ }), n = await $(t);
98
120
  if (!t.ok) {
99
121
  let a = t.statusText;
100
122
  throw typeof n == "object" && n && ("message" in n ? a = String(n.message) : "error" in n && typeof n.error == "object" && n.error && "message" in n.error && (a = String(
101
123
  n.error.message
102
- ))), new q(
124
+ ))), new M(
103
125
  a || `Dictionary request failed (${t.status})`,
104
126
  t.status,
105
127
  n
@@ -108,7 +130,7 @@ class v {
108
130
  return n;
109
131
  }
110
132
  }
111
- const M = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
133
+ const R = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
112
134
  <!-- Created with Inkscape (http://www.inkscape.org/) -->
113
135
 
114
136
  <svg
@@ -154,7 +176,7 @@ const M = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
154
176
  sodipodi:nodetypes="cccc" />
155
177
  </g>
156
178
  </svg>
157
- `, U = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfmAxMKDTHgIis/AAAAwUlEQVQoz33RsUtCcRTF8U+vJ8/RCAKHdEoc+isachBcMhranQQXt/YIGmxrLAgRac/JFsP+jVqaHVvkuTy0V/08dzzfC/eew2+1FWxRz1KCG42/ZuxeKpWgaeYub++ZStcAsRcddgwdgCPVDC1qOHat7F2dz2xvMwluXeDBWQgomeDSIAp8s1DEh8PIdqUhoOQbFV8h4MojTsxjb9mbNZW13bIwtu9U72dQr7mgeNIPR10z9CwKlzXStfv/eef5uldwrDr7rieveQAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMi0wMy0xOVQxMDoxMzo0OSswMDowMH0jItoAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjItMDMtMTlUMTA6MTM6NDkrMDA6MDAMfppmAAAAAElFTkSuQmCC", $ = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
179
+ `, U = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfmAxMKDTHgIis/AAAAwUlEQVQoz33RsUtCcRTF8U+vJ8/RCAKHdEoc+isachBcMhranQQXt/YIGmxrLAgRac/JFsP+jVqaHVvkuTy0V/08dzzfC/eew2+1FWxRz1KCG42/ZuxeKpWgaeYub++ZStcAsRcddgwdgCPVDC1qOHat7F2dz2xvMwluXeDBWQgomeDSIAp8s1DEh8PIdqUhoOQbFV8h4MojTsxjb9mbNZW13bIwtu9U72dQr7mgeNIPR10z9CwKlzXStfv/eef5uldwrDr7rieveQAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMi0wMy0xOVQxMDoxMzo0OSswMDowMH0jItoAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjItMDMtMTlUMTA6MTM6NDkrMDA6MDAMfppmAAAAAElFTkSuQmCC", F = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
158
180
  <!-- Created with Inkscape (http://www.inkscape.org/) -->
159
181
 
160
182
  <svg
@@ -196,7 +218,7 @@ const M = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
196
218
  d="m 9.8109427,14.803704 8.9999993,-8.9999986 -17.9999995,2e-7 z m 0,-4.225584 -4.7744158,-4.7744144 9.5488291,-2e-7 z"
197
219
  id="rect1"
198
220
  sodipodi:nodetypes="cccccccc" /></g></svg>
199
- `, F = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
221
+ `, P = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
200
222
  <!-- Created with Inkscape (http://www.inkscape.org/) -->
201
223
 
202
224
  <svg
@@ -243,7 +265,7 @@ const M = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
243
265
  sodipodi:nodetypes="cccccccc" />
244
266
  </g>
245
267
  </svg>
246
- `, P = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
268
+ `, N = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
247
269
  <svg
248
270
  width="24.000002"
249
271
  height="24"
@@ -311,7 +333,7 @@ const M = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
311
333
  x="1.1215118e-09"
312
334
  y="4.9718442"
313
335
  ry="0.64957041" /></svg>
314
- `, R = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAATrAAAE6wHYKlsNAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAcRJREFUOI2lkztvE0EQgL8Z7/rB2T5fCixhQQc00FAjJCRkiTYV/JH0adIgfgJVGn4CKRBUSIjCHYiOBimK7KA4ORw/dofC3Ck2dhpGGu1r5pvZmV0xM/5HXDEZDAbf2u12BkiM0UIImBlmRoyxHBeLBaPRaNzv9++tAJIkyVS1673HzBCRUtfFzEo/d/VAVRERzvf2uDw6AqB6eMhlt1va9Hq9FWgJiDEiIqgqcTwmnp4CUPeearu9EmRjDYp7qiqVNEV3dgCYx8hlniMimBlZlm0GFN0QERoHB7j9/bIGVUDiHCrVfzLQqwDvPSLCZDIhz3MuLi6YTye4eY58fkOnUbkeUERMkoRWq0WaptRqDaYfXvPr3StmP75cX4PZbIb3HoDx6TmttImveZoPn9N+0KfWvbsdYGY45xARvn76zvu3H8m6GS/2dpnefLRsb4Bb2wAhBJxbLoc/hwCcDc9QqVCvuzLy+uPa2IUnu4+p36hz5/5tGkmdxWKBc45Op0MIYXsNClAzTXj28imquqKFzUbA8fHxbzMbi0glhKBmpsuEREQkqmpU1Sgi8eTkJC/8ZNN3FhEHNIHG360pkJvZdN32D0SOwDehr1HXAAAAAElFTkSuQmCC", G = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
336
+ `, G = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAATrAAAE6wHYKlsNAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAcRJREFUOI2lkztvE0EQgL8Z7/rB2T5fCixhQQc00FAjJCRkiTYV/JH0adIgfgJVGn4CKRBUSIjCHYiOBimK7KA4ORw/dofC3Ck2dhpGGu1r5pvZmV0xM/5HXDEZDAbf2u12BkiM0UIImBlmRoyxHBeLBaPRaNzv9++tAJIkyVS1673HzBCRUtfFzEo/d/VAVRERzvf2uDw6AqB6eMhlt1va9Hq9FWgJiDEiIqgqcTwmnp4CUPeearu9EmRjDYp7qiqVNEV3dgCYx8hlniMimBlZlm0GFN0QERoHB7j9/bIGVUDiHCrVfzLQqwDvPSLCZDIhz3MuLi6YTye4eY58fkOnUbkeUERMkoRWq0WaptRqDaYfXvPr3StmP75cX4PZbIb3HoDx6TmttImveZoPn9N+0KfWvbsdYGY45xARvn76zvu3H8m6GS/2dpnefLRsb4Bb2wAhBJxbLoc/hwCcDc9QqVCvuzLy+uPa2IUnu4+p36hz5/5tGkmdxWKBc45Op0MIYXsNClAzTXj28imquqKFzUbA8fHxbzMbi0glhKBmpsuEREQkqmpU1Sgi8eTkJC/8ZNN3FhEHNIHG360pkJvZdN32D0SOwDehr1HXAAAAAElFTkSuQmCC", V = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
315
337
  <!-- Created with Inkscape (http://www.inkscape.org/) -->
316
338
 
317
339
  <svg
@@ -357,7 +379,7 @@ const M = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
357
379
  sodipodi:nodetypes="cccc" />
358
380
  </g>
359
381
  </svg>
360
- `, N = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
382
+ `, O = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
361
383
  <!-- Created with Inkscape (http://www.inkscape.org/) -->
362
384
 
363
385
  <svg
@@ -399,7 +421,7 @@ const M = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
399
421
  d="m 14.310942,9.9316324 -8.9999991,-8.9999982 2e-7,17.9999978 z m -4.225584,0 -4.7744149,4.7744156 -2e-7,-9.5488279 z"
400
422
  id="rect1"
401
423
  sodipodi:nodetypes="cccccccc" /></g></svg>
402
- `, O = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
424
+ `, H = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
403
425
  <!-- Created with Inkscape (http://www.inkscape.org/) -->
404
426
 
405
427
  <svg
@@ -446,7 +468,7 @@ const M = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
446
468
  sodipodi:nodetypes="cccccccc" />
447
469
  </g>
448
470
  </svg>
449
- `, V = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
471
+ `, W = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
450
472
  <svg
451
473
  width="24.000002"
452
474
  height="24"
@@ -515,7 +537,7 @@ const M = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
515
537
  x="1.1215118e-09"
516
538
  y="4.9718442"
517
539
  ry="0.64957041" /></svg>
518
- `, H = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
540
+ `, j = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
519
541
  <!-- Created with Inkscape (http://www.inkscape.org/) -->
520
542
 
521
543
  <svg
@@ -575,7 +597,7 @@ const M = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
575
597
  id="path2"
576
598
  style="fill:url(#radialGradient2)" />
577
599
  </svg>
578
- `, W = `<?xml version="1.0" encoding="UTF-8"?>
600
+ `, Z = `<?xml version="1.0" encoding="UTF-8"?>
579
601
  <!-- Created with Inkscape (http://www.inkscape.org/) -->
580
602
  <svg width="32" height="32" version="1.1" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
581
603
  <defs>
@@ -586,7 +608,7 @@ const M = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
586
608
  </defs>
587
609
  <path d="m3.7149 8.6551 24.57 1e-6 -12.286 14.69z" fill="url(#radialGradient2)" fill-rule="evenodd" stroke-width="3.7795"/>
588
610
  </svg>
589
- `, j = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
611
+ `, X = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
590
612
  <svg
591
613
  width="23.02533"
592
614
  height="24"
@@ -699,7 +721,7 @@ const M = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
699
721
  transform="matrix(0.71827705,0,0,0.71827705,-3.1349141,-8.3199121)"
700
722
  style="fill:url(#linearGradient9);fill-opacity:1;stroke:none" />
701
723
  </svg>
702
- `, Z = `<svg fill="none" stroke="white" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
724
+ `, Q = `<svg fill="none" stroke="white" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
703
725
  <defs>
704
726
  <linearGradient id="videoGrad" y2="100%">
705
727
  <stop stop-color="#FF5F6D" offset="0"/>
@@ -709,7 +731,7 @@ const M = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
709
731
  <rect x="2" y="5" width="20" height="14" rx="2" ry="2" fill="url(#videoGrad)" stroke="none"/>
710
732
  <polygon points="10 9 15 12 10 15" fill="#fff"/>
711
733
  </svg>
712
- `, Q = `<svg fill="none" stroke="white" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
734
+ `, K = `<svg fill="none" stroke="white" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
713
735
  <defs>
714
736
  <linearGradient id="warnGrad" y2="100%">
715
737
  <stop stop-color="#FF5F6D" offset="0"/>
@@ -725,27 +747,27 @@ function s(i) {
725
747
  return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(i)}`;
726
748
  }
727
749
  const u = {
728
- "arrow.svg": s(M),
750
+ "arrow.svg": s(R),
729
751
  "audio.png": U,
730
- "collapse_article.svg": s(F),
731
- "collapse_article_hovered.svg": s($),
732
- "collapse_opt.svg": s(P),
733
- "document.png": R,
734
- "downarrow.svg": s(G),
735
- "expand_article.svg": s(O),
736
- "expand_article_hovered.svg": s(N),
737
- "expand_opt.svg": s(V),
738
- "old-arrow.svg": s(H),
739
- "old-downarrow.svg": s(W),
740
- "playsound.svg": s(j),
741
- "video.svg": s(Z),
742
- "warning.svg": s(Q)
752
+ "collapse_article.svg": s(P),
753
+ "collapse_article_hovered.svg": s(F),
754
+ "collapse_opt.svg": s(N),
755
+ "document.png": G,
756
+ "downarrow.svg": s(V),
757
+ "expand_article.svg": s(H),
758
+ "expand_article_hovered.svg": s(O),
759
+ "expand_opt.svg": s(W),
760
+ "old-arrow.svg": s(j),
761
+ "old-downarrow.svg": s(Z),
762
+ "playsound.svg": s(X),
763
+ "video.svg": s(Q),
764
+ "warning.svg": s(K)
743
765
  };
744
- function A(i) {
766
+ function S(i) {
745
767
  const e = /^qrc:\/{2,3}(?:icons\/)?([^?#]+)(?:[?#].*)?$/i.exec(i);
746
768
  return e?.[1] ? u[e[1]] : void 0;
747
769
  }
748
- function z(i) {
770
+ function A(i) {
749
771
  return i.replace(
750
772
  /qrc:\/{2,3}icons\/([a-z0-9_.-]+)/gi,
751
773
  (e, o) => u[o] ?? e
@@ -7883,19 +7905,19 @@ a:hover {
7883
7905
  code::selection {
7884
7906
  background: #333333;
7885
7907
  }
7886
- ` }, X = h["article-style.css"], K = h["article-style-print.css"], J = h["article-style-st-babylon.css"], Y = h["article-style-st-classic.css"], ee = h["article-style-st-lingoes-blue.css"], ie = h["article-style-st-lingoes.css"], te = h["article-style-st-lingvo.css"], oe = h["article-style-st-modern.css"], ne = {
7908
+ ` }, J = h["article-style.css"], Y = h["article-style-print.css"], ee = h["article-style-st-babylon.css"], ie = h["article-style-st-classic.css"], te = h["article-style-st-lingoes-blue.css"], oe = h["article-style-st-lingoes.css"], ne = h["article-style-st-lingvo.css"], re = h["article-style-st-modern.css"], ae = {
7887
7909
  default: "",
7888
- classic: Y,
7889
- modern: oe,
7890
- lingvo: te,
7891
- babylon: J,
7892
- lingoes: ie,
7893
- "lingoes-blue": ee
7894
- }, re = z(X), ae = z(K);
7895
- function de(i = "default") {
7896
- return z(ne[i]);
7897
- }
7898
- const le = `
7910
+ classic: ie,
7911
+ modern: re,
7912
+ lingvo: ne,
7913
+ babylon: ee,
7914
+ lingoes: oe,
7915
+ "lingoes-blue": te
7916
+ }, de = A(J), le = A(Y);
7917
+ function se(i = "default") {
7918
+ return A(ae[i]);
7919
+ }
7920
+ const ce = `
7899
7921
  :root {
7900
7922
  --gd-responsive-gutter: clamp(0.5rem, 2.5vw, 1rem);
7901
7923
  }
@@ -8021,13 +8043,13 @@ const le = `
8021
8043
  min-block-size: 2.75rem;
8022
8044
  }
8023
8045
  }
8024
- `, T = /* @__PURE__ */ new Set([
8046
+ `, E = /* @__PURE__ */ new Set([
8025
8047
  "bres",
8026
8048
  "qrcx",
8027
8049
  "gico",
8028
8050
  "gdau",
8029
8051
  "gdvideo"
8030
- ]), se = {
8052
+ ]), _ = "/api/v1", me = {
8031
8053
  gdlookup: "lookup",
8032
8054
  bword: "lookup",
8033
8055
  entry: "lookup",
@@ -8042,10 +8064,10 @@ const le = `
8042
8064
  gdinternal: "unsupported",
8043
8065
  ankicard: "unsupported",
8044
8066
  ankisearch: "unsupported"
8045
- }, ce = new Set(
8046
- Object.entries(se).filter(([, i]) => i === "unsupported").map(([i]) => i)
8067
+ }, pe = new Set(
8068
+ Object.entries(me).filter(([, i]) => i === "unsupported").map(([i]) => i)
8047
8069
  );
8048
- function f(i) {
8070
+ function w(i) {
8049
8071
  try {
8050
8072
  return decodeURIComponent(i);
8051
8073
  } catch {
@@ -8055,43 +8077,47 @@ function f(i) {
8055
8077
  function I(i, e) {
8056
8078
  return `${i.replace(/\/+$/, "")}/${e.replace(/^\/+/, "")}`;
8057
8079
  }
8058
- function me(i) {
8059
- return i.pathname.replace(/^\/+/, "").split("/").map((e) => encodeURIComponent(f(e))).join("/");
8080
+ function ge(i) {
8081
+ return i.pathname.replace(/^\/+/, "").split("/").map((e) => encodeURIComponent(w(e))).join("/");
8060
8082
  }
8061
- function pe(i, e) {
8083
+ function he(i, e) {
8062
8084
  return /^[a-z][a-z\d+.-]*:/i.test(i) || i.startsWith("//") ? i : /^[a-z][a-z\d+.-]*:/i.test(e) ? new URL(i, e.endsWith("/") ? e : `${e}/`).toString() : I(e, i);
8063
8085
  }
8064
- function S(i) {
8086
+ function D(i, e) {
8087
+ const o = e.replace(/[?#].*$/, "").replace(/\/+$/, "");
8088
+ return (i === _ || i.startsWith(`${_}/`)) && /(?:^|\/)api\/v1$/i.test(o) ? `${o}${i.slice(_.length)}` : /^[a-z][a-z\d+.-]*:/i.test(e) ? new URL(i, e).toString() : i;
8089
+ }
8090
+ function C(i) {
8065
8091
  const e = i.resourceBaseUrl;
8066
8092
  if (e)
8067
- return e.startsWith("/") && !e.startsWith("//") && /^[a-z][a-z\d+.-]*:/i.test(i.apiBaseUrl) ? new URL(e, i.apiBaseUrl).toString() : e;
8093
+ return e.startsWith("/") && !e.startsWith("//") ? D(e, i.apiBaseUrl) : e;
8068
8094
  }
8069
8095
  function p(i, e) {
8070
- const o = A(i);
8096
+ const o = S(i);
8071
8097
  if (o)
8072
8098
  return o;
8073
8099
  if (i.startsWith("/") && !i.startsWith("//"))
8074
- return /^[a-z][a-z\d+.-]*:/i.test(e.apiBaseUrl) ? new URL(i, e.apiBaseUrl).toString() : i;
8100
+ return D(i, e.apiBaseUrl);
8075
8101
  let t;
8076
8102
  try {
8077
8103
  t = new URL(i);
8078
8104
  } catch {
8079
- const d = S(e);
8080
- return d ? pe(i, d) : i;
8105
+ const d = C(e);
8106
+ return d ? he(i, d) : i;
8081
8107
  }
8082
8108
  const n = t.protocol.slice(0, -1).toLowerCase();
8083
- if (!T.has(n))
8109
+ if (!E.has(n))
8084
8110
  return i;
8085
8111
  const a = t.hostname || e.dictionaryId;
8086
8112
  if (n === "gico")
8087
8113
  return e.iconUrl ? p(e.iconUrl, {
8088
8114
  ...e,
8089
8115
  iconUrl: void 0
8090
- }) : A("qrc:///icons/document.png") ?? "";
8091
- const r = me(t), l = `${e.apiBaseUrl.replace(/\/+$/, "")}/dictionaries/${encodeURIComponent(a)}/resources`, m = I(S(e) ?? l, r);
8116
+ }) : S("qrc:///icons/document.png") ?? "";
8117
+ const r = ge(t), l = `${e.apiBaseUrl.replace(/\/+$/, "")}/dictionaries/${encodeURIComponent(a)}/resources`, m = I(C(e) ?? l, r);
8092
8118
  return t.hash ? `${m}${t.hash}` : m;
8093
8119
  }
8094
- function ge(i) {
8120
+ function fe(i) {
8095
8121
  const e = /^([a-z][a-z\d+.-]*):(.*)$/i.exec(i);
8096
8122
  if (!e)
8097
8123
  return;
@@ -8103,31 +8129,31 @@ function ge(i) {
8103
8129
  const r = new URL(i);
8104
8130
  t = r.searchParams.get("word") ?? r.pathname.replace(/^\/+/, ""), n = r.searchParams.get("gdanchor") ?? (r.hash.slice(1) || void 0), a = r.searchParams.get("dictionaries")?.split(",").filter(Boolean), !t && (o === "bword" || o === "entry") && (t = r.hostname);
8105
8131
  } catch {
8106
- const r = e[2]?.replace(/^\/{0,2}/, "") ?? "", [l, m] = r.split("#", 2), [d, w] = (l ?? "").split("?", 2);
8107
- t = d ?? "", n = new URLSearchParams(w ?? "").get("gdanchor") ?? (m || void 0);
8132
+ const r = e[2]?.replace(/^\/{0,2}/, "") ?? "", [l, m] = r.split("#", 2), [d, b] = (l ?? "").split("?", 2);
8133
+ t = d ?? "", n = new URLSearchParams(b ?? "").get("gdanchor") ?? (m || void 0);
8108
8134
  }
8109
- return t = f(t.replace(/^\/+/, "")), t ? {
8135
+ return t = w(t.replace(/^\/+/, "")), t ? {
8110
8136
  kind: "lookup",
8111
8137
  word: t,
8112
- ...n ? { anchor: f(n) } : {},
8138
+ ...n ? { anchor: w(n) } : {},
8113
8139
  ...a?.length ? { dictionaryIds: a } : {}
8114
8140
  } : { kind: "unsafe" };
8115
8141
  }
8116
- function D(i, e) {
8142
+ function q(i, e) {
8117
8143
  const o = i.trim();
8118
8144
  if (!o || o === "#")
8119
8145
  return { kind: "anchor", anchor: "" };
8120
8146
  if (o.startsWith("#"))
8121
- return { kind: "anchor", anchor: f(o.slice(1)) };
8122
- const t = ge(o);
8147
+ return { kind: "anchor", anchor: w(o.slice(1)) };
8148
+ const t = fe(o);
8123
8149
  if (t)
8124
8150
  return t;
8125
8151
  const n = /^([a-z][a-z\d+.-]*):/i.exec(o)?.[1]?.toLowerCase();
8126
8152
  if (n === "javascript" || n === "vbscript" || n === "file" || n === "data")
8127
8153
  return { kind: "unsafe" };
8128
- if (n && ce.has(n))
8154
+ if (n && pe.has(n))
8129
8155
  return { kind: "unsafe" };
8130
- if (n && T.has(n))
8156
+ if (n && E.has(n))
8131
8157
  return { kind: n === "gdau" ? "audio" : n === "gdvideo" ? "video" : "resource", url: p(o, e) };
8132
8158
  if (o.startsWith("//") || n === "http" || n === "https" || n === "mailto" || n === "tel")
8133
8159
  return { kind: "external", url: o };
@@ -8138,15 +8164,15 @@ function D(i, e) {
8138
8164
  const [a, r] = o.split("#", 2);
8139
8165
  return a ? {
8140
8166
  kind: "lookup",
8141
- word: f(a),
8142
- ...r ? { anchor: f(r) } : {}
8143
- } : { kind: "anchor", anchor: f(r ?? "") };
8167
+ word: w(a),
8168
+ ...r ? { anchor: w(r) } : {}
8169
+ } : { kind: "anchor", anchor: w(r ?? "") };
8144
8170
  }
8145
- const he = ["src", "poster", "data"];
8171
+ const we = ["src", "poster", "data"];
8146
8172
  function x(i) {
8147
8173
  return /^(?:data:|blob:|https?:|#)/i.test(i);
8148
8174
  }
8149
- function fe(i, e, o) {
8175
+ function be(i, e, o) {
8150
8176
  const t = [
8151
8177
  ["data-gd-audio", "audio"],
8152
8178
  ["data-gd-video", "video"],
@@ -8167,7 +8193,7 @@ function fe(i, e, o) {
8167
8193
  const a = i.getAttribute("data-gd-lookup")?.trim();
8168
8194
  if (a && a !== "true" && a !== "1")
8169
8195
  return { kind: "lookup", word: a };
8170
- const r = D(e, o);
8196
+ const r = q(e, o);
8171
8197
  if (r.kind === "lookup")
8172
8198
  return r;
8173
8199
  const l = i.getAttribute("data-gd-word")?.trim();
@@ -8176,7 +8202,7 @@ function fe(i, e, o) {
8176
8202
  if (n === "unsafe")
8177
8203
  return { kind: "unsafe" };
8178
8204
  }
8179
- function we(i, e, o) {
8205
+ function ke(i, e, o) {
8180
8206
  switch (e.kind) {
8181
8207
  case "anchor":
8182
8208
  i.setAttribute(
@@ -8203,7 +8229,7 @@ function we(i, e, o) {
8203
8229
  break;
8204
8230
  }
8205
8231
  }
8206
- function C(i, e) {
8232
+ function T(i, e) {
8207
8233
  return i.replace(
8208
8234
  /url\(\s*(["']?)([^"')]+)\1\s*\)/gi,
8209
8235
  (t, n, a) => {
@@ -8215,13 +8241,13 @@ function C(i, e) {
8215
8241
  (t, n, a) => x(a) ? t : `@import ${n}${p(a, e)}${n}`
8216
8242
  );
8217
8243
  }
8218
- function be(i, e) {
8244
+ function ue(i, e) {
8219
8245
  return i.split(/,\s+(?=[^,]+(?:\s+\d+(?:\.\d+)?[wx])?(?:,|$))/).map((o) => {
8220
8246
  const t = /^(\S+)([\s\S]*)$/.exec(o.trim());
8221
8247
  return !t?.[1] || x(t[1]) ? o.trim() : `${p(t[1], e)}${t[2] ?? ""}`;
8222
8248
  }).join(", ");
8223
8249
  }
8224
- function ke(i) {
8250
+ function xe(i) {
8225
8251
  if (!i.classList.contains("hidden_expand_opt"))
8226
8252
  return;
8227
8253
  const e = i.getAttribute("onclick") ?? "", o = /gdExpandOptPart\(\s*['"]([^'"]+)['"]\s*,\s*['"]([^'"]+)['"]\s*\)/.exec(
@@ -8229,7 +8255,7 @@ function ke(i) {
8229
8255
  );
8230
8256
  o?.[1] && o[2] && (i.setAttribute("data-gd-expander", o[1]), i.setAttribute("data-gd-optional", o[2]));
8231
8257
  }
8232
- function ue(i, e, o) {
8258
+ function ye(i, e, o) {
8233
8259
  if (typeof document > "u")
8234
8260
  throw new Error("Article rendering requires a browser document");
8235
8261
  const t = {
@@ -8242,37 +8268,37 @@ function ue(i, e, o) {
8242
8268
  r.remove();
8243
8269
  }), o === "none" && a.querySelectorAll("script").forEach((r) => r.remove());
8244
8270
  for (const r of a.querySelectorAll("*")) {
8245
- if (ke(r), o === "none")
8271
+ if (xe(r), o === "none")
8246
8272
  for (const d of [...r.attributes])
8247
8273
  (/^on/i.test(d.name) || d.name.toLowerCase() === "srcdoc") && r.removeAttribute(d.name);
8248
8274
  if (r instanceof HTMLAnchorElement || r.tagName === "AREA") {
8249
8275
  const d = r.getAttribute("href");
8250
- d !== null && we(
8276
+ d !== null && ke(
8251
8277
  r,
8252
- fe(r, d, t) ?? D(d, t),
8278
+ be(r, d, t) ?? q(d, t),
8253
8279
  i.dictionaryId
8254
8280
  );
8255
8281
  } else if (r.hasAttribute("href")) {
8256
8282
  const d = r.getAttribute("href") ?? "";
8257
8283
  x(d) || r.setAttribute("href", p(d, t));
8258
8284
  }
8259
- for (const d of he) {
8260
- const w = r.getAttribute(d);
8261
- w === null || x(w) || (/^(?:javascript|vbscript|file):/i.test(w) ? r.removeAttribute(d) : r.setAttribute(d, p(w, t)));
8285
+ for (const d of we) {
8286
+ const b = r.getAttribute(d);
8287
+ b === null || x(b) || (/^(?:javascript|vbscript|file):/i.test(b) ? r.removeAttribute(d) : r.setAttribute(d, p(b, t)));
8262
8288
  }
8263
8289
  const l = r.getAttribute("srcset");
8264
- l && r.setAttribute("srcset", be(l, t));
8290
+ l && r.setAttribute("srcset", ue(l, t));
8265
8291
  const m = r.getAttribute("style");
8266
8292
  m && r.setAttribute(
8267
8293
  "style",
8268
- C(m, t)
8294
+ T(m, t)
8269
8295
  );
8270
8296
  }
8271
8297
  for (const r of a.querySelectorAll("style"))
8272
- r.textContent = C(r.textContent ?? "", t);
8298
+ r.textContent = T(r.textContent ?? "", t);
8273
8299
  return a.innerHTML;
8274
8300
  }
8275
- const xe = {
8301
+ const ve = {
8276
8302
  fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Arial, sans-serif',
8277
8303
  textColor: "#222222",
8278
8304
  mutedTextColor: "#555555",
@@ -8286,8 +8312,8 @@ const xe = {
8286
8312
  selectionTextColor: "#ffffff",
8287
8313
  radius: "8px",
8288
8314
  spacing: "8px"
8289
- }, ye = {
8290
- fontFamily: xe.fontFamily,
8315
+ }, _e = {
8316
+ fontFamily: ve.fontFamily,
8291
8317
  textColor: "#edf1f5",
8292
8318
  mutedTextColor: "#aeb8c3",
8293
8319
  linkColor: "#79bfff",
@@ -8301,7 +8327,7 @@ const xe = {
8301
8327
  radius: "8px",
8302
8328
  spacing: "8px"
8303
8329
  };
8304
- function E(i = "light") {
8330
+ function L(i = "light") {
8305
8331
  return i !== "auto" ? i : globalThis.matchMedia?.("(prefers-color-scheme: dark)").matches ? "dark" : "light";
8306
8332
  }
8307
8333
  function c(i, e) {
@@ -8310,8 +8336,8 @@ function c(i, e) {
8310
8336
  function k(i) {
8311
8337
  return i.replace(/<\/style/gi, "<\\/style");
8312
8338
  }
8313
- function ve(i = {}) {
8314
- const e = E(i.mode), o = i.tokens ?? {}, t = e === "dark" ? { ...ye, ...o } : o, n = [
8339
+ function ze(i = {}) {
8340
+ const e = L(i.mode), o = i.tokens ?? {}, t = e === "dark" ? { ..._e, ...o } : o, n = [
8315
8341
  c("--gd-font-family", t.fontFamily),
8316
8342
  c("--gd-text-color", t.textColor),
8317
8343
  c("--gd-muted-text-color", t.mutedTextColor),
@@ -8345,24 +8371,24 @@ function ve(i = {}) {
8345
8371
  function g(i) {
8346
8372
  return i.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
8347
8373
  }
8348
- function _e(i) {
8374
+ function Ae(i) {
8349
8375
  return i.replace(
8350
8376
  /[^a-zA-Z0-9_-]/g,
8351
8377
  (e) => `_u${e.codePointAt(0)?.toString(16) ?? "0"}_`
8352
8378
  );
8353
8379
  }
8354
- function ze(i) {
8380
+ function Se(i) {
8355
8381
  return (i ?? "unknown").toLowerCase().replace(/[^a-z0-9_-]/g, "-");
8356
8382
  }
8357
- function Ae(i, e) {
8383
+ function Ce(i, e) {
8358
8384
  return i.iconUrl ? p(i.iconUrl, {
8359
8385
  apiBaseUrl: e,
8360
8386
  dictionaryId: i.dictionaryId,
8361
8387
  ...i.resourceBaseUrl ? { resourceBaseUrl: i.resourceBaseUrl } : {}
8362
8388
  }) : u["document.png"];
8363
8389
  }
8364
- function Se(i, e, o) {
8365
- const t = g(i.dictionaryId), n = _e(i.dictionaryId), a = ue(i, e, o), r = ze(i.sourceLanguage), l = g(i.targetLanguage ?? ""), m = g(Ae(i, e));
8390
+ function Te(i, e, o) {
8391
+ const t = g(i.dictionaryId), n = Ae(i.dictionaryId), a = ye(i, e, o), r = Se(i.sourceLanguage), l = g(i.targetLanguage ?? ""), m = g(Ce(i, e));
8366
8392
  return `
8367
8393
  <article class="gdarticle" id="gdfrom-${n}" data-gd-id="${t}">
8368
8394
  <gd-dict-header class="gddictname" id="gddictname-${n}"
@@ -8380,7 +8406,7 @@ function Se(i, e, o) {
8380
8406
  <div style="clear:both;" aria-hidden="true"></div>
8381
8407
  <span class="gdarticleseparator"></span>`;
8382
8408
  }
8383
- function Ce(i) {
8409
+ function Ee(i) {
8384
8410
  return i.length ? `<div class="gdstemmedsuggestion">
8385
8411
  <span class="gdstemmedsuggestion_head">Close words: </span>
8386
8412
  <span class="gdstemmedsuggestion_body">${i.map(
@@ -8388,7 +8414,7 @@ function Ce(i) {
8388
8414
  ).join(", ")}</span>
8389
8415
  </div>` : "";
8390
8416
  }
8391
- function Te(i, e) {
8417
+ function Ie(i, e) {
8392
8418
  return `(function(){
8393
8419
  "use strict";
8394
8420
  const config=${JSON.stringify({
@@ -8404,6 +8430,32 @@ function Te(i, e) {
8404
8430
  type,
8405
8431
  detail
8406
8432
  },"*");
8433
+ const reportResourceError=(failure)=>{
8434
+ if(!failure||typeof failure.url!=="string"||!failure.url)return;
8435
+ if(failure.resourceType!=="stylesheet"&&failure.resourceType!=="script")return;
8436
+ post("resource-error",{
8437
+ resourceType:failure.resourceType,
8438
+ url:failure.url,
8439
+ dictionaryId:typeof failure.dictionaryId==="string"&&failure.dictionaryId
8440
+ ?failure.dictionaryId
8441
+ :undefined
8442
+ });
8443
+ };
8444
+ globalThis.__GOLDENDICT_WEB_REPORT_RESOURCE_ERROR__=reportResourceError;
8445
+ const pendingResourceErrors=globalThis.__GOLDENDICT_WEB_RESOURCE_ERRORS__;
8446
+ if(Array.isArray(pendingResourceErrors)){
8447
+ pendingResourceErrors.splice(0).forEach(reportResourceError);
8448
+ }
8449
+ const verifyStylesheets=()=>{
8450
+ document.querySelectorAll('link[rel~="stylesheet"][href]').forEach((link)=>{
8451
+ if(!(link instanceof HTMLLinkElement)||link.disabled||link.sheet!==null)return;
8452
+ reportResourceError({
8453
+ resourceType:"stylesheet",
8454
+ url:link.href,
8455
+ dictionaryId:link.closest(".gdarticle")?.getAttribute("data-gd-id")||undefined
8456
+ });
8457
+ });
8458
+ };
8407
8459
  const articleOf=(target)=>target instanceof Element?target.closest(".gdarticle"):null;
8408
8460
  const articleId=(article)=>article?.getAttribute("data-gd-id")||"";
8409
8461
  const syncDictionaryTheme=()=>{
@@ -8545,10 +8597,10 @@ function Te(i, e) {
8545
8597
  const resizeObserver=new ResizeObserver(requestSize);
8546
8598
  resizeObserver.observe(document.body);
8547
8599
  addEventListener("resize",requestSize,{passive:true});
8548
- addEventListener("load",()=>{requestSize();post("ready",{});});
8600
+ addEventListener("load",()=>{verifyStylesheets();requestSize();post("ready",{});});
8549
8601
  })();`;
8550
8602
  }
8551
- function Ie(i, e) {
8603
+ function De(i, e) {
8552
8604
  const o = i === "none" ? `'nonce-${e}'` : "'unsafe-inline' 'unsafe-eval' data: blob: http: https:", t = i === "none" ? "'none'" : "http: https:";
8553
8605
  return [
8554
8606
  "default-src 'none'",
@@ -8564,39 +8616,66 @@ function Ie(i, e) {
8564
8616
  "base-uri 'none'"
8565
8617
  ].join("; ");
8566
8618
  }
8567
- function De() {
8568
- return 'globalThis.__DICT__={name:"GoldenDict",version:"web"};';
8619
+ function qe() {
8620
+ return `(function(){
8621
+ globalThis.__DICT__={name:"GoldenDict",version:"web"};
8622
+ const pending=[];
8623
+ globalThis.__GOLDENDICT_WEB_RESOURCE_ERRORS__=pending;
8624
+ addEventListener("error",(event)=>{
8625
+ const target=event.target;
8626
+ let resourceType="";
8627
+ let url="";
8628
+ if(target instanceof HTMLLinkElement&&target.relList.contains("stylesheet")){
8629
+ resourceType="stylesheet";
8630
+ url=target.href;
8631
+ }else if(target instanceof HTMLScriptElement&&target.src){
8632
+ resourceType="script";
8633
+ url=target.src;
8634
+ }
8635
+ if(!resourceType||!url)return;
8636
+ const article=target.closest(".gdarticle");
8637
+ const failure={
8638
+ resourceType,
8639
+ url,
8640
+ dictionaryId:article?.getAttribute("data-gd-id")||undefined
8641
+ };
8642
+ const report=globalThis.__GOLDENDICT_WEB_REPORT_RESOURCE_ERROR__;
8643
+ if(typeof report==="function")report(failure);
8644
+ else pending.push(failure);
8645
+ },true);
8646
+ })();`;
8569
8647
  }
8570
- function Ee(i, e) {
8571
- const o = e.theme ?? {}, t = E(o.mode), n = e.layoutMode ?? "responsive", a = e.instanceId.replace(/[^a-zA-Z0-9_-]/g, ""), r = i.articles.map(
8572
- (d) => Se(d, e.apiBaseUrl, e.scriptPolicy)
8648
+ function Le(i, e) {
8649
+ const o = e.theme ?? {}, t = L(o.mode), n = e.layoutMode ?? "responsive", a = e.instanceId.replace(/[^a-zA-Z0-9_-]/g, ""), r = i.articles.map(
8650
+ (d) => Te(d, e.apiBaseUrl, e.scriptPolicy)
8573
8651
  ).join(""), l = r ? `${r}<div class="empty-space" aria-hidden="true"></div>` : `<div class="gdnotfound"><p>No translation for <b>${g(i.word)}</b> was found.</p></div>`, m = o.brandName ? `${i.word} — ${o.brandName}` : i.word;
8574
8652
  return `<!doctype html>
8575
8653
  <html data-gd-theme="${t}" data-gd-layout="${n}" data-darkreader-scheme="${t}"><head>
8576
8654
  <meta charset="utf-8">
8577
8655
  <meta name="viewport" content="width=device-width,initial-scale=1">
8578
- <meta http-equiv="Content-Security-Policy" content="${g(Ie(e.scriptPolicy, a))}">
8656
+ <meta http-equiv="Content-Security-Policy" content="${g(De(e.scriptPolicy, a))}">
8579
8657
  <title>${g(m)}</title>
8580
- <script nonce="${a}" data-gd-runtime="compatibility">${De()}<\/script>
8581
- <style>${k(re)}</style>
8582
- <style>${k(de(o.preset))}</style>
8583
- ${n === "responsive" ? `<style data-gd-style="responsive">${k(le)}</style>` : ""}
8584
- <style>${ve(o)}</style>
8585
- <style media="print">${k(ae)}</style>
8658
+ <script nonce="${a}" data-gd-runtime="compatibility">${qe()}<\/script>
8659
+ <style>${k(de)}</style>
8660
+ <style>${k(se(o.preset))}</style>
8661
+ ${n === "responsive" ? `<style data-gd-style="responsive">${k(ce)}</style>` : ""}
8662
+ <style>${ze(o)}</style>
8663
+ <style media="print">${k(le)}</style>
8586
8664
  </head><body>
8587
8665
  ${l}
8588
- ${Ce(i.suggestions)}
8589
- <script nonce="${a}">${Te(e.instanceId, t).replace(/<\/script/gi, "<\\/script")}<\/script>
8666
+ ${Ee(i.suggestions)}
8667
+ <script nonce="${a}">${Ie(e.instanceId, t).replace(/<\/script/gi, "<\\/script")}<\/script>
8590
8668
  </body></html>`;
8591
8669
  }
8592
- const b = {
8670
+ const f = {
8593
8671
  lookup: "goldendict-lookup",
8594
8672
  activeArticleChange: "goldendict-active-article-change",
8595
8673
  articleToggle: "goldendict-article-toggle",
8596
8674
  mediaRequest: "goldendict-media-request",
8597
8675
  externalLink: "goldendict-external-link",
8676
+ resourceError: "goldendict-resource-error",
8598
8677
  stateChange: "goldendict-state-change"
8599
- }, qe = `
8678
+ }, Me = `
8600
8679
  :host{display:block;box-sizing:border-box;width:100%;min-width:0;max-width:100%;color:#222;font-family:system-ui,sans-serif;container:goldendict-view / inline-size}
8601
8680
  .shell{position:relative;box-sizing:border-box;width:100%;min-width:0;max-width:100%;min-height:8rem;border-radius:var(--gd-host-radius,8px);overflow:hidden;background:var(--gd-host-background,#fff)}
8602
8681
  .brand{display:flex;align-items:center;gap:.65rem;min-width:0;padding:.65rem .9rem;border-bottom:1px solid var(--gd-host-border,#e3e3e3);background:var(--gd-host-surface,#f7f9fb);font-weight:650}
@@ -8604,7 +8683,7 @@ const b = {
8604
8683
  .brand img{display:block;flex:0 0 auto;width:1.75rem;height:1.75rem;object-fit:contain}
8605
8684
  .brand img[hidden]{display:none}
8606
8685
  .brand span{min-width:0;overflow-wrap:anywhere}
8607
- .status{display:grid;place-items:center;min-height:8rem;padding:1.25rem;text-align:center;color:var(--gd-host-muted,#59636e)}
8686
+ .status{display:grid;place-items:center;min-height:8rem;padding:1.25rem;overflow-wrap:anywhere;text-align:center;color:var(--gd-host-muted,#59636e)}
8608
8687
  .status[hidden]{display:none}
8609
8688
  .status[data-state="error"]{color:var(--gd-host-error,#a21d2d)}
8610
8689
  .spinner{width:1.25rem;height:1.25rem;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:spin .75s linear infinite;margin:0 auto .7rem}
@@ -8614,13 +8693,13 @@ const b = {
8614
8693
  @container goldendict-view (max-width:30rem){.brand{gap:.5rem;padding:.55rem .65rem}.status{padding:1rem .75rem}}
8615
8694
  @media (prefers-reduced-motion:reduce){.spinner{animation:none}}
8616
8695
  `;
8617
- function Le() {
8696
+ function Be() {
8618
8697
  return globalThis.crypto?.randomUUID?.() ?? `gd-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
8619
8698
  }
8620
- function Be(i) {
8699
+ function $e(i) {
8621
8700
  return (i instanceof DOMException || i instanceof Error) && i.name === "AbortError";
8622
8701
  }
8623
- class _ extends HTMLElement {
8702
+ class z extends HTMLElement {
8624
8703
  static observedAttributes = [
8625
8704
  "api-base",
8626
8705
  "word",
@@ -8629,7 +8708,7 @@ class _ extends HTMLElement {
8629
8708
  "script-policy",
8630
8709
  "layout-mode"
8631
8710
  ];
8632
- instanceId = Le();
8711
+ instanceId = Be();
8633
8712
  frame;
8634
8713
  statusElement;
8635
8714
  brandElement;
@@ -8643,12 +8722,14 @@ class _ extends HTMLElement {
8643
8722
  responseValue;
8644
8723
  themeValue = {};
8645
8724
  stateValue = "idle";
8725
+ errorValue;
8726
+ resourceErrorsValue = [];
8646
8727
  dictionaryIdsValue = [];
8647
8728
  pendingAnchor;
8648
8729
  constructor() {
8649
8730
  super();
8650
8731
  const e = this.attachShadow({ mode: "open" });
8651
- e.innerHTML = `<style>${qe}</style>
8732
+ e.innerHTML = `<style>${Me}</style>
8652
8733
  <section class="shell" part="container">
8653
8734
  <div class="brand" part="brand" hidden>
8654
8735
  <img alt="" hidden><span></span>
@@ -8717,6 +8798,14 @@ class _ extends HTMLElement {
8717
8798
  get response() {
8718
8799
  return this.responseValue;
8719
8800
  }
8801
+ /** The current request or article-resource error, if `state` is `"error"`. */
8802
+ get error() {
8803
+ return this.errorValue;
8804
+ }
8805
+ /** Dictionary-authored stylesheets or scripts that failed in this render. */
8806
+ get resourceErrors() {
8807
+ return this.resourceErrorsValue.map((e) => ({ ...e }));
8808
+ }
8720
8809
  configureClient(e) {
8721
8810
  this.clientValue = new v(e);
8722
8811
  }
@@ -8738,7 +8827,7 @@ class _ extends HTMLElement {
8738
8827
  return;
8739
8828
  this.setLookupResponse(r);
8740
8829
  } catch (r) {
8741
- if (n !== this.requestSequence || Be(r))
8830
+ if (n !== this.requestSequence || $e(r))
8742
8831
  return;
8743
8832
  const l = r instanceof Error ? r : new Error(String(r));
8744
8833
  this.responseValue = void 0, this.resetFrame(), this.setState("error", { word: t, error: l });
@@ -8759,11 +8848,13 @@ class _ extends HTMLElement {
8759
8848
  this.postCommand({ type: "scroll-article", dictionaryId: e });
8760
8849
  }
8761
8850
  renderResponse(e) {
8762
- const o = ++this.renderSequence, t = `${this.instanceId}-${o}`;
8851
+ const o = ++this.renderSequence;
8852
+ this.resourceErrorsValue = [], this.errorValue = void 0;
8853
+ const t = `${this.instanceId}-${o}`;
8763
8854
  this.activeBridgeInstanceId = t;
8764
8855
  const n = this.replaceFrame(!1);
8765
8856
  n.title = e.word ? `Dictionary results for ${e.word}` : "Dictionary article";
8766
- const a = Ee(e, {
8857
+ const a = Le(e, {
8767
8858
  apiBaseUrl: this.clientValue.baseUrl,
8768
8859
  instanceId: t,
8769
8860
  scriptPolicy: this.scriptPolicy,
@@ -8775,7 +8866,7 @@ class _ extends HTMLElement {
8775
8866
  });
8776
8867
  }
8777
8868
  resetFrame() {
8778
- this.activeBridgeInstanceId = void 0, this.replaceFrame(!0);
8869
+ this.activeBridgeInstanceId = void 0, this.resourceErrorsValue = [], this.replaceFrame(!0);
8779
8870
  }
8780
8871
  replaceFrame(e) {
8781
8872
  const o = this.frame, t = this.ownerDocument.createElement("iframe");
@@ -8784,7 +8875,10 @@ class _ extends HTMLElement {
8784
8875
  }), o.replaceWith(t), this.frame = t, t.offsetWidth, t;
8785
8876
  }
8786
8877
  handleFrameLoaded() {
8787
- this.responseValue && (this.setState(
8878
+ this.responseValue && (this.resourceErrorsValue.length ? this.setState("error", {
8879
+ word: this.responseValue.word,
8880
+ error: this.errorValue ?? this.resourceError(this.resourceErrorsValue[0])
8881
+ }) : this.setState(
8788
8882
  this.responseValue.articles.length ? "ready" : "not-found",
8789
8883
  { word: this.responseValue.word }
8790
8884
  ), this.pendingAnchor && (this.postCommand({ type: "scroll-anchor", anchor: this.pendingAnchor }), this.pendingAnchor = void 0));
@@ -8809,12 +8903,12 @@ class _ extends HTMLElement {
8809
8903
  this.handleLookupMessage(t);
8810
8904
  break;
8811
8905
  case "active-article":
8812
- this.emit(b.activeArticleChange, {
8906
+ this.emit(f.activeArticleChange, {
8813
8907
  dictionaryId: String(t.dictionaryId ?? "")
8814
8908
  });
8815
8909
  break;
8816
8910
  case "article-toggle":
8817
- this.emit(b.articleToggle, {
8911
+ this.emit(f.articleToggle, {
8818
8912
  dictionaryId: String(t.dictionaryId ?? ""),
8819
8913
  collapsed: !!t.collapsed
8820
8914
  });
@@ -8825,8 +8919,34 @@ class _ extends HTMLElement {
8825
8919
  case "external-link":
8826
8920
  this.handleExternalLink(String(t.url ?? ""));
8827
8921
  break;
8922
+ case "resource-error":
8923
+ this.handleResourceErrorMessage(t);
8924
+ break;
8828
8925
  }
8829
8926
  };
8927
+ handleResourceErrorMessage(e) {
8928
+ const o = e.resourceType === "stylesheet" || e.resourceType === "script" ? e.resourceType : void 0, t = String(e.url ?? "").trim();
8929
+ if (!o || !t)
8930
+ return;
8931
+ const n = {
8932
+ resourceType: o,
8933
+ url: t,
8934
+ ...e.dictionaryId ? { dictionaryId: String(e.dictionaryId) } : {}
8935
+ };
8936
+ this.resourceErrorsValue.some(
8937
+ (a) => a.resourceType === n.resourceType && a.url === n.url && a.dictionaryId === n.dictionaryId
8938
+ ) || (this.resourceErrorsValue.push(n), this.emit(
8939
+ f.resourceError,
8940
+ { ...n }
8941
+ ), this.setState("error", {
8942
+ word: this.responseValue?.word,
8943
+ error: this.resourceError(n)
8944
+ }));
8945
+ }
8946
+ resourceError(e) {
8947
+ const o = e.resourceType === "stylesheet" ? "stylesheet" : "script";
8948
+ return new Error(`Dictionary ${o} failed to load: ${e.url}`);
8949
+ }
8830
8950
  handleLookupMessage(e) {
8831
8951
  const o = String(e.word ?? "").trim();
8832
8952
  if (!o)
@@ -8836,7 +8956,7 @@ class _ extends HTMLElement {
8836
8956
  ...e.anchor ? { anchor: String(e.anchor) } : {},
8837
8957
  ...t.length ? { dictionaryIds: [...t] } : {}
8838
8958
  };
8839
- this.emit(b.lookup, n, !0).defaultPrevented || (this.pendingAnchor = n.anchor, this.lookup(o, t));
8959
+ this.emit(f.lookup, n, !0).defaultPrevented || (this.pendingAnchor = n.anchor, this.lookup(o, t));
8840
8960
  }
8841
8961
  handleMediaMessage(e) {
8842
8962
  const o = e.kind === "video" || e.kind === "resource" ? e.kind : "audio", t = {
@@ -8844,14 +8964,14 @@ class _ extends HTMLElement {
8844
8964
  url: String(e.url ?? ""),
8845
8965
  ...e.dictionaryId ? { dictionaryId: String(e.dictionaryId) } : {}
8846
8966
  };
8847
- !t.url || this.emit(b.mediaRequest, t, !0).defaultPrevented || (o === "audio" ? new Audio(t.url).play().catch(() => {
8967
+ !t.url || this.emit(f.mediaRequest, t, !0).defaultPrevented || (o === "audio" ? new Audio(t.url).play().catch(() => {
8848
8968
  }) : this.openExternal(t.url));
8849
8969
  }
8850
8970
  handleExternalLink(e) {
8851
8971
  if (!e)
8852
8972
  return;
8853
8973
  this.emit(
8854
- b.externalLink,
8974
+ f.externalLink,
8855
8975
  { url: e },
8856
8976
  !0
8857
8977
  ).defaultPrevented || this.openExternal(e);
@@ -8866,15 +8986,15 @@ class _ extends HTMLElement {
8866
8986
  }
8867
8987
  setState(e, o = {}) {
8868
8988
  const t = e !== this.stateValue;
8869
- if (this.stateValue = e, this.statusElement.dataset.state = e, this.statusElement.hidden = e === "ready" || e === "not-found", e === "loading") {
8989
+ if (this.stateValue = e, this.errorValue = e === "error" ? o.error ?? new Error("The dictionary request failed.") : void 0, this.statusElement.dataset.state = e, this.statusElement.hidden = e === "ready" || e === "not-found", e === "loading") {
8870
8990
  this.frame.hidden = !0, this.statusElement.innerHTML = '<div><div class="spinner" aria-hidden="true"></div>Looking up <strong></strong>…</div>';
8871
8991
  const n = this.statusElement.querySelector("strong");
8872
8992
  n && (n.textContent = o.word ?? "");
8873
- } else e === "error" ? this.statusElement.textContent = o.error?.message ?? "The dictionary request failed." : e === "idle" ? this.statusElement.textContent = "Enter a word to search the loaded dictionaries." : this.statusElement.textContent = e === "not-found" ? `No translation found for ${o.word ?? ""}.` : "";
8874
- t && this.emit(b.stateChange, {
8993
+ } else e === "error" ? this.statusElement.textContent = this.errorValue?.message ?? "The dictionary request failed." : e === "idle" ? this.statusElement.textContent = "Enter a word to search the loaded dictionaries." : this.statusElement.textContent = e === "not-found" ? `No translation found for ${o.word ?? ""}.` : "";
8994
+ t && this.emit(f.stateChange, {
8875
8995
  state: e,
8876
8996
  ...o.word ? { word: o.word } : {},
8877
- ...o.error ? { error: o.error } : {}
8997
+ ...this.errorValue ? { error: this.errorValue } : {}
8878
8998
  });
8879
8999
  }
8880
9000
  postCommand(e) {
@@ -8897,26 +9017,26 @@ class _ extends HTMLElement {
8897
9017
  return this.dispatchEvent(n), n;
8898
9018
  }
8899
9019
  }
8900
- function Me(i = "goldendict-view") {
9020
+ function Re(i = "goldendict-view") {
8901
9021
  if (!globalThis.customElements)
8902
- return _;
9022
+ return z;
8903
9023
  const e = globalThis.customElements.get(i);
8904
- return e || (globalThis.customElements.define(i, _), _);
9024
+ return e || (globalThis.customElements.define(i, z), z);
8905
9025
  }
8906
- Me();
9026
+ Re();
8907
9027
  export {
8908
- ye as DARK_THEME_TOKENS,
8909
- q as DictionaryApiError,
9028
+ _e as DARK_THEME_TOKENS,
9029
+ M as DictionaryApiError,
8910
9030
  v as DictionaryClient,
8911
- b as GOLDENDICT_EVENTS,
8912
- se as GOLDENDICT_SCHEME_SUPPORT,
8913
- _ as GoldenDictView,
8914
- xe as LIGHT_THEME_TOKENS,
8915
- D as classifyArticleLink,
8916
- Me as defineGoldendictView,
9031
+ f as GOLDENDICT_EVENTS,
9032
+ me as GOLDENDICT_SCHEME_SUPPORT,
9033
+ z as GoldenDictView,
9034
+ ve as LIGHT_THEME_TOKENS,
9035
+ q as classifyArticleLink,
9036
+ Re as defineGoldendictView,
8917
9037
  k as escapeStyleText,
8918
9038
  p as resolveResourceUrl,
8919
- E as resolveThemeMode,
8920
- ve as themeToCss
9039
+ L as resolveThemeMode,
9040
+ ze as themeToCss
8921
9041
  };
8922
9042
  //# sourceMappingURL=index.js.map