@prose-reader/enhancer-search 1.344.0 → 1.345.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 +1 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../../shared/dist/index.js","../package.json","../src/report.ts","../src/search.ts","../src/index.ts"],"sourcesContent":["//#region src/array.ts\nvar e = (e, t) => e === t || e.length === t.length && e.every((e, n) => e === t[n]), t = (e) => e.split(/[#?]/)[0]?.split(\".\").pop()?.trim() || \"\";\nfunction n(e) {\n\tlet t = [];\n\tif (e.length === 0) return \"\";\n\tif (typeof e[0] != \"string\") throw TypeError(`Url must be a string. Received ${e[0]}`);\n\te[0].match(/^[^/:]+:\\/*$/) && e.length > 1 && (e[0] = e.shift() + e[0]), e[0].match(/^file:\\/\\/\\//) ? e[0] = e[0].replace(/^([^/:]+):\\/*/, \"$1:///\") : e[0] = e[0].replace(/^([^/:]+):\\/*/, \"$1://\");\n\tfor (let n = 0; n < e.length; n++) {\n\t\tlet r = e[n];\n\t\tif (typeof r != \"string\") throw TypeError(`Url must be a string. Received ${r}`);\n\t\tr !== \"\" && (n > 0 && (r = r.replace(/^[/]+/, \"\")), r = n < e.length - 1 ? r.replace(/[/]+$/, \"\") : r.replace(/[/]+$/, \"/\"), t.push(r));\n\t}\n\tlet n = t.join(\"/\");\n\tn = n.replace(/\\/(\\?|&|#[^!])/g, \"$1\");\n\tlet r = n.split(\"?\");\n\treturn n = r.shift() + (r.length > 0 ? \"?\" : \"\") + r.join(\"&\"), n;\n}\nfunction r(...e) {\n\treturn n(Array.from(Array.isArray(e[0]) ? e[0] : e));\n}\nfunction i(e) {\n\tlet t = e.split(\"/\");\n\treturn t.pop(), t.join(\"/\");\n}\n//#endregion\n//#region src/contentType.ts\nvar a = (e) => {\n\tswitch (t(e).toLowerCase()) {\n\t\tcase \"png\": return \"image/png\";\n\t\tcase \"jpg\": return \"image/jpg\";\n\t\tcase \"jpeg\": return \"image/jpeg\";\n\t\tcase \"gif\": return \"image/gif\";\n\t\tcase \"webp\": return \"image/webp\";\n\t\tcase \"avif\": return \"image/avif\";\n\t\tcase \"bmp\": return \"image/bmp\";\n\t\tcase \"tif\":\n\t\tcase \"tiff\": return \"image/tiff\";\n\t\tcase \"svg\": return \"image/svg+xml\";\n\t\tcase \"txt\": return \"text/plain\";\n\t\tcase \"xhtml\": return \"application/xhtml+xml\";\n\t\tcase \"mp3\": return \"audio/mpeg\";\n\t\tcase \"m4a\":\n\t\tcase \"m4b\": return \"audio/mp4\";\n\t\tcase \"aac\": return \"audio/aac\";\n\t\tcase \"ogg\":\n\t\tcase \"oga\": return \"audio/ogg\";\n\t\tcase \"wav\": return \"audio/wav\";\n\t\tcase \"flac\": return \"audio/flac\";\n\t\tcase \"opus\": return \"audio/opus\";\n\t}\n}, o = ({ mimeType: e, uri: t }) => (e ?? a(t ?? \"\"))?.startsWith(\"application/xhtml+xml\"), s = (e) => e.startsWith(\"image/\") || e.startsWith(\"audio/\") || e.startsWith(\"video/\"), c = (e) => {\n\tif (!e.length) return;\n\tlet t = e.indexOf(\";\");\n\treturn t >= 0 ? e.substring(0, t) : e;\n}, l = /^[A-Za-z0-9_][A-Za-z0-9_.-]*$/, u = /^[A-Za-z0-9_]/, d = /^xml/i, f = /[^A-Za-z0-9_.-]+/g, p = \"_\", m = (e) => e.replace(/^_+|_+$/g, \"\"), h = (e) => m(e.trim().replaceAll(\"/\", \"_\").replace(f, \"_\")), g = (e) => {\n\tif (l.test(e) && !d.test(e)) return e;\n\tlet t = h(e), n = t && !d.test(t) ? t : `${p}${t}`;\n\treturn u.test(n) ? n : `${p}${n}`;\n}, _ = (e, t) => {\n\tlet n = g(e);\n\tif (!t.has(n)) return t.add(n), n;\n\tlet r = 2, i = `${n}-${r}`;\n\tfor (; t.has(i);) r += 1, i = `${n}-${r}`;\n\treturn t.add(i), i;\n}, v = () => {\n\tlet e = /* @__PURE__ */ new Set();\n\treturn (t) => _(t, e);\n}, y = (e) => {\n\tlet t = e.pageSpreadLeft === !0;\n\tif (t !== (e.pageSpreadRight === !0)) return t ? \"left\" : \"right\";\n}, b = (e, t, n) => {\n\tif (Object.is(e, t)) return !0;\n\tif (typeof e != \"object\" || !e || typeof t != \"object\" || !t) return !1;\n\tlet r = Object.keys(e), i = Object.keys(t);\n\tif (r.length !== i.length) return !1;\n\tlet a = n?.customEqual ?? Object.is, o = e, s = t;\n\tfor (let e of r) if (!Object.hasOwn(s, e) || !a(o[e], s[e])) return !1;\n\treturn !0;\n}, x = (e, t) => e.reduce((e, n) => {\n\tlet r = t(n);\n\treturn e[r] || (e[r] = []), e[r].push(n), e;\n}, {});\nfunction S(e, t) {\n\tlet n = { ...e };\n\tfor (let r in t) if (Object.hasOwn(t, r)) {\n\t\tlet i = t[r];\n\t\t(i !== void 0 || !(r in e)) && (n[r] = i);\n\t}\n\treturn n;\n}\n//#endregion\n//#region src/report.ts\nfunction C() {\n\tlet e = globalThis.__PROSE_READER_DEBUG;\n\treturn e === !0 || e === \"true\";\n}\nvar w = (e, t) => typeof e == \"boolean\" ? {\n\tenabled: e,\n\toptions: t\n} : {\n\tenabled: e?.enabled,\n\toptions: e ?? t\n}, T = (e) => e.at(-1)?.color, E = (e) => {\n\tif (!e.length) return;\n\tif (!e.some((e) => e.color)) return [e.map((e) => e.label).join(\" \")];\n\tlet t = \"\", n = [];\n\tfor (let r of e) t += `%c${t ? ` ${r.label}` : r.label}`, n.push(r.color ? `color: ${r.color}` : \"\");\n\treturn [t, ...n];\n}, D = (e = [], t = C()) => {\n\tlet n = t, r = {\n\t\tenable: (e) => {\n\t\t\ta(e);\n\t\t},\n\t\tnamespace: (t, r, i) => {\n\t\t\tlet a = w(r, i), o = a.options?.color ?? T(e);\n\t\t\treturn D([...e, {\n\t\t\t\tlabel: `[${t}]`,\n\t\t\t\tcolor: o\n\t\t\t}], a.enabled ?? n);\n\t\t},\n\t\tisEnabled: () => n,\n\t\tdebug: () => {},\n\t\tinfo: () => {},\n\t\tlog: () => {},\n\t\tgroupCollapsed: () => {},\n\t\tgroupEnd: () => {},\n\t\tgetGroupArgs: (t) => {\n\t\t\tlet n = E(e);\n\t\t\tif (!n) return [t];\n\t\t\tlet [r, ...i] = n;\n\t\t\treturn [`${r} ${t}`, ...i];\n\t\t},\n\t\twarn: () => {},\n\t\terror: () => {}\n\t}, i = (t) => {\n\t\tif (!t) {\n\t\t\tr.debug = () => {}, r.info = () => {}, r.log = () => {}, r.groupCollapsed = () => {}, r.groupEnd = () => {}, r.warn = () => {}, r.error = () => {};\n\t\t\treturn;\n\t\t}\n\t\tlet n = E(e) ?? [];\n\t\tr.debug = Function.prototype.bind.call(console.debug, console, ...n), r.info = Function.prototype.bind.call(console.info, console, ...n), r.log = Function.prototype.bind.call(console.log, console, ...n), r.groupCollapsed = Function.prototype.bind.call(console.groupCollapsed, console), r.groupEnd = Function.prototype.bind.call(console.groupEnd, console), r.warn = Function.prototype.bind.call(console.warn, console, ...n), r.error = Function.prototype.bind.call(console.error, console, ...n);\n\t}, a = (e) => {\n\t\tn !== e && (n = e, i(n));\n\t};\n\treturn i(n), r;\n}, O = D(), k = \"prose-reader-resource-error\", A = (e, t) => {\n\tlet n = e.split(/(\\d+)/), r = t.split(/(\\d+)/);\n\tfor (let e = 0, t = n.length; e < t; e++) if (n[e] !== r[e]) return n[e]?.match(/\\d/) ? (n[e] || \"\") - +(r[e] || \"\") : (n[e] || \"\").localeCompare(r[e] || \"\");\n\treturn 1;\n}, j = (e) => e.endsWith(\"/\") ? e.slice(0, -1) : e, M = (e) => {\n\tlet t = j(e);\n\treturn t.substring(t.lastIndexOf(\"/\") + 1) || t;\n}, N = (e) => {\n\tlet t = e.lastIndexOf(\"/\");\n\treturn t >= 0 ? e.substring(0, t) : \"\";\n}, P = (e) => e.replaceAll(\"&\", \"&amp;\").replaceAll(\"\\\"\", \"&quot;\").replaceAll(\"'\", \"&apos;\").replaceAll(\"<\", \"&lt;\").replaceAll(\">\", \"&gt;\");\n//#endregion\nexport { k as PROSE_READER_RESOURCE_ERROR_INJECTED_META_NAME, O as Report, e as arrayEqual, _ as createUniqueXmlSafeId, g as createXmlSafeId, v as createXmlSafeIdFactory, a as detectMimeTypeFromName, P as escapeXmlAttributeValue, y as getItemSpreadPosition, i as getParentPath, N as getUriBasePath, M as getUriBasename, t as getUrlExtension, x as groupBy, s as isMediaContentMimeType, b as isShallowEqual, o as isXmlBasedMimeType, c as parseContentType, j as removeTrailingSlash, S as shallowMergeIfDefined, A as sortByTitleComparator, r as urlJoin };\n\n//# sourceMappingURL=index.js.map","{\n \"name\": \"@prose-reader/enhancer-search\",\n \"version\": \"1.343.0\",\n \"type\": \"module\",\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"files\": [\n \"/dist\"\n ],\n \"exports\": {\n \".\": {\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n }\n },\n \"scripts\": {\n \"start\": \"vite build --watch --mode development\",\n \"build\": \"tsc && vite build\",\n \"test\": \"vitest run --coverage\"\n },\n \"dependencies\": {\n \"@prose-reader/core\": \"^1.343.0\"\n },\n \"peerDependencies\": {\n \"rxjs\": \"*\"\n },\n \"gitHead\": \"4601e14dcacf50b2295cb343582a7ef2c7e1eedc\"\n}\n","import { Report } from \"@prose-reader/shared\"\nimport { name } from \"../package.json\"\n\nconst IS_DEBUG_ENABLED = true\n\nexport const report = Report.namespace(name, IS_DEBUG_ENABLED)\n","import type { Reader, SpineItem } from \"@prose-reader/core\"\nimport { type Observable, of } from \"rxjs\"\nimport type { ResultItem } from \"./types\"\n\nexport type SearchResult = ResultItem[]\n\n/**\n * Walk the subtree accumulating ranges for every match of `regexp`.\n *\n * A full-book search runs this over the rendered document of *every* spine\n * item, so the text-node loop below is the hot path (thousands of text nodes\n * per large chapter). Two things are hoisted out of it to keep the work\n * proportional to the number of matches rather than the number of nodes:\n * - the search regexp is compiled once by the caller and reused across every\n * node (only its `lastIndex` is reset), instead of recompiling per text node,\n * - matches are pushed into a single shared array instead of allocating a new\n * array at each node and spreading child results upward.\n */\nconst collectMatchingRanges = (\n node: Node,\n regexp: RegExp,\n matchLength: number,\n rangeList: Range[],\n) => {\n if (node.nodeName === `head`) return\n\n const nodeList = node.childNodes\n\n for (let i = 0; i < nodeList.length; i++) {\n const subNode = nodeList[i]\n\n if (!subNode) {\n continue\n }\n\n if (subNode.hasChildNodes()) {\n collectMatchingRanges(subNode, regexp, matchLength, rangeList)\n }\n\n if (subNode.nodeType === 3) {\n const content = (subNode as Text).data.toLowerCase()\n if (content) {\n let match: RegExpExecArray | null = null\n regexp.lastIndex = 0\n\n // biome-ignore lint/suspicious/noAssignInExpressions: TODO\n while ((match = regexp.exec(content)) !== null) {\n if (match.index >= 0 && subNode.ownerDocument) {\n const range = subNode.ownerDocument.createRange()\n range.setStart(subNode, match.index)\n range.setEnd(subNode, match.index + matchLength)\n\n rangeList.push(range)\n }\n }\n }\n }\n }\n}\n\nconst searchNodeContainingText = (node: Node, text: string) => {\n const rangeList: Range[] = []\n\n collectMatchingRanges(node, RegExp(`(${text})`, `gi`), text.length, rangeList)\n\n return rangeList\n}\n\nexport const searchInDocument = (\n reader: Reader,\n item: SpineItem,\n doc: Document,\n text: string,\n): Observable<SearchResult> => {\n const ranges = searchNodeContainingText(doc, text)\n\n const newResults = ranges.map((range) => {\n const cfi = reader.cfi.generateCfiFromRange(range, item.item)\n\n return {\n cfi,\n } satisfies ResultItem\n })\n\n return of(newResults)\n}\n","import { deferIdle, type Reader } from \"@prose-reader/core\"\nimport { defer, forkJoin, of } from \"rxjs\"\nimport { catchError, finalize, map, switchMap } from \"rxjs/operators\"\nimport { report } from \"./report\"\nimport type { SearchResult } from \"./search\"\nimport { searchInDocument } from \"./search\"\nimport type { ResultItem, SearchEnhancerAPI } from \"./types\"\n\nexport type { SearchEnhancerAPI, ResultItem, SearchResult }\n\n/**\n * Contract of search enhancer.\n *\n * - At best a result match should be navigable. It means the search needs to\n * be done on a rendered document. This is because rendering can differ from the original\n * item resource. A resource can be something non digestible and very specific (.pdf). The search\n * enhancer is agnostic and can only search into documents.\n */\nexport const searchEnhancer =\n <InheritOptions, InheritOutput extends Reader>(\n next: (options: InheritOptions) => InheritOutput,\n ) =>\n (options: InheritOptions): InheritOutput & SearchEnhancerAPI => {\n const reader = next(options)\n\n const searchForItem = (index: number, text: string) => {\n const item = reader.spineItemsManager.get(index)\n\n if (!item) {\n return of([])\n }\n\n return deferIdle(() => reader.renderHeadless(index)).pipe(\n switchMap((result) => {\n const { doc, release } = result || {}\n\n if (!doc) return of([])\n\n return deferIdle(() =>\n searchInDocument(reader, item, doc, text),\n ).pipe(\n finalize(() => {\n release?.()\n }),\n catchError((e) => {\n report.error(e)\n\n return of([])\n }),\n )\n }),\n )\n }\n\n const search = (text: string) =>\n defer(() => {\n if (text === ``) {\n return of([])\n }\n\n const searches$ =\n reader.context.manifest?.spineItems.map((_, index) =>\n searchForItem(index, text),\n ) || []\n\n return forkJoin([...searches$, of([])])\n }).pipe(\n map((results) => {\n const flattenedResults = results.flat()\n\n report.debug(\"results\", flattenedResults)\n\n return flattenedResults\n }),\n )\n\n return {\n ...reader,\n __PROSE_READER_ENHANCER_SEARCH: true,\n search: {\n search,\n },\n }\n }\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../../shared/dist/index.js","../package.json","../src/report.ts","../src/search.ts","../src/index.ts"],"sourcesContent":["//#region src/array.ts\nvar e = (e, t) => e === t || e.length === t.length && e.every((e, n) => e === t[n]), t = (e) => e.split(/[#?]/)[0]?.split(\".\").pop()?.trim() || \"\";\nfunction n(e) {\n\tlet t = [];\n\tif (e.length === 0) return \"\";\n\tif (typeof e[0] != \"string\") throw TypeError(`Url must be a string. Received ${e[0]}`);\n\te[0].match(/^[^/:]+:\\/*$/) && e.length > 1 && (e[0] = e.shift() + e[0]), e[0].match(/^file:\\/\\/\\//) ? e[0] = e[0].replace(/^([^/:]+):\\/*/, \"$1:///\") : e[0] = e[0].replace(/^([^/:]+):\\/*/, \"$1://\");\n\tfor (let n = 0; n < e.length; n++) {\n\t\tlet r = e[n];\n\t\tif (typeof r != \"string\") throw TypeError(`Url must be a string. Received ${r}`);\n\t\tr !== \"\" && (n > 0 && (r = r.replace(/^[/]+/, \"\")), r = n < e.length - 1 ? r.replace(/[/]+$/, \"\") : r.replace(/[/]+$/, \"/\"), t.push(r));\n\t}\n\tlet n = t.join(\"/\");\n\tn = n.replace(/\\/(\\?|&|#[^!])/g, \"$1\");\n\tlet r = n.split(\"?\");\n\treturn n = r.shift() + (r.length > 0 ? \"?\" : \"\") + r.join(\"&\"), n;\n}\nfunction r(...e) {\n\treturn n(Array.from(Array.isArray(e[0]) ? e[0] : e));\n}\nfunction i(e) {\n\tlet t = e.split(\"/\");\n\treturn t.pop(), t.join(\"/\");\n}\n//#endregion\n//#region src/contentType.ts\nvar a = (e) => {\n\tswitch (t(e).toLowerCase()) {\n\t\tcase \"png\": return \"image/png\";\n\t\tcase \"jpg\": return \"image/jpg\";\n\t\tcase \"jpeg\": return \"image/jpeg\";\n\t\tcase \"gif\": return \"image/gif\";\n\t\tcase \"webp\": return \"image/webp\";\n\t\tcase \"avif\": return \"image/avif\";\n\t\tcase \"bmp\": return \"image/bmp\";\n\t\tcase \"tif\":\n\t\tcase \"tiff\": return \"image/tiff\";\n\t\tcase \"svg\": return \"image/svg+xml\";\n\t\tcase \"txt\": return \"text/plain\";\n\t\tcase \"xhtml\": return \"application/xhtml+xml\";\n\t\tcase \"mp3\": return \"audio/mpeg\";\n\t\tcase \"m4a\":\n\t\tcase \"m4b\": return \"audio/mp4\";\n\t\tcase \"aac\": return \"audio/aac\";\n\t\tcase \"ogg\":\n\t\tcase \"oga\": return \"audio/ogg\";\n\t\tcase \"wav\": return \"audio/wav\";\n\t\tcase \"flac\": return \"audio/flac\";\n\t\tcase \"opus\": return \"audio/opus\";\n\t}\n}, o = ({ mimeType: e, uri: t }) => (e ?? a(t ?? \"\"))?.startsWith(\"application/xhtml+xml\"), s = (e) => e.startsWith(\"image/\") || e.startsWith(\"audio/\") || e.startsWith(\"video/\"), c = (e) => {\n\tif (!e.length) return;\n\tlet t = e.indexOf(\";\");\n\treturn t >= 0 ? e.substring(0, t) : e;\n}, l = /^[A-Za-z0-9_][A-Za-z0-9_.-]*$/, u = /^[A-Za-z0-9_]/, d = /^xml/i, f = /[^A-Za-z0-9_.-]+/g, p = \"_\", m = (e) => e.replace(/^_+|_+$/g, \"\"), h = (e) => m(e.trim().replaceAll(\"/\", \"_\").replace(f, \"_\")), g = (e) => {\n\tif (l.test(e) && !d.test(e)) return e;\n\tlet t = h(e), n = t && !d.test(t) ? t : `${p}${t}`;\n\treturn u.test(n) ? n : `${p}${n}`;\n}, _ = (e, t) => {\n\tlet n = g(e);\n\tif (!t.has(n)) return t.add(n), n;\n\tlet r = 2, i = `${n}-${r}`;\n\tfor (; t.has(i);) r += 1, i = `${n}-${r}`;\n\treturn t.add(i), i;\n}, v = () => {\n\tlet e = /* @__PURE__ */ new Set();\n\treturn (t) => _(t, e);\n}, y = (e) => {\n\tlet t = e.pageSpreadLeft === !0;\n\tif (t !== (e.pageSpreadRight === !0)) return t ? \"left\" : \"right\";\n}, b = (e, t, n) => {\n\tif (Object.is(e, t)) return !0;\n\tif (typeof e != \"object\" || !e || typeof t != \"object\" || !t) return !1;\n\tlet r = Object.keys(e), i = Object.keys(t);\n\tif (r.length !== i.length) return !1;\n\tlet a = n?.customEqual ?? Object.is, o = e, s = t;\n\tfor (let e of r) if (!Object.hasOwn(s, e) || !a(o[e], s[e])) return !1;\n\treturn !0;\n}, x = (e, t) => e.reduce((e, n) => {\n\tlet r = t(n);\n\treturn e[r] || (e[r] = []), e[r].push(n), e;\n}, {});\nfunction S(e, t) {\n\tlet n = { ...e };\n\tfor (let r in t) if (Object.hasOwn(t, r)) {\n\t\tlet i = t[r];\n\t\t(i !== void 0 || !(r in e)) && (n[r] = i);\n\t}\n\treturn n;\n}\n//#endregion\n//#region src/report.ts\nfunction C() {\n\tlet e = globalThis.__PROSE_READER_DEBUG;\n\treturn e === !0 || e === \"true\";\n}\nvar w = (e, t) => typeof e == \"boolean\" ? {\n\tenabled: e,\n\toptions: t\n} : {\n\tenabled: e?.enabled,\n\toptions: e ?? t\n}, T = (e) => e.at(-1)?.color, E = (e) => {\n\tif (!e.length) return;\n\tif (!e.some((e) => e.color)) return [e.map((e) => e.label).join(\" \")];\n\tlet t = \"\", n = [];\n\tfor (let r of e) t += `%c${t ? ` ${r.label}` : r.label}`, n.push(r.color ? `color: ${r.color}` : \"\");\n\treturn [t, ...n];\n}, D = (e = [], t = C()) => {\n\tlet n = t, r = {\n\t\tenable: (e) => {\n\t\t\ta(e);\n\t\t},\n\t\tnamespace: (t, r, i) => {\n\t\t\tlet a = w(r, i), o = a.options?.color ?? T(e);\n\t\t\treturn D([...e, {\n\t\t\t\tlabel: `[${t}]`,\n\t\t\t\tcolor: o\n\t\t\t}], a.enabled ?? n);\n\t\t},\n\t\tisEnabled: () => n,\n\t\tdebug: () => {},\n\t\tinfo: () => {},\n\t\tlog: () => {},\n\t\tgroupCollapsed: () => {},\n\t\tgroupEnd: () => {},\n\t\tgetGroupArgs: (t) => {\n\t\t\tlet n = E(e);\n\t\t\tif (!n) return [t];\n\t\t\tlet [r, ...i] = n;\n\t\t\treturn [`${r} ${t}`, ...i];\n\t\t},\n\t\twarn: () => {},\n\t\terror: () => {}\n\t}, i = (t) => {\n\t\tif (!t) {\n\t\t\tr.debug = () => {}, r.info = () => {}, r.log = () => {}, r.groupCollapsed = () => {}, r.groupEnd = () => {}, r.warn = () => {}, r.error = () => {};\n\t\t\treturn;\n\t\t}\n\t\tlet n = E(e) ?? [];\n\t\tr.debug = Function.prototype.bind.call(console.debug, console, ...n), r.info = Function.prototype.bind.call(console.info, console, ...n), r.log = Function.prototype.bind.call(console.log, console, ...n), r.groupCollapsed = Function.prototype.bind.call(console.groupCollapsed, console), r.groupEnd = Function.prototype.bind.call(console.groupEnd, console), r.warn = Function.prototype.bind.call(console.warn, console, ...n), r.error = Function.prototype.bind.call(console.error, console, ...n);\n\t}, a = (e) => {\n\t\tn !== e && (n = e, i(n));\n\t};\n\treturn i(n), r;\n}, O = D(), k = \"prose-reader-resource-error\", A = (e, t) => {\n\tlet n = e.split(/(\\d+)/), r = t.split(/(\\d+)/);\n\tfor (let e = 0, t = n.length; e < t; e++) if (n[e] !== r[e]) return n[e]?.match(/\\d/) ? (n[e] || \"\") - +(r[e] || \"\") : (n[e] || \"\").localeCompare(r[e] || \"\");\n\treturn 1;\n}, j = (e) => e.endsWith(\"/\") ? e.slice(0, -1) : e, M = (e) => {\n\tlet t = j(e);\n\treturn t.substring(t.lastIndexOf(\"/\") + 1) || t;\n}, N = (e) => {\n\tlet t = e.lastIndexOf(\"/\");\n\treturn t >= 0 ? e.substring(0, t) : \"\";\n}, P = (e) => e.replaceAll(\"&\", \"&amp;\").replaceAll(\"\\\"\", \"&quot;\").replaceAll(\"'\", \"&apos;\").replaceAll(\"<\", \"&lt;\").replaceAll(\">\", \"&gt;\");\n//#endregion\nexport { k as PROSE_READER_RESOURCE_ERROR_INJECTED_META_NAME, O as Report, e as arrayEqual, _ as createUniqueXmlSafeId, g as createXmlSafeId, v as createXmlSafeIdFactory, a as detectMimeTypeFromName, P as escapeXmlAttributeValue, y as getItemSpreadPosition, i as getParentPath, N as getUriBasePath, M as getUriBasename, t as getUrlExtension, x as groupBy, s as isMediaContentMimeType, b as isShallowEqual, o as isXmlBasedMimeType, c as parseContentType, j as removeTrailingSlash, S as shallowMergeIfDefined, A as sortByTitleComparator, r as urlJoin };\n\n//# sourceMappingURL=index.js.map","{\n \"name\": \"@prose-reader/enhancer-search\",\n \"version\": \"1.344.0\",\n \"type\": \"module\",\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"files\": [\n \"/dist\"\n ],\n \"exports\": {\n \".\": {\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n }\n },\n \"scripts\": {\n \"start\": \"vite build --watch --mode development\",\n \"build\": \"tsc && vite build\",\n \"test\": \"vitest run --coverage\"\n },\n \"dependencies\": {\n \"@prose-reader/core\": \"^1.344.0\"\n },\n \"peerDependencies\": {\n \"rxjs\": \"*\"\n },\n \"gitHead\": \"4601e14dcacf50b2295cb343582a7ef2c7e1eedc\"\n}\n","import { Report } from \"@prose-reader/shared\"\nimport { name } from \"../package.json\"\n\nconst IS_DEBUG_ENABLED = true\n\nexport const report = Report.namespace(name, IS_DEBUG_ENABLED)\n","import type { Reader, SpineItem } from \"@prose-reader/core\"\nimport { type Observable, of } from \"rxjs\"\nimport type { ResultItem } from \"./types\"\n\nexport type SearchResult = ResultItem[]\n\n/**\n * Walk the subtree accumulating ranges for every match of `regexp`.\n *\n * A full-book search runs this over the rendered document of *every* spine\n * item, so the text-node loop below is the hot path (thousands of text nodes\n * per large chapter). Two things are hoisted out of it to keep the work\n * proportional to the number of matches rather than the number of nodes:\n * - the search regexp is compiled once by the caller and reused across every\n * node (only its `lastIndex` is reset), instead of recompiling per text node,\n * - matches are pushed into a single shared array instead of allocating a new\n * array at each node and spreading child results upward.\n */\nconst collectMatchingRanges = (\n node: Node,\n regexp: RegExp,\n matchLength: number,\n rangeList: Range[],\n) => {\n if (node.nodeName === `head`) return\n\n const nodeList = node.childNodes\n\n for (let i = 0; i < nodeList.length; i++) {\n const subNode = nodeList[i]\n\n if (!subNode) {\n continue\n }\n\n if (subNode.hasChildNodes()) {\n collectMatchingRanges(subNode, regexp, matchLength, rangeList)\n }\n\n if (subNode.nodeType === 3) {\n const content = (subNode as Text).data.toLowerCase()\n if (content) {\n let match: RegExpExecArray | null = null\n regexp.lastIndex = 0\n\n // biome-ignore lint/suspicious/noAssignInExpressions: TODO\n while ((match = regexp.exec(content)) !== null) {\n if (match.index >= 0 && subNode.ownerDocument) {\n const range = subNode.ownerDocument.createRange()\n range.setStart(subNode, match.index)\n range.setEnd(subNode, match.index + matchLength)\n\n rangeList.push(range)\n }\n }\n }\n }\n }\n}\n\nconst searchNodeContainingText = (node: Node, text: string) => {\n const rangeList: Range[] = []\n\n collectMatchingRanges(node, RegExp(`(${text})`, `gi`), text.length, rangeList)\n\n return rangeList\n}\n\nexport const searchInDocument = (\n reader: Reader,\n item: SpineItem,\n doc: Document,\n text: string,\n): Observable<SearchResult> => {\n const ranges = searchNodeContainingText(doc, text)\n\n const newResults = ranges.map((range) => {\n const cfi = reader.cfi.generateCfiFromRange(range, item.item)\n\n return {\n cfi,\n } satisfies ResultItem\n })\n\n return of(newResults)\n}\n","import { deferIdle, type Reader } from \"@prose-reader/core\"\nimport { defer, forkJoin, of } from \"rxjs\"\nimport { catchError, finalize, map, switchMap } from \"rxjs/operators\"\nimport { report } from \"./report\"\nimport type { SearchResult } from \"./search\"\nimport { searchInDocument } from \"./search\"\nimport type { ResultItem, SearchEnhancerAPI } from \"./types\"\n\nexport type { SearchEnhancerAPI, ResultItem, SearchResult }\n\n/**\n * Contract of search enhancer.\n *\n * - At best a result match should be navigable. It means the search needs to\n * be done on a rendered document. This is because rendering can differ from the original\n * item resource. A resource can be something non digestible and very specific (.pdf). The search\n * enhancer is agnostic and can only search into documents.\n */\nexport const searchEnhancer =\n <InheritOptions, InheritOutput extends Reader>(\n next: (options: InheritOptions) => InheritOutput,\n ) =>\n (options: InheritOptions): InheritOutput & SearchEnhancerAPI => {\n const reader = next(options)\n\n const searchForItem = (index: number, text: string) => {\n const item = reader.spineItemsManager.get(index)\n\n if (!item) {\n return of([])\n }\n\n return deferIdle(() => reader.renderHeadless(index)).pipe(\n switchMap((result) => {\n const { doc, release } = result || {}\n\n if (!doc) return of([])\n\n return deferIdle(() =>\n searchInDocument(reader, item, doc, text),\n ).pipe(\n finalize(() => {\n release?.()\n }),\n catchError((e) => {\n report.error(e)\n\n return of([])\n }),\n )\n }),\n )\n }\n\n const search = (text: string) =>\n defer(() => {\n if (text === ``) {\n return of([])\n }\n\n const searches$ =\n reader.context.manifest?.spineItems.map((_, index) =>\n searchForItem(index, text),\n ) || []\n\n return forkJoin([...searches$, of([])])\n }).pipe(\n map((results) => {\n const flattenedResults = results.flat()\n\n report.debug(\"results\", flattenedResults)\n\n return flattenedResults\n }),\n )\n\n return {\n ...reader,\n __PROSE_READER_ENHANCER_SEARCH: true,\n search: {\n search,\n },\n }\n }\n"],"mappings":"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"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../shared/dist/index.js","../package.json","../src/report.ts","../src/search.ts","../src/index.ts"],"sourcesContent":["//#region src/array.ts\nvar e = (e, t) => e === t || e.length === t.length && e.every((e, n) => e === t[n]), t = (e) => e.split(/[#?]/)[0]?.split(\".\").pop()?.trim() || \"\";\nfunction n(e) {\n\tlet t = [];\n\tif (e.length === 0) return \"\";\n\tif (typeof e[0] != \"string\") throw TypeError(`Url must be a string. Received ${e[0]}`);\n\te[0].match(/^[^/:]+:\\/*$/) && e.length > 1 && (e[0] = e.shift() + e[0]), e[0].match(/^file:\\/\\/\\//) ? e[0] = e[0].replace(/^([^/:]+):\\/*/, \"$1:///\") : e[0] = e[0].replace(/^([^/:]+):\\/*/, \"$1://\");\n\tfor (let n = 0; n < e.length; n++) {\n\t\tlet r = e[n];\n\t\tif (typeof r != \"string\") throw TypeError(`Url must be a string. Received ${r}`);\n\t\tr !== \"\" && (n > 0 && (r = r.replace(/^[/]+/, \"\")), r = n < e.length - 1 ? r.replace(/[/]+$/, \"\") : r.replace(/[/]+$/, \"/\"), t.push(r));\n\t}\n\tlet n = t.join(\"/\");\n\tn = n.replace(/\\/(\\?|&|#[^!])/g, \"$1\");\n\tlet r = n.split(\"?\");\n\treturn n = r.shift() + (r.length > 0 ? \"?\" : \"\") + r.join(\"&\"), n;\n}\nfunction r(...e) {\n\treturn n(Array.from(Array.isArray(e[0]) ? e[0] : e));\n}\nfunction i(e) {\n\tlet t = e.split(\"/\");\n\treturn t.pop(), t.join(\"/\");\n}\n//#endregion\n//#region src/contentType.ts\nvar a = (e) => {\n\tswitch (t(e).toLowerCase()) {\n\t\tcase \"png\": return \"image/png\";\n\t\tcase \"jpg\": return \"image/jpg\";\n\t\tcase \"jpeg\": return \"image/jpeg\";\n\t\tcase \"gif\": return \"image/gif\";\n\t\tcase \"webp\": return \"image/webp\";\n\t\tcase \"avif\": return \"image/avif\";\n\t\tcase \"bmp\": return \"image/bmp\";\n\t\tcase \"tif\":\n\t\tcase \"tiff\": return \"image/tiff\";\n\t\tcase \"svg\": return \"image/svg+xml\";\n\t\tcase \"txt\": return \"text/plain\";\n\t\tcase \"xhtml\": return \"application/xhtml+xml\";\n\t\tcase \"mp3\": return \"audio/mpeg\";\n\t\tcase \"m4a\":\n\t\tcase \"m4b\": return \"audio/mp4\";\n\t\tcase \"aac\": return \"audio/aac\";\n\t\tcase \"ogg\":\n\t\tcase \"oga\": return \"audio/ogg\";\n\t\tcase \"wav\": return \"audio/wav\";\n\t\tcase \"flac\": return \"audio/flac\";\n\t\tcase \"opus\": return \"audio/opus\";\n\t}\n}, o = ({ mimeType: e, uri: t }) => (e ?? a(t ?? \"\"))?.startsWith(\"application/xhtml+xml\"), s = (e) => e.startsWith(\"image/\") || e.startsWith(\"audio/\") || e.startsWith(\"video/\"), c = (e) => {\n\tif (!e.length) return;\n\tlet t = e.indexOf(\";\");\n\treturn t >= 0 ? e.substring(0, t) : e;\n}, l = /^[A-Za-z0-9_][A-Za-z0-9_.-]*$/, u = /^[A-Za-z0-9_]/, d = /^xml/i, f = /[^A-Za-z0-9_.-]+/g, p = \"_\", m = (e) => e.replace(/^_+|_+$/g, \"\"), h = (e) => m(e.trim().replaceAll(\"/\", \"_\").replace(f, \"_\")), g = (e) => {\n\tif (l.test(e) && !d.test(e)) return e;\n\tlet t = h(e), n = t && !d.test(t) ? t : `${p}${t}`;\n\treturn u.test(n) ? n : `${p}${n}`;\n}, _ = (e, t) => {\n\tlet n = g(e);\n\tif (!t.has(n)) return t.add(n), n;\n\tlet r = 2, i = `${n}-${r}`;\n\tfor (; t.has(i);) r += 1, i = `${n}-${r}`;\n\treturn t.add(i), i;\n}, v = () => {\n\tlet e = /* @__PURE__ */ new Set();\n\treturn (t) => _(t, e);\n}, y = (e) => {\n\tlet t = e.pageSpreadLeft === !0;\n\tif (t !== (e.pageSpreadRight === !0)) return t ? \"left\" : \"right\";\n}, b = (e, t, n) => {\n\tif (Object.is(e, t)) return !0;\n\tif (typeof e != \"object\" || !e || typeof t != \"object\" || !t) return !1;\n\tlet r = Object.keys(e), i = Object.keys(t);\n\tif (r.length !== i.length) return !1;\n\tlet a = n?.customEqual ?? Object.is, o = e, s = t;\n\tfor (let e of r) if (!Object.hasOwn(s, e) || !a(o[e], s[e])) return !1;\n\treturn !0;\n}, x = (e, t) => e.reduce((e, n) => {\n\tlet r = t(n);\n\treturn e[r] || (e[r] = []), e[r].push(n), e;\n}, {});\nfunction S(e, t) {\n\tlet n = { ...e };\n\tfor (let r in t) if (Object.hasOwn(t, r)) {\n\t\tlet i = t[r];\n\t\t(i !== void 0 || !(r in e)) && (n[r] = i);\n\t}\n\treturn n;\n}\n//#endregion\n//#region src/report.ts\nfunction C() {\n\tlet e = globalThis.__PROSE_READER_DEBUG;\n\treturn e === !0 || e === \"true\";\n}\nvar w = (e, t) => typeof e == \"boolean\" ? {\n\tenabled: e,\n\toptions: t\n} : {\n\tenabled: e?.enabled,\n\toptions: e ?? t\n}, T = (e) => e.at(-1)?.color, E = (e) => {\n\tif (!e.length) return;\n\tif (!e.some((e) => e.color)) return [e.map((e) => e.label).join(\" \")];\n\tlet t = \"\", n = [];\n\tfor (let r of e) t += `%c${t ? ` ${r.label}` : r.label}`, n.push(r.color ? `color: ${r.color}` : \"\");\n\treturn [t, ...n];\n}, D = (e = [], t = C()) => {\n\tlet n = t, r = {\n\t\tenable: (e) => {\n\t\t\ta(e);\n\t\t},\n\t\tnamespace: (t, r, i) => {\n\t\t\tlet a = w(r, i), o = a.options?.color ?? T(e);\n\t\t\treturn D([...e, {\n\t\t\t\tlabel: `[${t}]`,\n\t\t\t\tcolor: o\n\t\t\t}], a.enabled ?? n);\n\t\t},\n\t\tisEnabled: () => n,\n\t\tdebug: () => {},\n\t\tinfo: () => {},\n\t\tlog: () => {},\n\t\tgroupCollapsed: () => {},\n\t\tgroupEnd: () => {},\n\t\tgetGroupArgs: (t) => {\n\t\t\tlet n = E(e);\n\t\t\tif (!n) return [t];\n\t\t\tlet [r, ...i] = n;\n\t\t\treturn [`${r} ${t}`, ...i];\n\t\t},\n\t\twarn: () => {},\n\t\terror: () => {}\n\t}, i = (t) => {\n\t\tif (!t) {\n\t\t\tr.debug = () => {}, r.info = () => {}, r.log = () => {}, r.groupCollapsed = () => {}, r.groupEnd = () => {}, r.warn = () => {}, r.error = () => {};\n\t\t\treturn;\n\t\t}\n\t\tlet n = E(e) ?? [];\n\t\tr.debug = Function.prototype.bind.call(console.debug, console, ...n), r.info = Function.prototype.bind.call(console.info, console, ...n), r.log = Function.prototype.bind.call(console.log, console, ...n), r.groupCollapsed = Function.prototype.bind.call(console.groupCollapsed, console), r.groupEnd = Function.prototype.bind.call(console.groupEnd, console), r.warn = Function.prototype.bind.call(console.warn, console, ...n), r.error = Function.prototype.bind.call(console.error, console, ...n);\n\t}, a = (e) => {\n\t\tn !== e && (n = e, i(n));\n\t};\n\treturn i(n), r;\n}, O = D(), k = \"prose-reader-resource-error\", A = (e, t) => {\n\tlet n = e.split(/(\\d+)/), r = t.split(/(\\d+)/);\n\tfor (let e = 0, t = n.length; e < t; e++) if (n[e] !== r[e]) return n[e]?.match(/\\d/) ? (n[e] || \"\") - +(r[e] || \"\") : (n[e] || \"\").localeCompare(r[e] || \"\");\n\treturn 1;\n}, j = (e) => e.endsWith(\"/\") ? e.slice(0, -1) : e, M = (e) => {\n\tlet t = j(e);\n\treturn t.substring(t.lastIndexOf(\"/\") + 1) || t;\n}, N = (e) => {\n\tlet t = e.lastIndexOf(\"/\");\n\treturn t >= 0 ? e.substring(0, t) : \"\";\n}, P = (e) => e.replaceAll(\"&\", \"&amp;\").replaceAll(\"\\\"\", \"&quot;\").replaceAll(\"'\", \"&apos;\").replaceAll(\"<\", \"&lt;\").replaceAll(\">\", \"&gt;\");\n//#endregion\nexport { k as PROSE_READER_RESOURCE_ERROR_INJECTED_META_NAME, O as Report, e as arrayEqual, _ as createUniqueXmlSafeId, g as createXmlSafeId, v as createXmlSafeIdFactory, a as detectMimeTypeFromName, P as escapeXmlAttributeValue, y as getItemSpreadPosition, i as getParentPath, N as getUriBasePath, M as getUriBasename, t as getUrlExtension, x as groupBy, s as isMediaContentMimeType, b as isShallowEqual, o as isXmlBasedMimeType, c as parseContentType, j as removeTrailingSlash, S as shallowMergeIfDefined, A as sortByTitleComparator, r as urlJoin };\n\n//# sourceMappingURL=index.js.map","{\n \"name\": \"@prose-reader/enhancer-search\",\n \"version\": \"1.343.0\",\n \"type\": \"module\",\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"files\": [\n \"/dist\"\n ],\n \"exports\": {\n \".\": {\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n }\n },\n \"scripts\": {\n \"start\": \"vite build --watch --mode development\",\n \"build\": \"tsc && vite build\",\n \"test\": \"vitest run --coverage\"\n },\n \"dependencies\": {\n \"@prose-reader/core\": \"^1.343.0\"\n },\n \"peerDependencies\": {\n \"rxjs\": \"*\"\n },\n \"gitHead\": \"4601e14dcacf50b2295cb343582a7ef2c7e1eedc\"\n}\n","import { Report } from \"@prose-reader/shared\"\nimport { name } from \"../package.json\"\n\nconst IS_DEBUG_ENABLED = true\n\nexport const report = Report.namespace(name, IS_DEBUG_ENABLED)\n","import type { Reader, SpineItem } from \"@prose-reader/core\"\nimport { type Observable, of } from \"rxjs\"\nimport type { ResultItem } from \"./types\"\n\nexport type SearchResult = ResultItem[]\n\n/**\n * Walk the subtree accumulating ranges for every match of `regexp`.\n *\n * A full-book search runs this over the rendered document of *every* spine\n * item, so the text-node loop below is the hot path (thousands of text nodes\n * per large chapter). Two things are hoisted out of it to keep the work\n * proportional to the number of matches rather than the number of nodes:\n * - the search regexp is compiled once by the caller and reused across every\n * node (only its `lastIndex` is reset), instead of recompiling per text node,\n * - matches are pushed into a single shared array instead of allocating a new\n * array at each node and spreading child results upward.\n */\nconst collectMatchingRanges = (\n node: Node,\n regexp: RegExp,\n matchLength: number,\n rangeList: Range[],\n) => {\n if (node.nodeName === `head`) return\n\n const nodeList = node.childNodes\n\n for (let i = 0; i < nodeList.length; i++) {\n const subNode = nodeList[i]\n\n if (!subNode) {\n continue\n }\n\n if (subNode.hasChildNodes()) {\n collectMatchingRanges(subNode, regexp, matchLength, rangeList)\n }\n\n if (subNode.nodeType === 3) {\n const content = (subNode as Text).data.toLowerCase()\n if (content) {\n let match: RegExpExecArray | null = null\n regexp.lastIndex = 0\n\n // biome-ignore lint/suspicious/noAssignInExpressions: TODO\n while ((match = regexp.exec(content)) !== null) {\n if (match.index >= 0 && subNode.ownerDocument) {\n const range = subNode.ownerDocument.createRange()\n range.setStart(subNode, match.index)\n range.setEnd(subNode, match.index + matchLength)\n\n rangeList.push(range)\n }\n }\n }\n }\n }\n}\n\nconst searchNodeContainingText = (node: Node, text: string) => {\n const rangeList: Range[] = []\n\n collectMatchingRanges(node, RegExp(`(${text})`, `gi`), text.length, rangeList)\n\n return rangeList\n}\n\nexport const searchInDocument = (\n reader: Reader,\n item: SpineItem,\n doc: Document,\n text: string,\n): Observable<SearchResult> => {\n const ranges = searchNodeContainingText(doc, text)\n\n const newResults = ranges.map((range) => {\n const cfi = reader.cfi.generateCfiFromRange(range, item.item)\n\n return {\n cfi,\n } satisfies ResultItem\n })\n\n return of(newResults)\n}\n","import { deferIdle, type Reader } from \"@prose-reader/core\"\nimport { defer, forkJoin, of } from \"rxjs\"\nimport { catchError, finalize, map, switchMap } from \"rxjs/operators\"\nimport { report } from \"./report\"\nimport type { SearchResult } from \"./search\"\nimport { searchInDocument } from \"./search\"\nimport type { ResultItem, SearchEnhancerAPI } from \"./types\"\n\nexport type { SearchEnhancerAPI, ResultItem, SearchResult }\n\n/**\n * Contract of search enhancer.\n *\n * - At best a result match should be navigable. It means the search needs to\n * be done on a rendered document. This is because rendering can differ from the original\n * item resource. A resource can be something non digestible and very specific (.pdf). The search\n * enhancer is agnostic and can only search into documents.\n */\nexport const searchEnhancer =\n <InheritOptions, InheritOutput extends Reader>(\n next: (options: InheritOptions) => InheritOutput,\n ) =>\n (options: InheritOptions): InheritOutput & SearchEnhancerAPI => {\n const reader = next(options)\n\n const searchForItem = (index: number, text: string) => {\n const item = reader.spineItemsManager.get(index)\n\n if (!item) {\n return of([])\n }\n\n return deferIdle(() => reader.renderHeadless(index)).pipe(\n switchMap((result) => {\n const { doc, release } = result || {}\n\n if (!doc) return of([])\n\n return deferIdle(() =>\n searchInDocument(reader, item, doc, text),\n ).pipe(\n finalize(() => {\n release?.()\n }),\n catchError((e) => {\n report.error(e)\n\n return of([])\n }),\n )\n }),\n )\n }\n\n const search = (text: string) =>\n defer(() => {\n if (text === ``) {\n return of([])\n }\n\n const searches$ =\n reader.context.manifest?.spineItems.map((_, index) =>\n searchForItem(index, text),\n ) || []\n\n return forkJoin([...searches$, of([])])\n }).pipe(\n map((results) => {\n const flattenedResults = results.flat()\n\n report.debug(\"results\", flattenedResults)\n\n return flattenedResults\n }),\n )\n\n return {\n ...reader,\n __PROSE_READER_ENHANCER_SEARCH: true,\n search: {\n search,\n },\n }\n }\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../shared/dist/index.js","../package.json","../src/report.ts","../src/search.ts","../src/index.ts"],"sourcesContent":["//#region src/array.ts\nvar e = (e, t) => e === t || e.length === t.length && e.every((e, n) => e === t[n]), t = (e) => e.split(/[#?]/)[0]?.split(\".\").pop()?.trim() || \"\";\nfunction n(e) {\n\tlet t = [];\n\tif (e.length === 0) return \"\";\n\tif (typeof e[0] != \"string\") throw TypeError(`Url must be a string. Received ${e[0]}`);\n\te[0].match(/^[^/:]+:\\/*$/) && e.length > 1 && (e[0] = e.shift() + e[0]), e[0].match(/^file:\\/\\/\\//) ? e[0] = e[0].replace(/^([^/:]+):\\/*/, \"$1:///\") : e[0] = e[0].replace(/^([^/:]+):\\/*/, \"$1://\");\n\tfor (let n = 0; n < e.length; n++) {\n\t\tlet r = e[n];\n\t\tif (typeof r != \"string\") throw TypeError(`Url must be a string. Received ${r}`);\n\t\tr !== \"\" && (n > 0 && (r = r.replace(/^[/]+/, \"\")), r = n < e.length - 1 ? r.replace(/[/]+$/, \"\") : r.replace(/[/]+$/, \"/\"), t.push(r));\n\t}\n\tlet n = t.join(\"/\");\n\tn = n.replace(/\\/(\\?|&|#[^!])/g, \"$1\");\n\tlet r = n.split(\"?\");\n\treturn n = r.shift() + (r.length > 0 ? \"?\" : \"\") + r.join(\"&\"), n;\n}\nfunction r(...e) {\n\treturn n(Array.from(Array.isArray(e[0]) ? e[0] : e));\n}\nfunction i(e) {\n\tlet t = e.split(\"/\");\n\treturn t.pop(), t.join(\"/\");\n}\n//#endregion\n//#region src/contentType.ts\nvar a = (e) => {\n\tswitch (t(e).toLowerCase()) {\n\t\tcase \"png\": return \"image/png\";\n\t\tcase \"jpg\": return \"image/jpg\";\n\t\tcase \"jpeg\": return \"image/jpeg\";\n\t\tcase \"gif\": return \"image/gif\";\n\t\tcase \"webp\": return \"image/webp\";\n\t\tcase \"avif\": return \"image/avif\";\n\t\tcase \"bmp\": return \"image/bmp\";\n\t\tcase \"tif\":\n\t\tcase \"tiff\": return \"image/tiff\";\n\t\tcase \"svg\": return \"image/svg+xml\";\n\t\tcase \"txt\": return \"text/plain\";\n\t\tcase \"xhtml\": return \"application/xhtml+xml\";\n\t\tcase \"mp3\": return \"audio/mpeg\";\n\t\tcase \"m4a\":\n\t\tcase \"m4b\": return \"audio/mp4\";\n\t\tcase \"aac\": return \"audio/aac\";\n\t\tcase \"ogg\":\n\t\tcase \"oga\": return \"audio/ogg\";\n\t\tcase \"wav\": return \"audio/wav\";\n\t\tcase \"flac\": return \"audio/flac\";\n\t\tcase \"opus\": return \"audio/opus\";\n\t}\n}, o = ({ mimeType: e, uri: t }) => (e ?? a(t ?? \"\"))?.startsWith(\"application/xhtml+xml\"), s = (e) => e.startsWith(\"image/\") || e.startsWith(\"audio/\") || e.startsWith(\"video/\"), c = (e) => {\n\tif (!e.length) return;\n\tlet t = e.indexOf(\";\");\n\treturn t >= 0 ? e.substring(0, t) : e;\n}, l = /^[A-Za-z0-9_][A-Za-z0-9_.-]*$/, u = /^[A-Za-z0-9_]/, d = /^xml/i, f = /[^A-Za-z0-9_.-]+/g, p = \"_\", m = (e) => e.replace(/^_+|_+$/g, \"\"), h = (e) => m(e.trim().replaceAll(\"/\", \"_\").replace(f, \"_\")), g = (e) => {\n\tif (l.test(e) && !d.test(e)) return e;\n\tlet t = h(e), n = t && !d.test(t) ? t : `${p}${t}`;\n\treturn u.test(n) ? n : `${p}${n}`;\n}, _ = (e, t) => {\n\tlet n = g(e);\n\tif (!t.has(n)) return t.add(n), n;\n\tlet r = 2, i = `${n}-${r}`;\n\tfor (; t.has(i);) r += 1, i = `${n}-${r}`;\n\treturn t.add(i), i;\n}, v = () => {\n\tlet e = /* @__PURE__ */ new Set();\n\treturn (t) => _(t, e);\n}, y = (e) => {\n\tlet t = e.pageSpreadLeft === !0;\n\tif (t !== (e.pageSpreadRight === !0)) return t ? \"left\" : \"right\";\n}, b = (e, t, n) => {\n\tif (Object.is(e, t)) return !0;\n\tif (typeof e != \"object\" || !e || typeof t != \"object\" || !t) return !1;\n\tlet r = Object.keys(e), i = Object.keys(t);\n\tif (r.length !== i.length) return !1;\n\tlet a = n?.customEqual ?? Object.is, o = e, s = t;\n\tfor (let e of r) if (!Object.hasOwn(s, e) || !a(o[e], s[e])) return !1;\n\treturn !0;\n}, x = (e, t) => e.reduce((e, n) => {\n\tlet r = t(n);\n\treturn e[r] || (e[r] = []), e[r].push(n), e;\n}, {});\nfunction S(e, t) {\n\tlet n = { ...e };\n\tfor (let r in t) if (Object.hasOwn(t, r)) {\n\t\tlet i = t[r];\n\t\t(i !== void 0 || !(r in e)) && (n[r] = i);\n\t}\n\treturn n;\n}\n//#endregion\n//#region src/report.ts\nfunction C() {\n\tlet e = globalThis.__PROSE_READER_DEBUG;\n\treturn e === !0 || e === \"true\";\n}\nvar w = (e, t) => typeof e == \"boolean\" ? {\n\tenabled: e,\n\toptions: t\n} : {\n\tenabled: e?.enabled,\n\toptions: e ?? t\n}, T = (e) => e.at(-1)?.color, E = (e) => {\n\tif (!e.length) return;\n\tif (!e.some((e) => e.color)) return [e.map((e) => e.label).join(\" \")];\n\tlet t = \"\", n = [];\n\tfor (let r of e) t += `%c${t ? ` ${r.label}` : r.label}`, n.push(r.color ? `color: ${r.color}` : \"\");\n\treturn [t, ...n];\n}, D = (e = [], t = C()) => {\n\tlet n = t, r = {\n\t\tenable: (e) => {\n\t\t\ta(e);\n\t\t},\n\t\tnamespace: (t, r, i) => {\n\t\t\tlet a = w(r, i), o = a.options?.color ?? T(e);\n\t\t\treturn D([...e, {\n\t\t\t\tlabel: `[${t}]`,\n\t\t\t\tcolor: o\n\t\t\t}], a.enabled ?? n);\n\t\t},\n\t\tisEnabled: () => n,\n\t\tdebug: () => {},\n\t\tinfo: () => {},\n\t\tlog: () => {},\n\t\tgroupCollapsed: () => {},\n\t\tgroupEnd: () => {},\n\t\tgetGroupArgs: (t) => {\n\t\t\tlet n = E(e);\n\t\t\tif (!n) return [t];\n\t\t\tlet [r, ...i] = n;\n\t\t\treturn [`${r} ${t}`, ...i];\n\t\t},\n\t\twarn: () => {},\n\t\terror: () => {}\n\t}, i = (t) => {\n\t\tif (!t) {\n\t\t\tr.debug = () => {}, r.info = () => {}, r.log = () => {}, r.groupCollapsed = () => {}, r.groupEnd = () => {}, r.warn = () => {}, r.error = () => {};\n\t\t\treturn;\n\t\t}\n\t\tlet n = E(e) ?? [];\n\t\tr.debug = Function.prototype.bind.call(console.debug, console, ...n), r.info = Function.prototype.bind.call(console.info, console, ...n), r.log = Function.prototype.bind.call(console.log, console, ...n), r.groupCollapsed = Function.prototype.bind.call(console.groupCollapsed, console), r.groupEnd = Function.prototype.bind.call(console.groupEnd, console), r.warn = Function.prototype.bind.call(console.warn, console, ...n), r.error = Function.prototype.bind.call(console.error, console, ...n);\n\t}, a = (e) => {\n\t\tn !== e && (n = e, i(n));\n\t};\n\treturn i(n), r;\n}, O = D(), k = \"prose-reader-resource-error\", A = (e, t) => {\n\tlet n = e.split(/(\\d+)/), r = t.split(/(\\d+)/);\n\tfor (let e = 0, t = n.length; e < t; e++) if (n[e] !== r[e]) return n[e]?.match(/\\d/) ? (n[e] || \"\") - +(r[e] || \"\") : (n[e] || \"\").localeCompare(r[e] || \"\");\n\treturn 1;\n}, j = (e) => e.endsWith(\"/\") ? e.slice(0, -1) : e, M = (e) => {\n\tlet t = j(e);\n\treturn t.substring(t.lastIndexOf(\"/\") + 1) || t;\n}, N = (e) => {\n\tlet t = e.lastIndexOf(\"/\");\n\treturn t >= 0 ? e.substring(0, t) : \"\";\n}, P = (e) => e.replaceAll(\"&\", \"&amp;\").replaceAll(\"\\\"\", \"&quot;\").replaceAll(\"'\", \"&apos;\").replaceAll(\"<\", \"&lt;\").replaceAll(\">\", \"&gt;\");\n//#endregion\nexport { k as PROSE_READER_RESOURCE_ERROR_INJECTED_META_NAME, O as Report, e as arrayEqual, _ as createUniqueXmlSafeId, g as createXmlSafeId, v as createXmlSafeIdFactory, a as detectMimeTypeFromName, P as escapeXmlAttributeValue, y as getItemSpreadPosition, i as getParentPath, N as getUriBasePath, M as getUriBasename, t as getUrlExtension, x as groupBy, s as isMediaContentMimeType, b as isShallowEqual, o as isXmlBasedMimeType, c as parseContentType, j as removeTrailingSlash, S as shallowMergeIfDefined, A as sortByTitleComparator, r as urlJoin };\n\n//# sourceMappingURL=index.js.map","{\n \"name\": \"@prose-reader/enhancer-search\",\n \"version\": \"1.344.0\",\n \"type\": \"module\",\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"files\": [\n \"/dist\"\n ],\n \"exports\": {\n \".\": {\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n }\n },\n \"scripts\": {\n \"start\": \"vite build --watch --mode development\",\n \"build\": \"tsc && vite build\",\n \"test\": \"vitest run --coverage\"\n },\n \"dependencies\": {\n \"@prose-reader/core\": \"^1.344.0\"\n },\n \"peerDependencies\": {\n \"rxjs\": \"*\"\n },\n \"gitHead\": \"4601e14dcacf50b2295cb343582a7ef2c7e1eedc\"\n}\n","import { Report } from \"@prose-reader/shared\"\nimport { name } from \"../package.json\"\n\nconst IS_DEBUG_ENABLED = true\n\nexport const report = Report.namespace(name, IS_DEBUG_ENABLED)\n","import type { Reader, SpineItem } from \"@prose-reader/core\"\nimport { type Observable, of } from \"rxjs\"\nimport type { ResultItem } from \"./types\"\n\nexport type SearchResult = ResultItem[]\n\n/**\n * Walk the subtree accumulating ranges for every match of `regexp`.\n *\n * A full-book search runs this over the rendered document of *every* spine\n * item, so the text-node loop below is the hot path (thousands of text nodes\n * per large chapter). Two things are hoisted out of it to keep the work\n * proportional to the number of matches rather than the number of nodes:\n * - the search regexp is compiled once by the caller and reused across every\n * node (only its `lastIndex` is reset), instead of recompiling per text node,\n * - matches are pushed into a single shared array instead of allocating a new\n * array at each node and spreading child results upward.\n */\nconst collectMatchingRanges = (\n node: Node,\n regexp: RegExp,\n matchLength: number,\n rangeList: Range[],\n) => {\n if (node.nodeName === `head`) return\n\n const nodeList = node.childNodes\n\n for (let i = 0; i < nodeList.length; i++) {\n const subNode = nodeList[i]\n\n if (!subNode) {\n continue\n }\n\n if (subNode.hasChildNodes()) {\n collectMatchingRanges(subNode, regexp, matchLength, rangeList)\n }\n\n if (subNode.nodeType === 3) {\n const content = (subNode as Text).data.toLowerCase()\n if (content) {\n let match: RegExpExecArray | null = null\n regexp.lastIndex = 0\n\n // biome-ignore lint/suspicious/noAssignInExpressions: TODO\n while ((match = regexp.exec(content)) !== null) {\n if (match.index >= 0 && subNode.ownerDocument) {\n const range = subNode.ownerDocument.createRange()\n range.setStart(subNode, match.index)\n range.setEnd(subNode, match.index + matchLength)\n\n rangeList.push(range)\n }\n }\n }\n }\n }\n}\n\nconst searchNodeContainingText = (node: Node, text: string) => {\n const rangeList: Range[] = []\n\n collectMatchingRanges(node, RegExp(`(${text})`, `gi`), text.length, rangeList)\n\n return rangeList\n}\n\nexport const searchInDocument = (\n reader: Reader,\n item: SpineItem,\n doc: Document,\n text: string,\n): Observable<SearchResult> => {\n const ranges = searchNodeContainingText(doc, text)\n\n const newResults = ranges.map((range) => {\n const cfi = reader.cfi.generateCfiFromRange(range, item.item)\n\n return {\n cfi,\n } satisfies ResultItem\n })\n\n return of(newResults)\n}\n","import { deferIdle, type Reader } from \"@prose-reader/core\"\nimport { defer, forkJoin, of } from \"rxjs\"\nimport { catchError, finalize, map, switchMap } from \"rxjs/operators\"\nimport { report } from \"./report\"\nimport type { SearchResult } from \"./search\"\nimport { searchInDocument } from \"./search\"\nimport type { ResultItem, SearchEnhancerAPI } from \"./types\"\n\nexport type { SearchEnhancerAPI, ResultItem, SearchResult }\n\n/**\n * Contract of search enhancer.\n *\n * - At best a result match should be navigable. It means the search needs to\n * be done on a rendered document. This is because rendering can differ from the original\n * item resource. A resource can be something non digestible and very specific (.pdf). The search\n * enhancer is agnostic and can only search into documents.\n */\nexport const searchEnhancer =\n <InheritOptions, InheritOutput extends Reader>(\n next: (options: InheritOptions) => InheritOutput,\n ) =>\n (options: InheritOptions): InheritOutput & SearchEnhancerAPI => {\n const reader = next(options)\n\n const searchForItem = (index: number, text: string) => {\n const item = reader.spineItemsManager.get(index)\n\n if (!item) {\n return of([])\n }\n\n return deferIdle(() => reader.renderHeadless(index)).pipe(\n switchMap((result) => {\n const { doc, release } = result || {}\n\n if (!doc) return of([])\n\n return deferIdle(() =>\n searchInDocument(reader, item, doc, text),\n ).pipe(\n finalize(() => {\n release?.()\n }),\n catchError((e) => {\n report.error(e)\n\n return of([])\n }),\n )\n }),\n )\n }\n\n const search = (text: string) =>\n defer(() => {\n if (text === ``) {\n return of([])\n }\n\n const searches$ =\n reader.context.manifest?.spineItems.map((_, index) =>\n searchForItem(index, text),\n ) || []\n\n return forkJoin([...searches$, of([])])\n }).pipe(\n map((results) => {\n const flattenedResults = results.flat()\n\n report.debug(\"results\", flattenedResults)\n\n return flattenedResults\n }),\n )\n\n return {\n ...reader,\n __PROSE_READER_ENHANCER_SEARCH: true,\n search: {\n search,\n },\n }\n }\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prose-reader/enhancer-search",
3
- "version": "1.344.0",
3
+ "version": "1.345.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -20,10 +20,10 @@
20
20
  "test": "vitest run --coverage"
21
21
  },
22
22
  "dependencies": {
23
- "@prose-reader/core": "^1.344.0"
23
+ "@prose-reader/core": "^1.345.0"
24
24
  },
25
25
  "peerDependencies": {
26
26
  "rxjs": "*"
27
27
  },
28
- "gitHead": "3eac02f8c2fca1f9900d411ed573ab9a281731c0"
28
+ "gitHead": "f2f6e09d604f1f8e539d01ddd70c6a799c9d82cd"
29
29
  }