diff --git a/web/js/autocomplete.js b/web/js/autocomplete.js index 638cc05..98d11bf 100644 --- a/web/js/autocomplete.js +++ b/web/js/autocomplete.js @@ -106,56 +106,98 @@ function searchCompletionCandidates(textareaElement) { const sources = getEnabledTagSourceInPriorityOrder(); for (const source of sources) { - // Search in sortedTags (already sorted by count) - for (const tagData of autoCompleteData[source].sortedTags) { - let matched = false; - let isExactMatch = false; - let matchedAlias = null; + if (settingValues.useFastSearch && autoCompleteData[source].flexSearchIndex) { + const searchResults = autoCompleteData[source].flexSearchIndex.search(partialTag, { + limit: settingValues.maxSuggestions * autoCompleteData[source].flexSearchLimitMultiplier, + suggest: false, + cache: true, + }); - // Check primary tag against all variations for exact/partial match - const tagMatch = matchWord(tagData.tag, queryVariations); - matched = tagMatch.matched; - isExactMatch = tagMatch.isExactMatch; - - // If primary tag didn't match, check aliases against all variations - if (!matched && tagData.alias && Array.isArray(tagData.alias) && tagData.alias.length > 0) { - for (const alias of tagData.alias) { - const lowerAlias = alias.toLowerCase(); - const aliasMatch = matchWord(lowerAlias, queryVariations); - if (aliasMatch.matched) { - matched = true; - isExactMatch = aliasMatch.isExactMatch; - matchedAlias = alias; - break; - } + let result = []; + result = searchResults.map((index) => { + return autoCompleteData[source].flexSearchMapping[index]; + }); + result = [...new Set(result)]; + result = result.sort((a, b) => { + const aTag = autoCompleteData[source].sortedTags[a]; + const bTag = autoCompleteData[source].sortedTags[b]; + if (matchWord(bTag.tag, queryVariations).isExactMatch) { + return 999999999999; } + if (matchWord(aTag.tag, queryVariations).isExactMatch) { + return -999999999999; + } + if (bTag.alias && bTag.alias.some(alias => matchWord(alias, queryVariations).isExactMatch)) { + return 999999999999; + } + if (aTag.alias && aTag.alias.some(alias => matchWord(alias, queryVariations).isExactMatch)) { + return -999999999999; + } + return a - b; + }); + result = result.slice(0, Math.min(result.length, settingValues.maxSuggestions)); + result = result.map((index) => { + return autoCompleteData[source].sortedTags[index]; + }); + + if (settingValues._logprocessingTime) { + const endTime = performance.now(); + const duration = endTime - startTime; + console.debug(`[Autocomplete-Plus] Fast Search for "${partialTag}" in ${source} took ${duration.toFixed(2)}ms. Found ${result.length} candidates within ${searchResults.length} searches with aliases.`); } + return result; + } else { + // Search in sortedTags (already sorted by count) + for (const tagData of autoCompleteData[source].sortedTags) { + let matched = false; + let isExactMatch = false; + let matchedAlias = null; - const tagSetKey = tagData.tag; + // Check primary tag against all variations for exact/partial match + const tagMatch = matchWord(tagData.tag, queryVariations); + matched = tagMatch.matched; + isExactMatch = tagMatch.isExactMatch; - // Add candidate if matched and not already added - if (matched && !addedTags.has(tagSetKey)) { - // Add to exact matches or partial matches based on match type - if (isExactMatch) { - exactMatches.push(tagData); - } else { - partialMatches.push(tagData); + // If primary tag didn't match, check aliases against all variations + if (!matched && tagData.alias && Array.isArray(tagData.alias) && tagData.alias.length > 0) { + for (const alias of tagData.alias) { + const lowerAlias = alias.toLowerCase(); + const aliasMatch = matchWord(lowerAlias, queryVariations); + if (aliasMatch.matched) { + matched = true; + isExactMatch = aliasMatch.isExactMatch; + matchedAlias = alias; + break; + } + } } - addedTags.add(tagSetKey); + const tagSetKey = tagData.tag; - // Check if we've reached the maximum suggestions limit combining both arrays - if (exactMatches.length + partialMatches.length >= settingValues.maxSuggestions) { - // Return the combined results, prioritizing exact matches - const result = [...exactMatches, ...partialMatches].slice(0, settingValues.maxSuggestions); - - if (settingValues._logprocessingTime) { - const endTime = performance.now(); - const duration = endTime - startTime; - console.debug(`[Autocomplete-Plus] Search for "${partialTag}" took ${duration.toFixed(2)}ms. Found ${result.length} candidates (max reached).`); + // Add candidate if matched and not already added + if (matched && !addedTags.has(tagSetKey)) { + // Add to exact matches or partial matches based on match type + if (isExactMatch) { + exactMatches.push(tagData); + } else { + partialMatches.push(tagData); } - return result; // Early exit + addedTags.add(tagSetKey); + + // Check if we've reached the maximum suggestions limit combining both arrays + if (exactMatches.length + partialMatches.length >= settingValues.maxSuggestions) { + // Return the combined results, prioritizing exact matches + const result = [...exactMatches, ...partialMatches].slice(0, settingValues.maxSuggestions); + + if (settingValues._logprocessingTime) { + const endTime = performance.now(); + const duration = endTime - startTime; + console.debug(`[Autocomplete-Plus] Search for "${partialTag}" took ${duration.toFixed(2)}ms. Found ${result.length} candidates (max reached).`); + } + + return result; // Early exit + } } } } @@ -921,4 +963,4 @@ export class AutocompleteEventHandler { */ handleClick(event) { } -} \ No newline at end of file +} diff --git a/web/js/data.js b/web/js/data.js index cd1e4f5..d3aa762 100644 --- a/web/js/data.js +++ b/web/js/data.js @@ -1,3 +1,4 @@ +import { Charset, Index } from './thirdparty/flexsearch.bundle.module.min.js' import { settingValues, updateMaxTagLength } from "./settings.js"; // --- Constants --- @@ -63,6 +64,16 @@ export class TagData { class AutocompleteData { constructor() { + /** @type {Index} */ + this.flexSearchIndex = null; + + /** @type {number[]} */ + this.flexSearchMapping = []; + + /** @type {number} */ + // The actual number will be calculated later when loading CSV files + this.flexSearchLimitMultiplier = 10; + /** @type {TagData[]} */ this.sortedTags = []; @@ -189,6 +200,57 @@ async function loadTags(csvUrl, siteName) { } } +/** + * Build FlexSearch index for the given site name. + * @param {string} siteName + */ +async function buildFlexSearchIndex(siteName) { + try { + if (autoCompleteData[siteName].sortedTags.length === 0) { + return; + } + + const index = new Index({ + tokenize: "bidirectional", + }); + + let startIdx = 0; + let maxCountOfAlias = 0; + const startTime = performance.now(); + function processChunkTasks() { + const chunkSize = 1000; + const end = Math.min(startIdx + chunkSize, autoCompleteData[siteName].sortedTags.length); + for (; startIdx < end; startIdx++) { + const tagData = autoCompleteData[siteName].sortedTags[startIdx]; + + index.add(autoCompleteData[siteName].flexSearchMapping.length, tagData.tag); + autoCompleteData[siteName].flexSearchMapping.push(startIdx); + + tagData.alias.forEach(alias => { + index.add(autoCompleteData[siteName].flexSearchMapping.length, alias); + autoCompleteData[siteName].flexSearchMapping.push(startIdx); + }) + + maxCountOfAlias = Math.max(maxCountOfAlias, tagData.alias.length); + } + + if (startIdx < autoCompleteData[siteName].sortedTags.length) { + setTimeout(processChunkTasks, 0); + // console.log(`[Autocomplete-Plus] Current porcess: ${startIdx}`); + } else { + const endTime = performance.now(); + const duration = endTime - startTime; + autoCompleteData[siteName].flexSearchIndex = index; + autoCompleteData[siteName].flexSearchLimitMultiplier = Math.min(10, maxCountOfAlias + 1); + console.debug(`[Autocomplete-Plus] Building ${autoCompleteData[siteName].sortedTags.length} index for ${siteName} took ${duration.toFixed(2)}ms.`); + } + } + processChunkTasks(); + } catch (error) { + console.error(`[Autocomplete-Plus] Failed to building flexSearch index`, error); + } +} + /** * Loads co-occurrence data from a single CSV file. * @param {string} csvUrl - The URL of the CSV file to load. @@ -376,12 +438,17 @@ export async function initializeData(csvListData, source) { // Now, execute all promise factories and wait for their completion. // The actual loading (fetch calls) will start when the factories are invoked here. await Promise.all([ - Promise.all(tagsLoadPromiseFactories.map(factory => factory())).then(() => { - const endTime = performance.now(); - if (csvListData[source].base_tags) { - console.log(`[Autocomplete-Plus] "${source}" Tags loading complete in ${(endTime - startTime).toFixed(2)}ms`); - } - }), + Promise.all(tagsLoadPromiseFactories.map(factory => factory())) + .then(() => { + // Build FlexSearch index after tags are loaded + return buildFlexSearchIndex(source); + }) + .then(() => { + const endTime = performance.now(); + if (csvListData[source].base_tags) { + console.log(`[Autocomplete-Plus] "${source}" Tags loading complete in ${(endTime - startTime).toFixed(2)}ms`); + } + }), Promise.all(cooccurrenceLoadPromiseFactories.map(factory => factory())).then(() => { const endTime = performance.now(); if (csvListData[source].base_cooccurrence) { diff --git a/web/js/main.js b/web/js/main.js index 376a2cc..b99dd10 100644 --- a/web/js/main.js +++ b/web/js/main.js @@ -286,6 +286,16 @@ app.registerExtension({ } }, // --- Autocomplete Settings --- + { + id: id + ".use_fast_search", + name: "Use Fast Search", + type: "boolean", + defaultValue: false, + category: [name, "Autocompletion", "Use Fast Search"], + onChange: (newVal, oldVal) => { + settingValues.useFastSearch = newVal; + } + }, { id: id + ".max_suggestions", name: "Max suggestions", diff --git a/web/js/settings.js b/web/js/settings.js index 4342852..669a5f2 100644 --- a/web/js/settings.js +++ b/web/js/settings.js @@ -7,6 +7,7 @@ export const settingValues = { // Autocomplete feature settings enabled: true, maxSuggestions: 10, + useFastSearch: false, // Related tags feature settings enableRelatedTags: true, diff --git a/web/js/thirdparty/flexsearch.bundle.module.min.js b/web/js/thirdparty/flexsearch.bundle.module.min.js new file mode 100644 index 0000000..10a4fda --- /dev/null +++ b/web/js/thirdparty/flexsearch.bundle.module.min.js @@ -0,0 +1,106 @@ +/**! + * FlexSearch.js v0.8.200 (Bundle/Module) + * Author and Copyright: Thomas Wilkerling + * Licence: Apache-2.0 + * Hosted by Nextapps GmbH + * https://github.com/nextapps-de/flexsearch + */ +var w;function H(a,c,b){const e=typeof b,d=typeof a;if("undefined"!==e){if("undefined"!==d){if(b){if("function"===d&&e===d)return function(h){return a(b(h))};c=a.constructor;if(c===b.constructor){if(c===Array)return b.concat(a);if(c===Map){var f=new Map(b);for(var g of a)f.set(g[0],g[1]);return f}if(c===Set){g=new Set(b);for(f of a.values())g.add(f);return g}}}return a}return b}return"undefined"===d?c:a}function aa(a,c){return"undefined"===typeof a?c:a}function I(){return Object.create(null)} +function M(a){return"string"===typeof a}function ba(a){return"object"===typeof a}function ca(a){const c=[];for(const b of a.keys())c.push(b);return c}function ea(a,c){if(M(c))a=a[c];else for(let b=0;a&&b"a1a".split(b).length; +this.numeric=H(a.numeric,e)}else{try{this.split=H(this.split,fa)}catch(d){this.split=/\s+/}this.numeric=H(a.numeric,H(this.numeric,!0))}this.prepare=H(a.prepare,null,this.prepare);this.finalize=H(a.finalize,null,this.finalize);b=a.filter;this.filter="function"===typeof b?b:H(b&&new Set(b),null,this.filter);this.dedupe=H(a.dedupe,!0,this.dedupe);this.matcher=H((b=a.matcher)&&new Map(b),null,this.matcher);this.mapper=H((b=a.mapper)&&new Map(b),null,this.mapper);this.stemmer=H((b=a.stemmer)&&new Map(b), +null,this.stemmer);this.replacer=H(a.replacer,null,this.replacer);this.minlength=H(a.minlength,1,this.minlength);this.maxlength=H(a.maxlength,1024,this.maxlength);this.rtl=H(a.rtl,!1,this.rtl);if(this.cache=b=H(a.cache,!0,this.cache))this.I=null,this.R="number"===typeof b?b:2E5,this.B=new Map,this.H=new Map,this.M=this.L=128;this.h="";this.N=null;this.A="";this.O=null;if(this.matcher)for(const d of this.matcher.keys())this.h+=(this.h?"|":"")+d;if(this.stemmer)for(const d of this.stemmer.keys())this.A+= +(this.A?"|":"")+d;return this};w.addStemmer=function(a,c){this.stemmer||(this.stemmer=new Map);this.stemmer.set(a,c);this.A+=(this.A?"|":"")+a;this.O=null;this.cache&&Q(this);return this};w.addFilter=function(a){"function"===typeof a?this.filter=a:(this.filter||(this.filter=new Set),this.filter.add(a));this.cache&&Q(this);return this}; +w.addMapper=function(a,c){if("object"===typeof a)return this.addReplacer(a,c);if(1a.length&&(this.dedupe||this.mapper))return this.addMapper(a,c);this.matcher||(this.matcher=new Map);this.matcher.set(a,c);this.h+=(this.h?"|":"")+a;this.N=null;this.cache&&Q(this);return this}; +w.addReplacer=function(a,c){if("string"===typeof a)return this.addMatcher(a,c);this.replacer||(this.replacer=[]);this.replacer.push(a,c);this.cache&&Q(this);return this}; +w.encode=function(a,c){if(this.cache&&a.length<=this.L)if(this.I){if(this.B.has(a))return this.B.get(a)}else this.I=setTimeout(Q,50,this);this.normalize&&("function"===typeof this.normalize?a=this.normalize(a):a=ka?a.normalize("NFKD").replace(ka,"").toLowerCase():a.toLowerCase());this.prepare&&(a=this.prepare(a));this.numeric&&3this.maxlength)){if(c){if(d[l])continue;d[l]=1}else{if(f===l)continue;f=l}if(b)e.push(l);else if(!this.filter||("function"===typeof this.filter?this.filter(l):!this.filter.has(l))){if(this.cache&&l.length<=this.M)if(this.I){var k=this.H.get(l);if(k||""===k){k&&e.push(k);continue}}else this.I=setTimeout(Q,50,this);if(this.stemmer){this.O||(this.O=new RegExp("(?!^)("+ +this.A+")$"));let u;for(;u!==l&&2this.stemmer.get(p))}if(l&&(this.mapper||this.dedupe&&1this.matcher.get(u)));if(l&&this.replacer)for(k=0;l&&kthis.R&&(this.H.clear(),this.M=this.M/1.1|0));if(l){if(l!==n)if(c){if(d[l])continue;d[l]=1}else{if(g===l)continue;g=l}e.push(l)}}}this.finalize&&(e=this.finalize(e)||e);this.cache&&a.length<=this.L&&(this.B.set(a,e),this.B.size>this.R&&(this.B.clear(),this.L=this.L/1.1|0));return e};function Q(a){a.I=null;a.B.clear();a.H.clear()};function ma(a,c,b){b||(c||"object"!==typeof a?"object"===typeof c&&(b=c,c=0):b=a);b&&(a=b.query||a,c=b.limit||c);let e=""+(c||0);b&&(e+=(b.offset||0)+!!b.context+!!b.suggest+(!1!==b.resolve)+(b.resolution||this.resolution)+(b.boost||0));a=(""+a).toLowerCase();this.cache||(this.cache=new R);let d=this.cache.get(a+e);if(!d){const f=b&&b.cache;f&&(b.cache=!1);d=this.search(a,c,b);f&&(b.cache=f);this.cache.set(a+e,d)}return d}function R(a){this.limit=a&&!0!==a?a:1E3;this.cache=new Map;this.h=""} +R.prototype.set=function(a,c){this.cache.set(this.h=a,c);this.cache.size>this.limit&&this.cache.delete(this.cache.keys().next().value)};R.prototype.get=function(a){const c=this.cache.get(a);c&&this.h!==a&&(this.cache.delete(a),this.cache.set(this.h=a,c));return c};R.prototype.remove=function(a){for(const c of this.cache){const b=c[0];c[1].includes(a)&&this.cache.delete(b)}};R.prototype.clear=function(){this.cache.clear();this.h=""};const na={normalize:!1,numeric:!1,dedupe:!1};const qa={};const ra=new Map([["b","p"],["v","f"],["w","f"],["z","s"],["x","s"],["d","t"],["n","m"],["c","k"],["g","k"],["j","k"],["q","k"],["i","e"],["y","e"],["u","o"]]);const sa=new Map([["ae","a"],["oe","o"],["sh","s"],["kh","k"],["th","t"],["ph","f"],["pf","f"]]),ta=[/([^aeo])h(.)/g,"$1$2",/([aeo])h([^aeo]|$)/g,"$1$2",/(.)\1+/g,"$1"];const ua={a:"",e:"",i:"",o:"",u:"",y:"",b:1,f:1,p:1,v:1,c:2,g:2,j:2,k:2,q:2,s:2,x:2,z:2,"\u00df":2,d:3,t:3,l:4,m:5,n:5,r:6};var va={Exact:na,Default:qa,Normalize:qa,LatinBalance:{mapper:ra},LatinAdvanced:{mapper:ra,matcher:sa,replacer:ta},LatinExtra:{mapper:ra,replacer:ta.concat([/(?!^)[aeo]/g,""]),matcher:sa},LatinSoundex:{dedupe:!1,include:{letter:!0},finalize:function(a){for(let b=0;b=g.length)c-=g.length;else{c=g[e?"splice":"slice"](c,b);const h=c.length;if(h&&(d=d.length?d.concat(c):c,b-=h,e&&(a.length-=h),!b))break;c=0}return d} +function za(a){if(!this||this.constructor!==za)return new za(a);this.index=a?[a]:[];this.length=a?a.length:0;const c=this;return new Proxy([],{get(b,e){if("length"===e)return c.length;if("push"===e)return function(d){c.index[c.index.length-1].push(d);c.length++};if("pop"===e)return function(){if(c.length)return c.length--,c.index[c.index.length-1].pop()};if("indexOf"===e)return function(d){let f=0;for(let g=0,h,k;g=this.priority*this.priority*3):(Ha=setTimeout(Ka,0),Ia=Date.now());if(Ja){const f=this;return new Promise(g=>{setTimeout(function(){g(f[a+"Async"].apply(f,c))},0)})}const d=this[a].apply(this,c);b=d.then?d:new Promise(f=>f(d));e&&b.then(e);return b}};let W=0; +function La(a={},c){function b(h){function k(m){m=m.data||m;const l=m.id,n=l&&f.h[l];n&&(n(m.msg),delete f.h[l])}this.worker=h;this.h=I();if(this.worker){d?this.worker.on("message",k):this.worker.onmessage=k;if(a.config)return new Promise(function(m){1E9c?a.slice(b,b+c):a,e?Ta.call(this,a):a;let d=[];for(let f=0,g,h;f=h){b-=h;continue}g=g.slice(b,b+c);h=g.length;b=0}h>c&&(g=g.slice(0,c),h=c);if(!d.length&&h>=c)return e?Ta.call(this,g):g;d.push(g);c-=h;if(!c)break}d=1a.length?this.result=a[0]:(this.result=Ya(a,c,b,!1,this.h),b=0));d&&(this.await=null);return d?this.resolve(c,b,e):this};Y.prototype.and=function(){return Ua(this,"and",Za,arguments)};function Za(a,c,b,e,d,f){if(!f&&!this.result.length)return d?this.result:this;let g;if(a.length)if(this.result.length&&a.unshift(this.result),2>a.length)this.result=a[0];else{let h=0;for(let k=0,m,l;ka.length)this.result=a[0];else{a:{f=b;var g=this.h;const h=[],k=I();let m=0;for(let l=0,n;lb||e?k.slice(e,b+e):k;else{if(ab||e)k=k.slice(e,b+ +e)}else{d=[];for(let n=0,u;ne)e-=u.length;else{if(b&&u.length>b||e)u=u.slice(e,b+e),b-=u.length,e&&(e-=u.length);d.push(u);if(!b)break}k=d}}return k} +function Ya(a,c,b,e,d){const f=[],g=I();let h;var k=a.length;let m;if(e)for(d=k-1;0<=d;d--){if(m=(e=a[d])&&e.length)for(k=0;kA&&(A=q.length+(q?1:0)),B=q.length+(q?1:0)+G.length,E+=D,ya.push(v.length),v.push({match:G})),q+=(q?" ":"")+G)}if(!x)F=y[C],q+=(q?" ":"")+F,k&&v.push({text:F});else if(k&&E>=k)break}E=ya.length*(f.length-2);if(p||t||k&&q.length-E>k)if(E=k+E-2*u,C=B-A,0y&&(y=0)),v=v.length-1){if(J>= +v.length){C[x+1]=1;J>=y.length&&(E[x+1]=1);continue}D-=u}q=v[J].text;if(L=t&&z[x])if(0L)if(C[x+1]=1,m)q=q.substring(0,L);else continue;(L-=q.length)||(L=-1);z[x]=L}else{C[x+1]=1;continue}if(D+q.length+1<=k)q=" "+q,B[x]+=q;else if(m)U=k-D-1,0=J){if(0>J){C[x]=1;E[x]=1;continue}D-=u}q=v[J].text;if(L=p&&F[x])if(0L)if(C[x]=1,m)q=q.substring(q.length- +L);else continue;(L-=q.length)||(L=-1);F[x]=L}else{C[x]=1;continue}if(D+q.length+1<=k)q+=" ",B[x]=q+B[x];else if(m)U=q.length+1-(k-D),0<=U&&U=y.length-1?Pa=1:Jb||e)a=a.slice(e,e+b);d&&(a=Ta.call(this,a))}return a} +function Ta(a){if(!this||!this.store)return a;if(this.db)return this.index.get(this.field[0]).db.enrich(a);const c=Array(a.length);for(let b=0,e;br;f--){g=t.substring(r,f);q=this.rtl?d-1-r:r;var h=this.score?this.score(c,t,p,g,q):wb(u, +m,p,d,q);xb(this,n,g,h,a,b)}break}case "bidirectional":case "reverse":if(1g?0:1),m,p,h-1,k-1),q=this.bidirectional&&t>f;xb(this,l,q?f:t,r,a,b,q?t:f)}}}}this.fastupdate||this.reg.add(a)}else c=""}this.db&&(c||this.commit_task.push({del:a}),this.S&&ub(this));return this}; +function xb(a,c,b,e,d,f,g){let h=g?a.ctx:a.map,k;if(!c[b]||g&&!(k=c[b])[g])if(g?(c=k||(c[b]=I()),c[g]=1,(k=h.get(g))?h=k:h.set(g,h=new Map)):c[b]=1,(k=h.get(b))?h=k:h.set(b,h=k=[]),h=h[e]||(h[e]=[]),!f||!h.includes(d)){if(h.length===2**31-1){c=new za(h);if(a.fastupdate)for(let m of a.reg.values())m.includes(h)&&(m[m.indexOf(h)]=c);k[e]=h=c}h.push(d);a.fastupdate&&((e=a.reg.get(d))?e.push(h):a.reg.set(d,[h]))}} +function wb(a,c,b,e,d){return b&&1b)&&(k=b,b=c,c=k);if(a.db)return a.db.get(c,b,e,d,f,g,h);a=b?(a=a.ctx.get(b))&&a.get(c):a.map.get(c);return a};function V(a,c){if(!this||this.constructor!==V)return new V(a);if(a){var b=M(a)?a:a.preset;b&&(a=Object.assign({},vb[b],a))}else a={};b=a.context;const e=!0===b?{depth:1}:b||{},d=M(a.encoder)?va[a.encoder]:a.encode||a.encoder||{};this.encoder=d.encode?d:"object"===typeof d?new la(d):{encode:d};this.resolution=a.resolution||9;this.tokenize=b=(b=a.tokenize)&&"default"!==b&&"exact"!==b&&b||"strict";this.depth="strict"===b&&e.depth||0;this.bidirectional=!1!==e.bidirectional;this.fastupdate=!!a.fastupdate; +this.score=a.score||null;(b=a.keystore||0)&&(this.keystore=b);this.map=b?new S(b):new Map;this.ctx=b?new S(b):new Map;this.reg=c||(this.fastupdate?b?new S(b):new Map:b?new T(b):new Set);this.T=e.resolution||3;this.rtl=d.rtl||a.rtl||!1;this.cache=(b=a.cache||null)&&new R(b);this.resolve=!1!==a.resolve;if(b=a.db)this.db=this.mount(b);this.S=!1!==a.commit;this.commit_task=[];this.commit_timer=null;this.priority=a.priority||4}w=V.prototype; +w.mount=function(a){this.commit_timer&&(clearTimeout(this.commit_timer),this.commit_timer=null);return a.mount(this)};w.commit=function(a,c){this.commit_timer&&(clearTimeout(this.commit_timer),this.commit_timer=null);return this.db.commit(this,a,c)};w.destroy=function(){this.commit_timer&&(clearTimeout(this.commit_timer),this.commit_timer=null);return this.db.destroy()};function ub(a){a.commit_timer||(a.commit_timer=setTimeout(function(){a.commit_timer=null;a.db.commit(a,void 0,void 0)},1))} +w.clear=function(){this.map.clear();this.ctx.clear();this.reg.clear();this.cache&&this.cache.clear();this.db&&(this.commit_timer&&clearTimeout(this.commit_timer),this.commit_timer=null,this.commit_task=[{clear:!0}]);return this};w.append=function(a,c){return this.add(a,c,!0)};w.contain=function(a){return this.db?this.db.has(a):this.reg.has(a)};w.update=function(a,c){const b=this,e=this.remove(a);return e&&e.then?e.then(()=>b.add(a,c)):this.add(a,c)}; +w.cleanup=function(){if(!this.fastupdate)return this;tb(this.map);this.depth&&tb(this.ctx);return this};w.searchCache=ma;w.export=function(a,c,b=0,e=0){let d,f;switch(e){case 0:d="reg";f=pb(this.reg);break;case 1:d="cfg";f=null;break;case 2:d="map";f=lb(this.map,this.reg.size);break;case 3:d="ctx";f=nb(this.ctx,this.reg.size);break;default:return}return rb.call(this,a,c,d,f,b,e)}; +w.import=function(a,c){if(c)switch("string"===typeof c&&(c=JSON.parse(c)),a=a.split("."),"json"===a[a.length-1]&&a.pop(),3===a.length&&a.shift(),a=1=l.length){e-=l.length;continue}const n=b?e+Math.min(l.length-e,b):l.length;for(let u=e;u=f.length)return[];if(!c&&!b)return f;f=f.slice(b,b+c);return e?d.enrich(f):f})}; +w.enrich=function(a){"object"!==typeof a&&(a=[a]);const c=this.db.transaction("reg","readonly").objectStore("reg"),b=[];for(let e=0;e{a.onsuccess=a.oncomplete=function(){c&&c(this.result);c=null;b(this.result)};a.onerror=a.onblocked=e;a=null})};export default {Index:V,Charset:va,Encoder:la,Document:Na,Worker:La,Resolver:Y,IndexedDB:Fb,Language:{}}; +export const Index=V;export const Charset=va;export const Encoder=la;export const Document=Na;export const Worker=La;export const Resolver=Y;export const IndexedDB=Fb;export const Language={}; \ No newline at end of file