@prose-reader/metadata-fetcher 1.339.0 → 1.341.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/index.js CHANGED
@@ -1,37 +1,38 @@
1
1
  import { normalizeIsbn as e } from "@prose-reader/archive-reader";
2
2
  import { Report as t } from "@prose-reader/shared";
3
+ import { XmlDocument as n } from "xmldoc";
3
4
  //#region src/utils/metadataAuthors.ts
4
- var n = (e) => {
5
+ var r = (e) => {
5
6
  let t = e.contributors ?? [], n = t.filter((e) => e.roles.includes("author")), r = (n.length > 0 ? n : t).map((e) => e.name.trim()).filter((e) => e.length > 0);
6
7
  return [...new Set(r)];
7
- }, r = /^\d{13}$/, i = /^\d{9}[\dX]$/, a = (t) => {
8
+ }, i = /^\d{13}$/, a = /^\d{9}[\dX]$/, o = (t) => {
8
9
  let n = e(t);
9
10
  if (n === void 0) return;
10
- if (r.test(n)) return n;
11
- if (!i.test(n)) return;
12
- let a = `978${n.slice(0, 9)}`, o = 0;
13
- for (let e = 0; e < a.length; e++) {
14
- let t = a.charCodeAt(e) - 48;
11
+ if (i.test(n)) return n;
12
+ if (!a.test(n)) return;
13
+ let r = `978${n.slice(0, 9)}`, o = 0;
14
+ for (let e = 0; e < r.length; e++) {
15
+ let t = r.charCodeAt(e) - 48;
15
16
  o += e % 2 == 0 ? t : t * 3;
16
17
  }
17
- return `${a}${(10 - o % 10) % 10}`;
18
- }, o = /[\u0300-\u036f]/g, s = /[^\p{L}\p{N}]+/gu, c = (e) => e.normalize("NFD").replace(o, "").toLowerCase().replace(s, " ").trim(), l = (e) => {
18
+ return `${r}${(10 - o % 10) % 10}`;
19
+ }, s = /[\u0300-\u036f]/g, c = /[^\p{L}\p{N}]+/gu, l = (e) => e.normalize("NFD").replace(s, "").toLowerCase().replace(c, " ").trim(), u = (e) => {
19
20
  let t = /* @__PURE__ */ new Map();
20
21
  for (let n = 0; n < e.length - 1; n++) {
21
22
  let r = e.slice(n, n + 2);
22
23
  t.set(r, (t.get(r) ?? 0) + 1);
23
24
  }
24
25
  return t;
25
- }, u = (e, t) => {
26
- let n = c(e).replaceAll(" ", ""), r = c(t).replaceAll(" ", "");
26
+ }, d = (e, t) => {
27
+ let n = l(e).replaceAll(" ", ""), r = l(t).replaceAll(" ", "");
27
28
  if (n.length === 0 || r.length === 0) return 0;
28
29
  if (n === r) return 1;
29
30
  if (n.length < 2 || r.length < 2) return 0;
30
- let i = l(n), a = 0;
31
- for (let [e, t] of l(r)) a += Math.min(t, i.get(e) ?? 0);
31
+ let i = u(n), a = 0;
32
+ for (let [e, t] of u(r)) a += Math.min(t, i.get(e) ?? 0);
32
33
  return 2 * a / (n.length - 1 + (r.length - 1));
33
- }, d = /\s*[:;]\s*|\s+[-–—]\s+/, f = (e) => {
34
- let [t = "", ...n] = e.split(d), r = t.trim(), i = n.join(" ").trim();
34
+ }, f = /\s*[:;]\s*|\s+[-–—]\s+/, p = (e) => {
35
+ let [t = "", ...n] = e.split(f), r = t.trim(), i = n.join(" ").trim();
35
36
  return r.length === 0 ? {
36
37
  main: e,
37
38
  hasSubtitle: !1
@@ -39,11 +40,11 @@ var n = (e) => {
39
40
  main: r,
40
41
  hasSubtitle: i.length > 0
41
42
  };
42
- }, p = .9, m = [
43
+ }, m = .9, h = [
43
44
  "volume",
44
45
  "part",
45
46
  "book"
46
- ], h = /\b(volumes?|vols?|parts?|books?)\s+([\p{L}\p{N}]+)\b/gu, g = {
47
+ ], g = /\b(volumes?|vols?|parts?|books?)\s+([\p{L}\p{N}]+)\b/gu, _ = {
47
48
  one: 1,
48
49
  first: 1,
49
50
  two: 2,
@@ -68,7 +69,7 @@ var n = (e) => {
68
69
  eleventh: 11,
69
70
  twelve: 12,
70
71
  twelfth: 12
71
- }, _ = {
72
+ }, v = {
72
73
  i: 1,
73
74
  v: 5,
74
75
  x: 10,
@@ -76,78 +77,91 @@ var n = (e) => {
76
77
  c: 100,
77
78
  d: 500,
78
79
  m: 1e3
79
- }, v = (e) => {
80
+ }, y = (e) => {
80
81
  if (!/^m{0,3}(cm|cd|d?c{0,3})(xc|xl|l?x{0,3})(ix|iv|v?i{0,3})$/i.test(e)) return;
81
82
  let t = 0, n = 0;
82
83
  for (let r of [...e.toLowerCase()].reverse()) {
83
- let e = _[r];
84
+ let e = v[r];
84
85
  if (e === void 0) return;
85
86
  e < n ? t -= e : (t += e, n = e);
86
87
  }
87
88
  return t > 0 ? t : void 0;
88
- }, y = (e) => /^\d+$/.test(e) ? Number.parseInt(e, 10) : g[e] ?? v(e), b = (e) => {
89
+ }, b = (e) => /^\d+$/.test(e) ? Number.parseInt(e, 10) : _[e] ?? y(e), x = (e) => {
89
90
  if (e.startsWith("vol")) return "volume";
90
91
  if (e.startsWith("part")) return "part";
91
92
  if (e.startsWith("book")) return "book";
92
- }, x = (e) => {
93
+ }, S = (e) => {
93
94
  let t = /* @__PURE__ */ new Map();
94
- for (let n of c(e).matchAll(h)) {
95
- let e = n[1] === void 0 ? void 0 : b(n[1]), r = n[2] === void 0 ? void 0 : y(n[2]);
95
+ for (let n of l(e).matchAll(g)) {
96
+ let e = n[1] === void 0 ? void 0 : x(n[1]), r = n[2] === void 0 ? void 0 : b(n[2]);
96
97
  if (e === void 0 || r === void 0) continue;
97
98
  let i = t.get(e) ?? /* @__PURE__ */ new Set();
98
99
  i.add(r), t.set(e, i);
99
100
  }
100
101
  return t;
101
- }, S = (e, t) => {
102
- let n = x(e), r = x(t);
103
- for (let e of m) {
102
+ }, C = (e, t) => {
103
+ let n = S(e), r = S(t);
104
+ for (let e of h) {
104
105
  let t = n.get(e), i = r.get(e);
105
106
  if (!(t === void 0 || i === void 0) && [...t].every((e) => !i.has(e))) return !0;
106
107
  }
107
108
  return !1;
108
- }, C = (e, t) => {
109
- if (S(e, t)) return 0;
110
- let n = u(e, t), r = f(e), i = f(t);
111
- return r.hasSubtitle === i.hasSubtitle ? n : Math.max(n, u(r.main, i.main) * p);
112
- }, w = (e) => c(e).split(" ").filter((e) => e.length > 0).sort().join(" "), T = (e, t) => u(w(e), w(t)), E = {
109
+ }, w = (e, t) => {
110
+ if (C(e, t)) return 0;
111
+ let n = d(e, t), r = p(e), i = p(t);
112
+ return r.hasSubtitle === i.hasSubtitle ? n : Math.max(n, d(r.main, i.main) * m);
113
+ }, T = (e) => l(e).split(" ").filter((e) => e.length > 0).sort().join(" "), E = (e, t) => d(T(e), T(t)), D = {
113
114
  isbn: 1,
114
115
  gtin: 1,
115
116
  identifiers: .6,
116
117
  title: .8,
117
118
  contributors: .5,
118
119
  series: .3,
119
- published: .2,
120
- publisher: .15,
120
+ "publication.original.date": .2,
121
+ "publication.original.publisher": .15,
122
+ "publication.edition.date": .2,
123
+ "publication.edition.publisher": .15,
121
124
  languages: .15,
122
125
  numberOfPages: .15
123
- }, D = /* @__PURE__ */ new Set(["isbn", "gtin"]), O = (e) => {
126
+ }, ee = /* @__PURE__ */ new Set(["isbn", "gtin"]), O = (e) => {
124
127
  let t = e?.trim();
125
128
  return t !== void 0 && t.length > 0 ? t : void 0;
126
- }, k = (e) => e.value.trim().toLowerCase(), A = (e) => e.scheme === void 0 ? e.value : `${e.scheme}:${e.value}`, j = (e, t) => k(e) === k(t) ? e.scheme === void 0 || t.scheme === void 0 || e.scheme.trim().toLowerCase() === t.scheme.trim().toLowerCase() : !1, M = (e) => e.trim().toLowerCase().split("-")[0] ?? "", N = (e, t) => {
129
+ }, k = (e, t) => {
130
+ let n = O(e.value)?.toLowerCase();
131
+ return n !== void 0 && n === O(t.value)?.toLowerCase();
132
+ }, A = (e) => O(e.scheme)?.toLowerCase(), te = (e) => e.scheme === void 0 ? e.value : `${e.scheme}:${e.value}`, ne = (e, t) => {
133
+ if (!k(e, t)) return !1;
134
+ let n = A(e), r = A(t);
135
+ return n === void 0 || r === void 0 || n === r;
136
+ }, re = (e, t) => {
137
+ if (!k(e, t)) return !1;
138
+ let n = A(e), r = A(t);
139
+ return n !== void 0 && n === r;
140
+ }, ie = (e) => e.trim().toLowerCase().split("-")[0] ?? "", ae = (e, t) => {
127
141
  let n = Math.abs(e - t);
128
142
  return n === 0 ? 1 : n === 1 ? .6 : n <= 3 ? .3 : 0;
129
- }, ee = (e, t) => {
143
+ }, oe = (e, t) => {
130
144
  let n = Math.max(e, t);
131
145
  return n <= 0 ? 0 : Math.max(0, 1 - Math.abs(e - t) / n * 2);
132
- }, P = (e, t, n) => e.reduce((e, r) => t.reduce((e, t) => Math.max(e, n(r, t)), e), 0), F = (e, t) => {
133
- let r = [], i = (e, t) => {
134
- t !== void 0 && r.push({
146
+ }, se = (e, t, n) => e.reduce((e, r) => t.reduce((e, t) => Math.max(e, n(r, t)), e), 0), ce = (e, t) => {
147
+ let n = [], i = (e, t) => {
148
+ t !== void 0 && n.push({
135
149
  field: e,
136
- weight: E[e],
150
+ weight: D[e],
137
151
  score: Math.min(1, Math.max(0, t.score)),
138
152
  query: t.query,
139
153
  candidate: t.candidate
140
154
  });
141
- }, o = (e, t, n, r = u) => {
155
+ }, a = (e, t, n, r = d) => {
142
156
  let a = O(t), o = O(n);
143
157
  a === void 0 || o === void 0 || i(e, {
144
158
  score: r(a, o),
145
159
  query: a,
146
160
  candidate: o
147
161
  });
148
- }, s = O(e.isbn), c = O(t.isbn), l = s === void 0 ? void 0 : a(s), d = c === void 0 ? void 0 : a(c);
149
- s !== void 0 && c !== void 0 && l !== void 0 && d !== void 0 && i("isbn", {
150
- score: +(l === d),
162
+ }, s = O(e.isbn), c = O(t.isbn), l = s === void 0 ? void 0 : o(s), u = c === void 0 ? void 0 : o(c);
163
+ s !== void 0 && c !== void 0 && l !== void 0 && u !== void 0 && i("isbn", {
164
+ score: +(l === u),
151
165
  query: s,
152
166
  candidate: c
153
167
  });
@@ -157,117 +171,70 @@ var n = (e) => {
157
171
  query: f,
158
172
  candidate: p
159
173
  });
160
- let m = e.identifiers ?? [], h = t.identifiers ?? [];
174
+ let m = e.identifiers ?? [], h = t.identifiers ?? [], g = m.some((e) => h.some((t) => re(e, t)));
161
175
  m.length > 0 && h.length > 0 && i("identifiers", {
162
- score: +!!m.some((e) => h.some((t) => j(e, t))),
163
- query: m.map(A).join(", "),
164
- candidate: h.map(A).join(", ")
165
- }), o("title", e.title, t.title, C), o("publisher", e.publisher, t.publisher), o("series", e.belongsTo?.series?.[0]?.name, t.belongsTo?.series?.[0]?.name);
166
- let g = n(t), _ = n(e);
167
- _.length > 0 && g.length > 0 && i("contributors", {
168
- score: P(_, g, T),
169
- query: _.join(", "),
170
- candidate: g.join(", ")
171
- });
172
- let v = e.published?.year, y = t.published?.year;
173
- v !== void 0 && y !== void 0 && i("published", {
174
- score: N(v, y),
175
- query: String(v),
176
- candidate: String(y)
176
+ score: +!!m.some((e) => h.some((t) => ne(e, t))),
177
+ query: m.map(te).join(", "),
178
+ candidate: h.map(te).join(", ")
179
+ }), a("title", e.title, t.title, w), a("publication.original.publisher", e.publication?.original?.publisher, t.publication?.original?.publisher), a("publication.edition.publisher", e.publication?.edition?.publisher, t.publication?.edition?.publisher), a("series", e.belongsTo?.series?.[0]?.name, t.belongsTo?.series?.[0]?.name);
180
+ let _ = r(t), v = r(e);
181
+ v.length > 0 && _.length > 0 && i("contributors", {
182
+ score: se(v, _, E),
183
+ query: v.join(", "),
184
+ candidate: _.join(", ")
177
185
  });
186
+ let y = (e, t, n) => {
187
+ t === void 0 || n === void 0 || i(e, {
188
+ score: ae(t, n),
189
+ query: String(t),
190
+ candidate: String(n)
191
+ });
192
+ };
193
+ y("publication.original.date", e.publication?.original?.date?.year, t.publication?.original?.date?.year), y("publication.edition.date", e.publication?.edition?.date?.year, t.publication?.edition?.date?.year);
178
194
  let b = e.languages ?? [], x = t.languages ?? [];
179
195
  if (b.length > 0 && x.length > 0) {
180
- let e = new Set(x.map(M));
196
+ let e = new Set(x.map(ie));
181
197
  i("languages", {
182
- score: +!!b.some((t) => e.has(M(t))),
198
+ score: +!!b.some((t) => e.has(ie(t))),
183
199
  query: b.join(", "),
184
200
  candidate: x.join(", ")
185
201
  });
186
202
  }
187
203
  e.numberOfPages !== void 0 && t.numberOfPages !== void 0 && i("numberOfPages", {
188
- score: ee(e.numberOfPages, t.numberOfPages),
204
+ score: oe(e.numberOfPages, t.numberOfPages),
189
205
  query: String(e.numberOfPages),
190
206
  candidate: String(t.numberOfPages)
191
207
  });
192
- let S = r.filter((e) => D.has(e.field));
208
+ let S = n.filter((e) => ee.has(e.field));
193
209
  if (S.some((e) => e.score === 0)) return {
194
210
  score: 0,
195
- signals: r
211
+ signals: n
196
212
  };
197
- if (S.some((e) => e.score === 1)) return {
213
+ if (g || S.some((e) => e.score === 1)) return {
198
214
  score: 1,
199
- signals: r
215
+ signals: n
200
216
  };
201
- let w = r.reduce((e, t) => e + t.weight, 0);
202
- return w === 0 ? {
217
+ let C = n.reduce((e, t) => e + t.weight, 0);
218
+ return C === 0 ? {
203
219
  score: 0,
204
- signals: r
220
+ signals: n
205
221
  } : {
206
- score: r.reduce((e, t) => e + t.score * t.weight, 0) / w,
207
- signals: r
222
+ score: n.reduce((e, t) => e + t.score * t.weight, 0) / C,
223
+ signals: n
208
224
  };
209
- }, I = (e) => {
210
- let t = Object.entries(e).filter(([, e]) => e !== void 0);
211
- return Object.fromEntries(t);
212
- }, te = (e) => {
213
- let t = /* @__PURE__ */ new Map();
214
- for (let n of e) {
215
- let e = `${n.scheme?.trim().toLowerCase() ?? ""}:${n.value.trim().toLowerCase()}`, r = t.get(e);
216
- if (r === void 0) {
217
- t.set(e, n);
218
- continue;
219
- }
220
- n.unique === !0 && r.unique !== !0 && t.set(e, {
221
- ...r,
222
- unique: !0
223
- });
224
- }
225
- return [...t.values()];
226
- }, L = (...e) => {
227
- let t = e.filter((e) => e !== void 0), n = (e) => {
228
- for (let n of t) {
229
- let t = n[e];
230
- if (t !== void 0) return t;
231
- }
232
- }, r = te(t.flatMap((e) => e.identifiers ?? [])), i = I({
233
- series: t.find((e) => e.belongsTo?.series !== void 0)?.belongsTo?.series,
234
- collection: t.find((e) => e.belongsTo?.collection !== void 0)?.belongsTo?.collection
235
- });
236
- return I({
237
- title: n("title"),
238
- cover: n("cover"),
239
- description: n("description"),
240
- publisher: n("publisher"),
241
- imprint: n("imprint"),
242
- rights: n("rights"),
243
- languages: n("languages"),
244
- subjects: n("subjects"),
245
- contributors: n("contributors"),
246
- published: n("published"),
247
- readingDirection: n("readingDirection"),
248
- renditionLayout: n("renditionLayout"),
249
- renditionFlow: n("renditionFlow"),
250
- renditionSpread: n("renditionSpread"),
251
- numberOfPages: n("numberOfPages"),
252
- gtin: n("gtin"),
253
- isbn: n("isbn"),
254
- identifiers: r.length > 0 ? r : void 0,
255
- belongsTo: Object.keys(i).length > 0 ? i : void 0,
256
- properties: n("properties"),
257
- comic: n("comic"),
258
- apple: n("apple"),
259
- kobo: n("kobo")
260
- });
261
- }, R = class extends Error {
225
+ }, j = class extends Error {
262
226
  status;
263
227
  constructor(e, t) {
264
228
  super(t ?? `Provider responded with status ${e}`), this.name = "MetadataProviderResponseError", this.status = e;
265
229
  }
266
- }, z = (e) => {
230
+ }, M = (e) => {
267
231
  if (typeof e != "object" || !e || !("status" in e)) return;
268
232
  let { status: t } = e;
269
233
  if (!(typeof t != "number" || !Number.isInteger(t))) return t >= 100 && t <= 599 ? t : void 0;
270
- }, B = t.namespace("@prose-reader/metadata-fetcher", void 0, { color: "#b06642" }), ne = 5, re = .5, ie = 1, ae = ({ candidate: e, providerId: t, score: n, signals: r, accepted: i, includeRaw: a }) => I({
234
+ }, N = t.namespace("@prose-reader/metadata-fetcher", void 0, { color: "#b06642" }), P = (e) => {
235
+ let t = Object.entries(e).filter(([, e]) => e !== void 0);
236
+ return Object.fromEntries(t);
237
+ }, le = 5, ue = .5, de = 3, fe = ({ candidate: e, providerId: t, score: n, signals: r, accepted: i, includeRaw: a }) => P({
271
238
  providerId: t,
272
239
  score: n,
273
240
  signals: r,
@@ -276,8 +243,8 @@ var n = (e) => {
276
243
  id: e.id,
277
244
  url: e.url,
278
245
  raw: a ? e.raw : void 0
279
- }), V = async (e, t) => {
280
- let n = "metadata" in e ? e.metadata : e, r = t.limit ?? ne, i = t.minScore ?? re, a = t.includeRaw === !0, o = await Promise.all(t.providers.map(async (e) => {
246
+ }), pe = async (e, t) => {
247
+ let n = "metadata" in e ? e.metadata : e, r = t.limit ?? le, i = t.minScore ?? ue, a = t.includeRaw === !0, o = await Promise.all(t.providers.map(async (e) => {
281
248
  try {
282
249
  return {
283
250
  provider: e,
@@ -289,12 +256,12 @@ var n = (e) => {
289
256
  };
290
257
  } catch (n) {
291
258
  if (t.signal?.aborted === !0) throw n;
292
- return B.error(`fetchMetadata: provider "${e.id}" failed`, n), {
259
+ return N.error(`fetchMetadata: provider "${e.id}" failed`, n), {
293
260
  provider: e,
294
261
  candidates: void 0,
295
- failure: I({
262
+ failure: P({
296
263
  id: e.id,
297
- status: z(n)
264
+ status: M(n)
298
265
  })
299
266
  };
300
267
  }
@@ -302,8 +269,8 @@ var n = (e) => {
302
269
  for (let { provider: e, candidates: t } of o) {
303
270
  if (t === void 0) continue;
304
271
  let o = t.map((t) => {
305
- let { score: r, signals: o } = F(n, t.metadata);
306
- return ae({
272
+ let { score: r, signals: o } = ce(n, t.metadata);
273
+ return fe({
307
274
  candidate: t,
308
275
  providerId: e.id,
309
276
  score: r,
@@ -312,7 +279,7 @@ var n = (e) => {
312
279
  includeRaw: a
313
280
  });
314
281
  }).sort((e, t) => t.score - e.score).slice(0, r);
315
- c[e.id] !== void 0 && B.warn(`fetchMetadata: several providers share the id "${e.id}"`), c[e.id] = {
282
+ c[e.id] !== void 0 && N.warn(`fetchMetadata: several providers share the id "${e.id}"`), c[e.id] = {
316
283
  provider: {
317
284
  id: e.id,
318
285
  name: e.name
@@ -320,63 +287,36 @@ var n = (e) => {
320
287
  matches: o
321
288
  }, l.push(...o);
322
289
  }
323
- let u = [...l].sort((e, t) => t.score - e.score);
324
290
  return {
325
- version: ie,
326
- metadata: L(...u.filter((e) => e.accepted).map((e) => e.metadata)),
327
- matches: u,
291
+ version: de,
292
+ matches: [...l].sort((e, t) => t.score - e.score),
328
293
  sources: c,
329
294
  failedProviders: s
330
295
  };
331
- }, H = (e) => typeof e == "object" && !!e && !Array.isArray(e), U = (e, t) => {
332
- let n = e[t];
333
- if (typeof n != "string") return;
334
- let r = n.trim();
335
- return r.length > 0 ? r : void 0;
336
- }, W = (e, t) => {
337
- let n = e[t];
338
- return typeof n == "number" && Number.isFinite(n) ? n : void 0;
339
- }, G = (e, t) => {
340
- let n = e[t];
341
- if (!Array.isArray(n)) return;
342
- let r = n.filter((e) => typeof e == "string").map((e) => e.trim()).filter((e) => e.length > 0);
343
- return r.length > 0 ? r : void 0;
344
- }, K = (e, t) => {
345
- let n = e[t];
346
- return Array.isArray(n) ? n.filter(H) : [];
347
- }, q = (e) => ({
348
- key: U(e, "key"),
349
- title: U(e, "title"),
350
- subtitle: U(e, "subtitle"),
351
- author_name: G(e, "author_name"),
352
- first_publish_year: W(e, "first_publish_year"),
353
- publisher: G(e, "publisher"),
354
- language: G(e, "language"),
355
- subject: G(e, "subject"),
356
- number_of_pages_median: W(e, "number_of_pages_median"),
357
- cover_i: W(e, "cover_i"),
358
- id_project_gutenberg: G(e, "id_project_gutenberg")
359
- }), J = (e) => H(e) ? K(e, "docs").map(q) : [], oe = /* @__PURE__ */ new Set(["gutenberg.org", "www.gutenberg.org"]), se = [
296
+ }, F = "ProjectGutenberg", me = /* @__PURE__ */ new Set(["gutenberg.org", "www.gutenberg.org"]), he = [
360
297
  /^\/ebooks\/(\d+)(?:[./]|$)/i,
361
298
  /^\/files\/(\d+)(?:\/|$)/i,
362
299
  /^\/cache\/epub\/(\d+)(?:\/|$)/i,
363
300
  /^\/(\d+)(?:\/|$)/
364
- ], ce = (e) => {
301
+ ], I = (e) => {
302
+ let t = e.trim();
303
+ if (!/^\d+$/.test(t)) return;
304
+ let n = t.replace(/^0+(?=\d)/, "");
305
+ return n === "0" ? void 0 : n;
306
+ }, ge = (e) => {
365
307
  try {
366
308
  let t = new URL(e.trim());
367
- if (t.protocol !== "http:" && t.protocol !== "https:" || !oe.has(t.hostname.toLowerCase())) return;
368
- for (let e of se) {
309
+ if (t.protocol !== "http:" && t.protocol !== "https:" || !me.has(t.hostname.toLowerCase())) return;
310
+ for (let e of he) {
369
311
  let n = e.exec(t.pathname)?.[1];
370
- if (n !== void 0) return n;
312
+ if (n !== void 0) return I(n);
371
313
  }
372
314
  } catch {
373
315
  return;
374
316
  }
375
- }, le = (e) => {
317
+ }, L = (e) => {
376
318
  for (let t of e.identifiers ?? []) {
377
- let e = t.scheme?.trim().toLowerCase();
378
- if (e !== void 0 && e !== "url" && e !== "uri") continue;
379
- let n = ce(t.value);
319
+ let e = t.scheme?.trim().toLowerCase(), n = e === "projectgutenberg" ? I(t.value) : e === void 0 || e === "url" || e === "uri" ? ge(t.value) : void 0;
380
320
  if (n !== void 0) return {
381
321
  id: n,
382
322
  identifier: {
@@ -385,7 +325,34 @@ var n = (e) => {
385
325
  }
386
326
  };
387
327
  }
388
- }, ue = {
328
+ }, R = (e) => typeof e == "object" && !!e && !Array.isArray(e), z = (e, t) => {
329
+ let n = e[t];
330
+ if (typeof n != "string") return;
331
+ let r = n.trim();
332
+ return r.length > 0 ? r : void 0;
333
+ }, B = (e, t) => {
334
+ let n = e[t];
335
+ return typeof n == "number" && Number.isFinite(n) ? n : void 0;
336
+ }, V = (e, t) => {
337
+ let n = e[t];
338
+ if (!Array.isArray(n)) return;
339
+ let r = n.filter((e) => typeof e == "string").map((e) => e.trim()).filter((e) => e.length > 0);
340
+ return r.length > 0 ? r : void 0;
341
+ }, _e = (e, t) => {
342
+ let n = e[t];
343
+ return Array.isArray(n) ? n.filter(R) : [];
344
+ }, ve = (e) => ({
345
+ key: z(e, "key"),
346
+ title: z(e, "title"),
347
+ subtitle: z(e, "subtitle"),
348
+ author_name: V(e, "author_name"),
349
+ first_publish_year: B(e, "first_publish_year"),
350
+ language: V(e, "language"),
351
+ subject: V(e, "subject"),
352
+ number_of_pages_median: B(e, "number_of_pages_median"),
353
+ cover_i: B(e, "cover_i"),
354
+ id_project_gutenberg: V(e, "id_project_gutenberg")
355
+ }), H = (e) => R(e) ? _e(e, "docs").map(ve) : [], ye = {
389
356
  afr: "af",
390
357
  alb: "sq",
391
358
  amh: "am",
@@ -490,28 +457,27 @@ var n = (e) => {
490
457
  wel: "cy",
491
458
  yid: "yi",
492
459
  zho: "zh"
493
- }, de = /* @__PURE__ */ new Set([
460
+ }, be = /* @__PURE__ */ new Set([
494
461
  "mul",
495
462
  "und",
496
463
  "zxx",
497
464
  "sgn"
498
- ]), Y = (e) => {
465
+ ]), U = (e) => {
499
466
  let t = e.trim().toLowerCase();
500
- if (t.length !== 0 && !de.has(t)) return ue[t] ?? t;
501
- }, fe = 25, pe = {
467
+ if (t.length !== 0 && !be.has(t)) return ye[t] ?? t;
468
+ }, xe = 25, Se = {
502
469
  key: "identifiers",
503
470
  title: "title",
504
471
  subtitle: "title",
505
472
  author_name: "contributors",
506
- first_publish_year: "published",
507
- publisher: "publisher",
473
+ first_publish_year: "publication.original.date",
508
474
  language: "languages",
509
475
  subject: "subjects",
510
476
  number_of_pages_median: "numberOfPages",
511
477
  cover_i: "cover",
512
478
  id_project_gutenberg: "identifiers"
513
- }, X = "OpenLibrary", me = "ProjectGutenberg", Z = (e) => e.length > 0 ? e : void 0, Q = (e, t) => {
514
- let n = e.title !== void 0 && e.subtitle !== void 0 ? `${e.title}: ${e.subtitle}` : e.title, r = Z([...new Set((e.language ?? []).map(Y).filter((e) => e !== void 0))]), i = [
479
+ }, W = "OpenLibrary", Ce = "ProjectGutenberg", G = (e) => e.length > 0 ? e : void 0, K = (e, t) => {
480
+ let n = e.title !== void 0 && e.subtitle !== void 0 ? `${e.title}: ${e.subtitle}` : e.title, r = G([...new Set((e.language ?? []).map(U).filter((e) => e !== void 0))]), i = [
515
481
  ...t.isbn === void 0 ? [] : [{
516
482
  value: t.isbn,
517
483
  scheme: "ISBN"
@@ -519,57 +485,55 @@ var n = (e) => {
519
485
  ...t.matchedProjectGutenbergIdentifier === void 0 ? [] : [t.matchedProjectGutenbergIdentifier],
520
486
  ...(e.id_project_gutenberg ?? []).map((e) => ({
521
487
  value: e,
522
- scheme: me
488
+ scheme: Ce
523
489
  })),
524
490
  ...e.key === void 0 ? [] : [{
525
491
  value: e.key,
526
- scheme: X
492
+ scheme: W
527
493
  }]
528
494
  ];
529
- return I({
495
+ return P({
530
496
  title: n,
531
497
  cover: e.cover_i === void 0 ? void 0 : {
532
498
  uri: `${t.coversBaseUrl}/b/id/${e.cover_i}-L.jpg`,
533
499
  mediaType: "image/jpeg",
534
500
  confidence: "derived"
535
501
  },
536
- publisher: e.publisher?.[0],
502
+ publication: e.first_publish_year === void 0 ? void 0 : { original: { date: { year: e.first_publish_year } } },
537
503
  languages: r,
538
- subjects: Z((e.subject ?? []).slice(0, 25)),
539
- contributors: Z((e.author_name ?? []).map((e) => ({
504
+ subjects: G((e.subject ?? []).slice(0, 25)),
505
+ contributors: G((e.author_name ?? []).map((e) => ({
540
506
  name: e,
541
507
  roles: ["author"]
542
508
  }))),
543
- published: e.first_publish_year === void 0 ? void 0 : { year: e.first_publish_year },
544
509
  numberOfPages: e.number_of_pages_median,
545
510
  isbn: t.isbn,
546
- identifiers: Z(i)
511
+ identifiers: G(i)
547
512
  });
548
- }, $ = "openLibrary", he = "https://openlibrary.org", ge = "https://covers.openlibrary.org", _e = [
513
+ }, we = "openLibrary", Te = "https://openlibrary.org", Ee = "https://covers.openlibrary.org", De = [
549
514
  "key",
550
515
  "title",
551
516
  "subtitle",
552
517
  "author_name",
553
518
  "first_publish_year",
554
- "publisher",
555
519
  "language",
556
520
  "subject",
557
521
  "number_of_pages_median",
558
522
  "cover_i",
559
523
  "id_project_gutenberg"
560
- ].join(","), ve = (e) => {
524
+ ].join(","), Oe = (e) => {
561
525
  let t = e.title?.trim();
562
526
  if (t === void 0 || t.length === 0) return;
563
- let r = n(e)[0];
527
+ let n = r(e)[0];
564
528
  return {
565
529
  title: t,
566
- ...r === void 0 ? {} : { author: r }
530
+ ...n === void 0 ? {} : { author: n }
567
531
  };
568
- }, ye = (e = {}) => {
569
- let t = e.baseUrl ?? he, n = e.coversBaseUrl ?? ge, r = async (n, r) => {
532
+ }, ke = (e = {}) => {
533
+ let t = e.baseUrl ?? Te, n = e.coversBaseUrl ?? Ee, r = async (n, r) => {
570
534
  let i = new URL("/search.json", t);
571
535
  for (let [e, t] of Object.entries(n)) i.searchParams.set(e, t);
572
- i.searchParams.set("fields", _e), i.searchParams.set("limit", String(r.limit));
536
+ i.searchParams.set("fields", De), i.searchParams.set("limit", String(r.limit));
573
537
  let a = await (e.fetch ?? globalThis.fetch)(i.toString(), {
574
538
  signal: r.signal,
575
539
  headers: {
@@ -577,10 +541,10 @@ var n = (e) => {
577
541
  ...e.userAgent === void 0 ? {} : { "User-Agent": e.userAgent }
578
542
  }
579
543
  });
580
- if (!a.ok) throw new R(a.status, `Open Library search failed with status ${a.status}`);
581
- return J(await a.json());
544
+ if (!a.ok) throw new j(a.status, `Open Library search failed with status ${a.status}`);
545
+ return H(await a.json());
582
546
  }, i = (e, r = {}) => e.map((e) => ({
583
- metadata: Q(e, {
547
+ metadata: K(e, {
584
548
  coversBaseUrl: n,
585
549
  isbn: r.isbn,
586
550
  matchedProjectGutenbergIdentifier: r.confirmedProjectGutenberg?.identifier
@@ -590,10 +554,10 @@ var n = (e) => {
590
554
  raw: e
591
555
  }));
592
556
  return {
593
- id: $,
557
+ id: we,
594
558
  name: "Open Library",
595
559
  search: async (e, t) => {
596
- let n = e.isbn?.trim() || void 0, a = le(e);
560
+ let n = e.isbn?.trim() || void 0, a = L(e);
597
561
  if (n !== void 0) {
598
562
  let e = await r({ isbn: n }, t);
599
563
  if (e.length > 0) return i(e, { isbn: n });
@@ -602,17 +566,204 @@ var n = (e) => {
602
566
  let e = await r({ q: `id_project_gutenberg:${a.id}` }, t);
603
567
  if (e.length > 0) return i(e, { confirmedProjectGutenberg: a });
604
568
  }
605
- let o = ve(e);
569
+ let o = Oe(e);
606
570
  return o === void 0 ? [] : i(await r(o, t));
607
571
  }
608
572
  };
609
- }, be = (e) => [
573
+ }, q = (e) => e.includes(":") ? e.slice(e.lastIndexOf(":") + 1) : e, Ae = (e) => e.type === "element", J = (e, t) => e.children.filter((e) => Ae(e) && q(e.name).toLowerCase() === t.toLowerCase()), Y = (e, t) => J(e, t)[0], X = (e) => {
574
+ let t = e?.val.trim();
575
+ return t !== void 0 && t.length > 0 ? t : void 0;
576
+ }, Z = (e, t) => {
577
+ for (let [n, r] of Object.entries(e.attr)) {
578
+ if (q(n).toLowerCase() !== t.toLowerCase()) continue;
579
+ let e = r.trim();
580
+ if (e.length > 0) return e;
581
+ }
582
+ }, je = (e, t) => J(e, t).flatMap((e) => {
583
+ let t = X(Y(Y(e, "Description") ?? e, "value"));
584
+ return t === void 0 ? [] : [t];
585
+ }), Me = (e) => {
586
+ let t = Z(e, "about"), n = t === void 0 ? void 0 : /(?:^|\/)ebooks\/(\d+)$/.exec(t)?.[1];
587
+ if (n === void 0) return;
588
+ let r = n.replace(/^0+(?=\d)/, "");
589
+ return r === "0" ? void 0 : r;
590
+ }, Ne = (e) => {
591
+ let t = [];
592
+ for (let n of e.children) {
593
+ if (!Ae(n)) continue;
594
+ let e = n.name.toLowerCase() === "dcterms:creator", r = n.name.toLowerCase().startsWith("marcrel:");
595
+ if (!e && !r) continue;
596
+ let i = X(Y(Y(n, "agent") ?? n, "name"));
597
+ i !== void 0 && t.push({
598
+ name: i,
599
+ role: e ? "aut" : q(n.name).toLowerCase()
600
+ });
601
+ }
602
+ return t;
603
+ }, Pe = (e) => J(e, "subject").flatMap((e) => {
604
+ let t = Y(e, "Description"), n = t === void 0 ? void 0 : Z(Y(t, "memberOf") ?? t, "resource"), r = X(t === void 0 ? void 0 : Y(t, "value"));
605
+ return r !== void 0 && n?.endsWith("/LCSH") === !0 ? [r] : [];
606
+ }), Fe = (e) => {
607
+ let t = J(e, "hasFormat").flatMap((e) => {
608
+ let t = Y(e, "file");
609
+ if (t === void 0) return [];
610
+ let n = Z(t, "about"), r = J(t, "format").map((e) => X(Y(Y(e, "Description") ?? e, "value"))).find((e) => e?.startsWith("image/") === !0);
611
+ return n === void 0 || r === void 0 || !/\.cover\.(?:medium|small)\.[a-z0-9]+(?:$|[?#])/i.test(n) ? [] : [{
612
+ uri: n,
613
+ mediaType: r
614
+ }];
615
+ });
616
+ return t.find((e) => /\.cover\.medium\./i.test(e.uri)) ?? t[0];
617
+ }, Q = (e) => e.length > 0 ? e : void 0, Ie = (e) => {
618
+ let t;
619
+ try {
620
+ t = new n(e);
621
+ } catch (e) {
622
+ let t = e instanceof Error ? e.message : String(e);
623
+ throw Error(`Project Gutenberg RDF is malformed: ${t}`, { cause: e });
624
+ }
625
+ if (q(t.name).toLowerCase() !== "rdf") return;
626
+ let r = Y(t, "ebook");
627
+ if (r === void 0) return;
628
+ let i = Me(r);
629
+ if (i === void 0) return;
630
+ let a = [...new Set(je(r, "language"))], o = [...new Set(Pe(r))], s = [...new Set(je(r, "bookshelf"))], c = Ne(r);
631
+ return {
632
+ id: i,
633
+ title: X(Y(r, "title")),
634
+ publisher: X(Y(r, "publisher")),
635
+ issued: X(Y(r, "issued")),
636
+ originalPublication: X(Y(r, "marc260")),
637
+ rights: X(Y(r, "rights")),
638
+ description: X(Y(r, "description")),
639
+ summary: X(Y(r, "marc520")),
640
+ languages: Q(a),
641
+ subjects: Q(o),
642
+ bookshelves: Q(s),
643
+ contributors: Q(c),
644
+ cover: Fe(r)
645
+ };
646
+ }, Le = 25, Re = {
647
+ id: "identifiers",
648
+ title: "title",
649
+ publisher: "publication.edition.publisher",
650
+ issued: "publication.edition.date",
651
+ originalPublication: "publication.original",
652
+ rights: "rights",
653
+ description: "description",
654
+ summary: "description",
655
+ languages: "languages",
656
+ subjects: "subjects",
657
+ bookshelves: "subjects",
658
+ contributors: "contributors",
659
+ cover: "cover"
660
+ }, ze = {
661
+ art: "artist",
662
+ aut: "author",
663
+ clr: "colorist",
664
+ ctb: "contributor",
665
+ edt: "editor",
666
+ ill: "illustrator",
667
+ nrt: "narrator",
668
+ trl: "translator"
669
+ }, Be = (e) => {
670
+ let t = /* @__PURE__ */ new Map();
671
+ for (let n of e.contributors ?? []) {
672
+ let e = n.name.trim().toLowerCase(), r = ze[n.role.trim().toLowerCase()] ?? n.role, i = t.get(e);
673
+ i === void 0 ? t.set(e, {
674
+ name: n.name,
675
+ roles: [r]
676
+ }) : i.roles.includes(r) || i.roles.push(r);
677
+ }
678
+ return t.size > 0 ? [...t.values()] : void 0;
679
+ }, Ve = (e) => {
680
+ if (e === void 0) return;
681
+ let t = /^(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?$/.exec(e.trim());
682
+ if (t === null) return;
683
+ let n = Number(t[1]), r = t[2] === void 0 ? void 0 : Number(t[2]), i = t[3] === void 0 ? void 0 : Number(t[3]);
684
+ if (!(!Number.isInteger(n) || n <= 0 || r !== void 0 && (r < 1 || r > 12) || i !== void 0 && (i < 1 || i > 31))) return {
685
+ year: n,
686
+ ...r === void 0 ? {} : { month: r },
687
+ ...i === void 0 ? {} : { day: i }
688
+ };
689
+ }, $ = (e, t) => e.split("$").slice(1).flatMap((e) => e[0]?.toLowerCase() === t.toLowerCase() ? [e.slice(1).trim()] : []).filter((e) => e.length > 0), He = (e) => {
690
+ if (e === void 0) return;
691
+ let t = $(e, "b"), n = (t.length === 1 ? t[0] : void 0)?.replace(/[\s,;:/]+$/u, "").trim(), r = $(e, "c"), i = [...new Set(r.flatMap((e) => [...e.matchAll(/\d{4}/g)].flatMap((e) => e[0] === void 0 ? [] : [Number(e[0])])))], a = P({
692
+ date: i.length === 1 ? { year: i[0] } : void 0,
693
+ publisher: n !== void 0 && n.length > 0 && !/^\[?s\.n\.?\]?$/i.test(n) ? n : void 0
694
+ });
695
+ return a.date !== void 0 || a.publisher !== void 0 ? a : void 0;
696
+ }, Ue = (e, t) => {
697
+ try {
698
+ let n = new URL(e, t);
699
+ return n.protocol === "http:" || n.protocol === "https:" ? n.toString() : void 0;
700
+ } catch {
701
+ return;
702
+ }
703
+ }, We = (e) => e.length > 0 ? e : void 0, Ge = (e, t) => {
704
+ let n = [t.matchedIdentifier, {
705
+ value: e.id,
706
+ scheme: F
707
+ }].filter((e, t, n) => n.findIndex((t) => t.value.trim().toLowerCase() === e.value.trim().toLowerCase() && t.scheme?.trim().toLowerCase() === e.scheme?.trim().toLowerCase()) === t), r = [.../* @__PURE__ */ new Set([...e.subjects ?? [], ...e.bookshelves ?? []])].slice(0, 25), i = e.cover === void 0 ? void 0 : Ue(e.cover.uri, t.baseUrl), a = i === void 0 ? void 0 : {
708
+ uri: i,
709
+ mediaType: e.cover?.mediaType,
710
+ confidence: "derived"
711
+ }, o = P({
712
+ date: Ve(e.issued),
713
+ publisher: e.publisher
714
+ }), s = P({
715
+ original: He(e.originalPublication),
716
+ edition: o.date !== void 0 || o.publisher !== void 0 ? o : void 0
717
+ });
718
+ return P({
719
+ title: e.title,
720
+ publication: s.original !== void 0 || s.edition !== void 0 ? s : void 0,
721
+ description: e.summary ?? e.description,
722
+ rights: e.rights,
723
+ languages: We([...new Set(e.languages ?? [])]),
724
+ subjects: We(r),
725
+ contributors: Be(e),
726
+ identifiers: n,
727
+ cover: a
728
+ });
729
+ }, Ke = "projectGutenberg", qe = "https://www.gutenberg.org", Je = (e = {}) => {
730
+ let t = e.baseUrl ?? qe;
731
+ return {
732
+ id: Ke,
733
+ name: "Project Gutenberg",
734
+ search: async (n, r) => {
735
+ let i = L(n);
736
+ if (i === void 0) return [];
737
+ let a = new URL(`/cache/epub/${i.id}/pg${i.id}.rdf`, t), o = await (e.fetch ?? globalThis.fetch)(a.toString(), {
738
+ signal: r.signal,
739
+ headers: {
740
+ Accept: "application/rdf+xml, application/xml;q=0.9",
741
+ ...e.userAgent === void 0 ? {} : { "User-Agent": e.userAgent }
742
+ }
743
+ });
744
+ if (o.status === 404) return [];
745
+ if (!o.ok) throw new j(o.status, `Project Gutenberg metadata lookup failed with status ${o.status}`);
746
+ let s = Ie(await o.text());
747
+ if (s === void 0 || s.id !== i.id) throw Error(`Project Gutenberg RDF did not contain the requested eBook ${i.id}`);
748
+ let c = new URL(`/ebooks/${i.id}`, t).toString();
749
+ return [{
750
+ id: s.id,
751
+ url: c,
752
+ raw: s,
753
+ metadata: Ge(s, {
754
+ baseUrl: t,
755
+ matchedIdentifier: i.identifier
756
+ })
757
+ }];
758
+ }
759
+ };
760
+ }, Ye = (e) => [
610
761
  e.title,
611
762
  e.isbn,
612
763
  e.gtin,
613
764
  e.belongsTo?.series?.[0]?.name
614
- ].some((e) => e !== void 0 && e.trim().length > 0) || (e.identifiers ?? []).length > 0 || n(e).length > 0;
765
+ ].some((e) => e !== void 0 && e.trim().length > 0) || (e.identifiers ?? []).length > 0 || r(e).length > 0;
615
766
  //#endregion
616
- export { E as METADATA_MATCH_WEIGHTS, R as MetadataProviderResponseError, X as OPEN_LIBRARY_IDENTIFIER_SCHEME, fe as OPEN_LIBRARY_MAX_SUBJECTS, $ as OPEN_LIBRARY_PROVIDER_ID, ye as createOpenLibraryProvider, V as fetchMetadata, be as hasSearchTerms, Y as marcLanguageToBcp47, L as mergeResolvedMetadata, n as metadataAuthors, c as normalizeForComparison, pe as openLibraryMetadataHomes, J as parseOpenLibrarySearchResponse, T as personNameSimilarity, Q as resolveOpenLibraryDoc, z as responseErrorStatus, F as scoreMetadataCandidate, u as textSimilarity, C as titleSimilarity, a as toIsbn13 };
767
+ export { D as METADATA_MATCH_WEIGHTS, j as MetadataProviderResponseError, W as OPEN_LIBRARY_IDENTIFIER_SCHEME, xe as OPEN_LIBRARY_MAX_SUBJECTS, we as OPEN_LIBRARY_PROVIDER_ID, F as PROJECT_GUTENBERG_IDENTIFIER_SCHEME, Le as PROJECT_GUTENBERG_MAX_SUBJECTS, Ke as PROJECT_GUTENBERG_PROVIDER_ID, ke as createOpenLibraryProvider, Je as createProjectGutenbergProvider, pe as fetchMetadata, Ye as hasSearchTerms, U as marcLanguageToBcp47, r as metadataAuthors, l as normalizeForComparison, Se as openLibraryMetadataHomes, H as parseOpenLibrarySearchResponse, Ie as parseProjectGutenbergRdf, E as personNameSimilarity, L as projectGutenbergLookupFromMetadata, Re as projectGutenbergMetadataHomes, K as resolveOpenLibraryDoc, Ge as resolveProjectGutenbergRecord, M as responseErrorStatus, ce as scoreMetadataCandidate, d as textSimilarity, w as titleSimilarity, o as toIsbn13 };
617
768
 
618
769
  //# sourceMappingURL=index.js.map