市场夺宝奇兵
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1151 lines
33 KiB

  1. import { computed } from "./runtime-core.esm-bundler-Cyv4obHQ.js";
  2. import { defineStore, usePayloadStore } from "./payload-BX9lTMvN.js";
  3. import { useOptionsStore } from "./options-D_MMddT_.js";
  4. /**
  5. * Fuse.js v7.1.0 - Lightweight fuzzy-search (http://fusejs.io)
  6. *
  7. * Copyright (c) 2025 Kiro Risk (http://kiro.me)
  8. * All Rights Reserved. Apache Software License 2.0
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. */
  12. function isArray(value) {
  13. return !Array.isArray ? getTag(value) === "[object Array]" : Array.isArray(value);
  14. }
  15. const INFINITY = Infinity;
  16. function baseToString(value) {
  17. if (typeof value == "string") return value;
  18. let result = value + "";
  19. return result == "0" && 1 / value == -INFINITY ? "-0" : result;
  20. }
  21. function toString(value) {
  22. return value == null ? "" : baseToString(value);
  23. }
  24. function isString(value) {
  25. return typeof value === "string";
  26. }
  27. function isNumber(value) {
  28. return typeof value === "number";
  29. }
  30. function isBoolean(value) {
  31. return value === true || value === false || isObjectLike(value) && getTag(value) == "[object Boolean]";
  32. }
  33. function isObject(value) {
  34. return typeof value === "object";
  35. }
  36. function isObjectLike(value) {
  37. return isObject(value) && value !== null;
  38. }
  39. function isDefined(value) {
  40. return value !== void 0 && value !== null;
  41. }
  42. function isBlank(value) {
  43. return !value.trim().length;
  44. }
  45. function getTag(value) {
  46. return value == null ? value === void 0 ? "[object Undefined]" : "[object Null]" : Object.prototype.toString.call(value);
  47. }
  48. const INCORRECT_INDEX_TYPE = "Incorrect 'index' type";
  49. const LOGICAL_SEARCH_INVALID_QUERY_FOR_KEY = (key) => `Invalid value for key ${key}`;
  50. const PATTERN_LENGTH_TOO_LARGE = (max) => `Pattern length exceeds max of ${max}.`;
  51. const MISSING_KEY_PROPERTY = (name) => `Missing ${name} property in key`;
  52. const INVALID_KEY_WEIGHT_VALUE = (key) => `Property 'weight' in key '${key}' must be a positive integer`;
  53. const hasOwn = Object.prototype.hasOwnProperty;
  54. var KeyStore = class {
  55. constructor(keys) {
  56. this._keys = [];
  57. this._keyMap = {};
  58. let totalWeight = 0;
  59. keys.forEach((key) => {
  60. let obj = createKey(key);
  61. this._keys.push(obj);
  62. this._keyMap[obj.id] = obj;
  63. totalWeight += obj.weight;
  64. });
  65. this._keys.forEach((key) => {
  66. key.weight /= totalWeight;
  67. });
  68. }
  69. get(keyId) {
  70. return this._keyMap[keyId];
  71. }
  72. keys() {
  73. return this._keys;
  74. }
  75. toJSON() {
  76. return JSON.stringify(this._keys);
  77. }
  78. };
  79. function createKey(key) {
  80. let path = null;
  81. let id = null;
  82. let src = null;
  83. let weight = 1;
  84. let getFn = null;
  85. if (isString(key) || isArray(key)) {
  86. src = key;
  87. path = createKeyPath(key);
  88. id = createKeyId(key);
  89. } else {
  90. if (!hasOwn.call(key, "name")) throw new Error(MISSING_KEY_PROPERTY("name"));
  91. const name = key.name;
  92. src = name;
  93. if (hasOwn.call(key, "weight")) {
  94. weight = key.weight;
  95. if (weight <= 0) throw new Error(INVALID_KEY_WEIGHT_VALUE(name));
  96. }
  97. path = createKeyPath(name);
  98. id = createKeyId(name);
  99. getFn = key.getFn;
  100. }
  101. return {
  102. path,
  103. id,
  104. weight,
  105. src,
  106. getFn
  107. };
  108. }
  109. function createKeyPath(key) {
  110. return isArray(key) ? key : key.split(".");
  111. }
  112. function createKeyId(key) {
  113. return isArray(key) ? key.join(".") : key;
  114. }
  115. function get(obj, path) {
  116. let list = [];
  117. let arr = false;
  118. const deepGet = (obj$1, path$1, index) => {
  119. if (!isDefined(obj$1)) return;
  120. if (!path$1[index]) list.push(obj$1);
  121. else {
  122. let key = path$1[index];
  123. const value = obj$1[key];
  124. if (!isDefined(value)) return;
  125. if (index === path$1.length - 1 && (isString(value) || isNumber(value) || isBoolean(value))) list.push(toString(value));
  126. else if (isArray(value)) {
  127. arr = true;
  128. for (let i = 0, len = value.length; i < len; i += 1) deepGet(value[i], path$1, index + 1);
  129. } else if (path$1.length) deepGet(value, path$1, index + 1);
  130. }
  131. };
  132. deepGet(obj, isString(path) ? path.split(".") : path, 0);
  133. return arr ? list : list[0];
  134. }
  135. const MatchOptions = {
  136. includeMatches: false,
  137. findAllMatches: false,
  138. minMatchCharLength: 1
  139. };
  140. const BasicOptions = {
  141. isCaseSensitive: false,
  142. ignoreDiacritics: false,
  143. includeScore: false,
  144. keys: [],
  145. shouldSort: true,
  146. sortFn: (a, b) => a.score === b.score ? a.idx < b.idx ? -1 : 1 : a.score < b.score ? -1 : 1
  147. };
  148. const FuzzyOptions = {
  149. location: 0,
  150. threshold: .6,
  151. distance: 100
  152. };
  153. const AdvancedOptions = {
  154. useExtendedSearch: false,
  155. getFn: get,
  156. ignoreLocation: false,
  157. ignoreFieldNorm: false,
  158. fieldNormWeight: 1
  159. };
  160. var Config = {
  161. ...BasicOptions,
  162. ...MatchOptions,
  163. ...FuzzyOptions,
  164. ...AdvancedOptions
  165. };
  166. const SPACE = /[^ ]+/g;
  167. function norm(weight = 1, mantissa = 3) {
  168. const cache = new Map();
  169. const m = Math.pow(10, mantissa);
  170. return {
  171. get(value) {
  172. const numTokens = value.match(SPACE).length;
  173. if (cache.has(numTokens)) return cache.get(numTokens);
  174. const norm$1 = 1 / Math.pow(numTokens, .5 * weight);
  175. const n = parseFloat(Math.round(norm$1 * m) / m);
  176. cache.set(numTokens, n);
  177. return n;
  178. },
  179. clear() {
  180. cache.clear();
  181. }
  182. };
  183. }
  184. var FuseIndex = class {
  185. constructor({ getFn = Config.getFn, fieldNormWeight = Config.fieldNormWeight } = {}) {
  186. this.norm = norm(fieldNormWeight, 3);
  187. this.getFn = getFn;
  188. this.isCreated = false;
  189. this.setIndexRecords();
  190. }
  191. setSources(docs = []) {
  192. this.docs = docs;
  193. }
  194. setIndexRecords(records = []) {
  195. this.records = records;
  196. }
  197. setKeys(keys = []) {
  198. this.keys = keys;
  199. this._keysMap = {};
  200. keys.forEach((key, idx) => {
  201. this._keysMap[key.id] = idx;
  202. });
  203. }
  204. create() {
  205. if (this.isCreated || !this.docs.length) return;
  206. this.isCreated = true;
  207. if (isString(this.docs[0])) this.docs.forEach((doc, docIndex) => {
  208. this._addString(doc, docIndex);
  209. });
  210. else this.docs.forEach((doc, docIndex) => {
  211. this._addObject(doc, docIndex);
  212. });
  213. this.norm.clear();
  214. }
  215. add(doc) {
  216. const idx = this.size();
  217. if (isString(doc)) this._addString(doc, idx);
  218. else this._addObject(doc, idx);
  219. }
  220. removeAt(idx) {
  221. this.records.splice(idx, 1);
  222. for (let i = idx, len = this.size(); i < len; i += 1) this.records[i].i -= 1;
  223. }
  224. getValueForItemAtKeyId(item, keyId) {
  225. return item[this._keysMap[keyId]];
  226. }
  227. size() {
  228. return this.records.length;
  229. }
  230. _addString(doc, docIndex) {
  231. if (!isDefined(doc) || isBlank(doc)) return;
  232. let record = {
  233. v: doc,
  234. i: docIndex,
  235. n: this.norm.get(doc)
  236. };
  237. this.records.push(record);
  238. }
  239. _addObject(doc, docIndex) {
  240. let record = {
  241. i: docIndex,
  242. $: {}
  243. };
  244. this.keys.forEach((key, keyIndex) => {
  245. let value = key.getFn ? key.getFn(doc) : this.getFn(doc, key.path);
  246. if (!isDefined(value)) return;
  247. if (isArray(value)) {
  248. let subRecords = [];
  249. const stack = [{
  250. nestedArrIndex: -1,
  251. value
  252. }];
  253. while (stack.length) {
  254. const { nestedArrIndex, value: value$1 } = stack.pop();
  255. if (!isDefined(value$1)) continue;
  256. if (isString(value$1) && !isBlank(value$1)) {
  257. let subRecord = {
  258. v: value$1,
  259. i: nestedArrIndex,
  260. n: this.norm.get(value$1)
  261. };
  262. subRecords.push(subRecord);
  263. } else if (isArray(value$1)) value$1.forEach((item, k) => {
  264. stack.push({
  265. nestedArrIndex: k,
  266. value: item
  267. });
  268. });
  269. }
  270. record.$[keyIndex] = subRecords;
  271. } else if (isString(value) && !isBlank(value)) {
  272. let subRecord = {
  273. v: value,
  274. n: this.norm.get(value)
  275. };
  276. record.$[keyIndex] = subRecord;
  277. }
  278. });
  279. this.records.push(record);
  280. }
  281. toJSON() {
  282. return {
  283. keys: this.keys,
  284. records: this.records
  285. };
  286. }
  287. };
  288. function createIndex(keys, docs, { getFn = Config.getFn, fieldNormWeight = Config.fieldNormWeight } = {}) {
  289. const myIndex = new FuseIndex({
  290. getFn,
  291. fieldNormWeight
  292. });
  293. myIndex.setKeys(keys.map(createKey));
  294. myIndex.setSources(docs);
  295. myIndex.create();
  296. return myIndex;
  297. }
  298. function parseIndex(data, { getFn = Config.getFn, fieldNormWeight = Config.fieldNormWeight } = {}) {
  299. const { keys, records } = data;
  300. const myIndex = new FuseIndex({
  301. getFn,
  302. fieldNormWeight
  303. });
  304. myIndex.setKeys(keys);
  305. myIndex.setIndexRecords(records);
  306. return myIndex;
  307. }
  308. function computeScore$1(pattern, { errors = 0, currentLocation = 0, expectedLocation = 0, distance = Config.distance, ignoreLocation = Config.ignoreLocation } = {}) {
  309. const accuracy = errors / pattern.length;
  310. if (ignoreLocation) return accuracy;
  311. const proximity = Math.abs(expectedLocation - currentLocation);
  312. if (!distance) return proximity ? 1 : accuracy;
  313. return accuracy + proximity / distance;
  314. }
  315. function convertMaskToIndices(matchmask = [], minMatchCharLength = Config.minMatchCharLength) {
  316. let indices = [];
  317. let start = -1;
  318. let end = -1;
  319. let i = 0;
  320. for (let len = matchmask.length; i < len; i += 1) {
  321. let match = matchmask[i];
  322. if (match && start === -1) start = i;
  323. else if (!match && start !== -1) {
  324. end = i - 1;
  325. if (end - start + 1 >= minMatchCharLength) indices.push([start, end]);
  326. start = -1;
  327. }
  328. }
  329. if (matchmask[i - 1] && i - start >= minMatchCharLength) indices.push([start, i - 1]);
  330. return indices;
  331. }
  332. const MAX_BITS = 32;
  333. function search(text, pattern, patternAlphabet, { location = Config.location, distance = Config.distance, threshold = Config.threshold, findAllMatches = Config.findAllMatches, minMatchCharLength = Config.minMatchCharLength, includeMatches = Config.includeMatches, ignoreLocation = Config.ignoreLocation } = {}) {
  334. if (pattern.length > MAX_BITS) throw new Error(PATTERN_LENGTH_TOO_LARGE(MAX_BITS));
  335. const patternLen = pattern.length;
  336. const textLen = text.length;
  337. const expectedLocation = Math.max(0, Math.min(location, textLen));
  338. let currentThreshold = threshold;
  339. let bestLocation = expectedLocation;
  340. const computeMatches = minMatchCharLength > 1 || includeMatches;
  341. const matchMask = computeMatches ? Array(textLen) : [];
  342. let index;
  343. while ((index = text.indexOf(pattern, bestLocation)) > -1) {
  344. let score = computeScore$1(pattern, {
  345. currentLocation: index,
  346. expectedLocation,
  347. distance,
  348. ignoreLocation
  349. });
  350. currentThreshold = Math.min(score, currentThreshold);
  351. bestLocation = index + patternLen;
  352. if (computeMatches) {
  353. let i = 0;
  354. while (i < patternLen) {
  355. matchMask[index + i] = 1;
  356. i += 1;
  357. }
  358. }
  359. }
  360. bestLocation = -1;
  361. let lastBitArr = [];
  362. let finalScore = 1;
  363. let binMax = patternLen + textLen;
  364. const mask = 1 << patternLen - 1;
  365. for (let i = 0; i < patternLen; i += 1) {
  366. let binMin = 0;
  367. let binMid = binMax;
  368. while (binMin < binMid) {
  369. const score$1 = computeScore$1(pattern, {
  370. errors: i,
  371. currentLocation: expectedLocation + binMid,
  372. expectedLocation,
  373. distance,
  374. ignoreLocation
  375. });
  376. if (score$1 <= currentThreshold) binMin = binMid;
  377. else binMax = binMid;
  378. binMid = Math.floor((binMax - binMin) / 2 + binMin);
  379. }
  380. binMax = binMid;
  381. let start = Math.max(1, expectedLocation - binMid + 1);
  382. let finish = findAllMatches ? textLen : Math.min(expectedLocation + binMid, textLen) + patternLen;
  383. let bitArr = Array(finish + 2);
  384. bitArr[finish + 1] = (1 << i) - 1;
  385. for (let j = finish; j >= start; j -= 1) {
  386. let currentLocation = j - 1;
  387. let charMatch = patternAlphabet[text.charAt(currentLocation)];
  388. if (computeMatches) matchMask[currentLocation] = +!!charMatch;
  389. bitArr[j] = (bitArr[j + 1] << 1 | 1) & charMatch;
  390. if (i) bitArr[j] |= (lastBitArr[j + 1] | lastBitArr[j]) << 1 | 1 | lastBitArr[j + 1];
  391. if (bitArr[j] & mask) {
  392. finalScore = computeScore$1(pattern, {
  393. errors: i,
  394. currentLocation,
  395. expectedLocation,
  396. distance,
  397. ignoreLocation
  398. });
  399. if (finalScore <= currentThreshold) {
  400. currentThreshold = finalScore;
  401. bestLocation = currentLocation;
  402. if (bestLocation <= expectedLocation) break;
  403. start = Math.max(1, 2 * expectedLocation - bestLocation);
  404. }
  405. }
  406. }
  407. const score = computeScore$1(pattern, {
  408. errors: i + 1,
  409. currentLocation: expectedLocation,
  410. expectedLocation,
  411. distance,
  412. ignoreLocation
  413. });
  414. if (score > currentThreshold) break;
  415. lastBitArr = bitArr;
  416. }
  417. const result = {
  418. isMatch: bestLocation >= 0,
  419. score: Math.max(.001, finalScore)
  420. };
  421. if (computeMatches) {
  422. const indices = convertMaskToIndices(matchMask, minMatchCharLength);
  423. if (!indices.length) result.isMatch = false;
  424. else if (includeMatches) result.indices = indices;
  425. }
  426. return result;
  427. }
  428. function createPatternAlphabet(pattern) {
  429. let mask = {};
  430. for (let i = 0, len = pattern.length; i < len; i += 1) {
  431. const char = pattern.charAt(i);
  432. mask[char] = (mask[char] || 0) | 1 << len - i - 1;
  433. }
  434. return mask;
  435. }
  436. const stripDiacritics = String.prototype.normalize ? (str) => str.normalize("NFD").replace(/[\u0300-\u036F\u0483-\u0489\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u07FD\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08D3-\u08E1\u08E3-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u09FE\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A70\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0AFA-\u0AFF\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B62\u0B63\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0C00-\u0C04\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0D00-\u0D03\u0D3B\u0D3C\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D82\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB\u0EBC\u0EC8-\u0ECD\u0F18\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F\u109A-\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u180B-\u180D\u1885\u1886\u18A9\u1920-\u192B\u1930-\u193B\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F\u1AB0-\u1ABE\u1B00-\u1B04\u1B34-\u1B44\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BE6-\u1BF3\u1C24-\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF2-\u1CF4\u1CF7-\u1CF9\u1DC0-\u1DF9\u1DFB-\u1DFF\u20D0-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA66F-\uA672\uA674-\uA67D\uA69E\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA880\uA881\uA8B4-\uA8C5\uA8E0-\uA8F1\uA8FF\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uA9E5\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F]/g, "") : (str) => str;
  437. var BitapSearch = class {
  438. constructor(pattern, { location = Config.location, threshold = Config.threshold, distance = Config.distance, includeMatches = Config.includeMatches, findAllMatches = Config.findAllMatches, minMatchCharLength = Config.minMatchCharLength, isCaseSensitive = Config.isCaseSensitive, ignoreDiacritics = Config.ignoreDiacritics, ignoreLocation = Config.ignoreLocation } = {}) {
  439. this.options = {
  440. location,
  441. threshold,
  442. distance,
  443. includeMatches,
  444. findAllMatches,
  445. minMatchCharLength,
  446. isCaseSensitive,
  447. ignoreDiacritics,
  448. ignoreLocation
  449. };
  450. pattern = isCaseSensitive ? pattern : pattern.toLowerCase();
  451. pattern = ignoreDiacritics ? stripDiacritics(pattern) : pattern;
  452. this.pattern = pattern;
  453. this.chunks = [];
  454. if (!this.pattern.length) return;
  455. const addChunk = (pattern$1, startIndex) => {
  456. this.chunks.push({
  457. pattern: pattern$1,
  458. alphabet: createPatternAlphabet(pattern$1),
  459. startIndex
  460. });
  461. };
  462. const len = this.pattern.length;
  463. if (len > MAX_BITS) {
  464. let i = 0;
  465. const remainder = len % MAX_BITS;
  466. const end = len - remainder;
  467. while (i < end) {
  468. addChunk(this.pattern.substr(i, MAX_BITS), i);
  469. i += MAX_BITS;
  470. }
  471. if (remainder) {
  472. const startIndex = len - MAX_BITS;
  473. addChunk(this.pattern.substr(startIndex), startIndex);
  474. }
  475. } else addChunk(this.pattern, 0);
  476. }
  477. searchIn(text) {
  478. const { isCaseSensitive, ignoreDiacritics, includeMatches } = this.options;
  479. text = isCaseSensitive ? text : text.toLowerCase();
  480. text = ignoreDiacritics ? stripDiacritics(text) : text;
  481. if (this.pattern === text) {
  482. let result$1 = {
  483. isMatch: true,
  484. score: 0
  485. };
  486. if (includeMatches) result$1.indices = [[0, text.length - 1]];
  487. return result$1;
  488. }
  489. const { location, distance, threshold, findAllMatches, minMatchCharLength, ignoreLocation } = this.options;
  490. let allIndices = [];
  491. let totalScore = 0;
  492. let hasMatches = false;
  493. this.chunks.forEach(({ pattern, alphabet, startIndex }) => {
  494. const { isMatch, score, indices } = search(text, pattern, alphabet, {
  495. location: location + startIndex,
  496. distance,
  497. threshold,
  498. findAllMatches,
  499. minMatchCharLength,
  500. includeMatches,
  501. ignoreLocation
  502. });
  503. if (isMatch) hasMatches = true;
  504. totalScore += score;
  505. if (isMatch && indices) allIndices = [...allIndices, ...indices];
  506. });
  507. let result = {
  508. isMatch: hasMatches,
  509. score: hasMatches ? totalScore / this.chunks.length : 1
  510. };
  511. if (hasMatches && includeMatches) result.indices = allIndices;
  512. return result;
  513. }
  514. };
  515. var BaseMatch = class {
  516. constructor(pattern) {
  517. this.pattern = pattern;
  518. }
  519. static isMultiMatch(pattern) {
  520. return getMatch(pattern, this.multiRegex);
  521. }
  522. static isSingleMatch(pattern) {
  523. return getMatch(pattern, this.singleRegex);
  524. }
  525. search() {}
  526. };
  527. function getMatch(pattern, exp) {
  528. const matches = pattern.match(exp);
  529. return matches ? matches[1] : null;
  530. }
  531. var ExactMatch = class extends BaseMatch {
  532. constructor(pattern) {
  533. super(pattern);
  534. }
  535. static get type() {
  536. return "exact";
  537. }
  538. static get multiRegex() {
  539. return /^="(.*)"$/;
  540. }
  541. static get singleRegex() {
  542. return /^=(.*)$/;
  543. }
  544. search(text) {
  545. const isMatch = text === this.pattern;
  546. return {
  547. isMatch,
  548. score: isMatch ? 0 : 1,
  549. indices: [0, this.pattern.length - 1]
  550. };
  551. }
  552. };
  553. var InverseExactMatch = class extends BaseMatch {
  554. constructor(pattern) {
  555. super(pattern);
  556. }
  557. static get type() {
  558. return "inverse-exact";
  559. }
  560. static get multiRegex() {
  561. return /^!"(.*)"$/;
  562. }
  563. static get singleRegex() {
  564. return /^!(.*)$/;
  565. }
  566. search(text) {
  567. const index = text.indexOf(this.pattern);
  568. const isMatch = index === -1;
  569. return {
  570. isMatch,
  571. score: isMatch ? 0 : 1,
  572. indices: [0, text.length - 1]
  573. };
  574. }
  575. };
  576. var PrefixExactMatch = class extends BaseMatch {
  577. constructor(pattern) {
  578. super(pattern);
  579. }
  580. static get type() {
  581. return "prefix-exact";
  582. }
  583. static get multiRegex() {
  584. return /^\^"(.*)"$/;
  585. }
  586. static get singleRegex() {
  587. return /^\^(.*)$/;
  588. }
  589. search(text) {
  590. const isMatch = text.startsWith(this.pattern);
  591. return {
  592. isMatch,
  593. score: isMatch ? 0 : 1,
  594. indices: [0, this.pattern.length - 1]
  595. };
  596. }
  597. };
  598. var InversePrefixExactMatch = class extends BaseMatch {
  599. constructor(pattern) {
  600. super(pattern);
  601. }
  602. static get type() {
  603. return "inverse-prefix-exact";
  604. }
  605. static get multiRegex() {
  606. return /^!\^"(.*)"$/;
  607. }
  608. static get singleRegex() {
  609. return /^!\^(.*)$/;
  610. }
  611. search(text) {
  612. const isMatch = !text.startsWith(this.pattern);
  613. return {
  614. isMatch,
  615. score: isMatch ? 0 : 1,
  616. indices: [0, text.length - 1]
  617. };
  618. }
  619. };
  620. var SuffixExactMatch = class extends BaseMatch {
  621. constructor(pattern) {
  622. super(pattern);
  623. }
  624. static get type() {
  625. return "suffix-exact";
  626. }
  627. static get multiRegex() {
  628. return /^"(.*)"\$$/;
  629. }
  630. static get singleRegex() {
  631. return /^(.*)\$$/;
  632. }
  633. search(text) {
  634. const isMatch = text.endsWith(this.pattern);
  635. return {
  636. isMatch,
  637. score: isMatch ? 0 : 1,
  638. indices: [text.length - this.pattern.length, text.length - 1]
  639. };
  640. }
  641. };
  642. var InverseSuffixExactMatch = class extends BaseMatch {
  643. constructor(pattern) {
  644. super(pattern);
  645. }
  646. static get type() {
  647. return "inverse-suffix-exact";
  648. }
  649. static get multiRegex() {
  650. return /^!"(.*)"\$$/;
  651. }
  652. static get singleRegex() {
  653. return /^!(.*)\$$/;
  654. }
  655. search(text) {
  656. const isMatch = !text.endsWith(this.pattern);
  657. return {
  658. isMatch,
  659. score: isMatch ? 0 : 1,
  660. indices: [0, text.length - 1]
  661. };
  662. }
  663. };
  664. var FuzzyMatch = class extends BaseMatch {
  665. constructor(pattern, { location = Config.location, threshold = Config.threshold, distance = Config.distance, includeMatches = Config.includeMatches, findAllMatches = Config.findAllMatches, minMatchCharLength = Config.minMatchCharLength, isCaseSensitive = Config.isCaseSensitive, ignoreDiacritics = Config.ignoreDiacritics, ignoreLocation = Config.ignoreLocation } = {}) {
  666. super(pattern);
  667. this._bitapSearch = new BitapSearch(pattern, {
  668. location,
  669. threshold,
  670. distance,
  671. includeMatches,
  672. findAllMatches,
  673. minMatchCharLength,
  674. isCaseSensitive,
  675. ignoreDiacritics,
  676. ignoreLocation
  677. });
  678. }
  679. static get type() {
  680. return "fuzzy";
  681. }
  682. static get multiRegex() {
  683. return /^"(.*)"$/;
  684. }
  685. static get singleRegex() {
  686. return /^(.*)$/;
  687. }
  688. search(text) {
  689. return this._bitapSearch.searchIn(text);
  690. }
  691. };
  692. var IncludeMatch = class extends BaseMatch {
  693. constructor(pattern) {
  694. super(pattern);
  695. }
  696. static get type() {
  697. return "include";
  698. }
  699. static get multiRegex() {
  700. return /^'"(.*)"$/;
  701. }
  702. static get singleRegex() {
  703. return /^'(.*)$/;
  704. }
  705. search(text) {
  706. let location = 0;
  707. let index;
  708. const indices = [];
  709. const patternLen = this.pattern.length;
  710. while ((index = text.indexOf(this.pattern, location)) > -1) {
  711. location = index + patternLen;
  712. indices.push([index, location - 1]);
  713. }
  714. const isMatch = !!indices.length;
  715. return {
  716. isMatch,
  717. score: isMatch ? 0 : 1,
  718. indices
  719. };
  720. }
  721. };
  722. const searchers = [
  723. ExactMatch,
  724. IncludeMatch,
  725. PrefixExactMatch,
  726. InversePrefixExactMatch,
  727. InverseSuffixExactMatch,
  728. SuffixExactMatch,
  729. InverseExactMatch,
  730. FuzzyMatch
  731. ];
  732. const searchersLen = searchers.length;
  733. const SPACE_RE = / +(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/;
  734. const OR_TOKEN = "|";
  735. function parseQuery(pattern, options = {}) {
  736. return pattern.split(OR_TOKEN).map((item) => {
  737. let query = item.trim().split(SPACE_RE).filter((item$1) => item$1 && !!item$1.trim());
  738. let results = [];
  739. for (let i = 0, len = query.length; i < len; i += 1) {
  740. const queryItem = query[i];
  741. let found = false;
  742. let idx = -1;
  743. while (!found && ++idx < searchersLen) {
  744. const searcher = searchers[idx];
  745. let token = searcher.isMultiMatch(queryItem);
  746. if (token) {
  747. results.push(new searcher(token, options));
  748. found = true;
  749. }
  750. }
  751. if (found) continue;
  752. idx = -1;
  753. while (++idx < searchersLen) {
  754. const searcher = searchers[idx];
  755. let token = searcher.isSingleMatch(queryItem);
  756. if (token) {
  757. results.push(new searcher(token, options));
  758. break;
  759. }
  760. }
  761. }
  762. return results;
  763. });
  764. }
  765. const MultiMatchSet = new Set([FuzzyMatch.type, IncludeMatch.type]);
  766. var ExtendedSearch = class {
  767. constructor(pattern, { isCaseSensitive = Config.isCaseSensitive, ignoreDiacritics = Config.ignoreDiacritics, includeMatches = Config.includeMatches, minMatchCharLength = Config.minMatchCharLength, ignoreLocation = Config.ignoreLocation, findAllMatches = Config.findAllMatches, location = Config.location, threshold = Config.threshold, distance = Config.distance } = {}) {
  768. this.query = null;
  769. this.options = {
  770. isCaseSensitive,
  771. ignoreDiacritics,
  772. includeMatches,
  773. minMatchCharLength,
  774. findAllMatches,
  775. ignoreLocation,
  776. location,
  777. threshold,
  778. distance
  779. };
  780. pattern = isCaseSensitive ? pattern : pattern.toLowerCase();
  781. pattern = ignoreDiacritics ? stripDiacritics(pattern) : pattern;
  782. this.pattern = pattern;
  783. this.query = parseQuery(this.pattern, this.options);
  784. }
  785. static condition(_, options) {
  786. return options.useExtendedSearch;
  787. }
  788. searchIn(text) {
  789. const query = this.query;
  790. if (!query) return {
  791. isMatch: false,
  792. score: 1
  793. };
  794. const { includeMatches, isCaseSensitive, ignoreDiacritics } = this.options;
  795. text = isCaseSensitive ? text : text.toLowerCase();
  796. text = ignoreDiacritics ? stripDiacritics(text) : text;
  797. let numMatches = 0;
  798. let allIndices = [];
  799. let totalScore = 0;
  800. for (let i = 0, qLen = query.length; i < qLen; i += 1) {
  801. const searchers$1 = query[i];
  802. allIndices.length = 0;
  803. numMatches = 0;
  804. for (let j = 0, pLen = searchers$1.length; j < pLen; j += 1) {
  805. const searcher = searchers$1[j];
  806. const { isMatch, indices, score } = searcher.search(text);
  807. if (isMatch) {
  808. numMatches += 1;
  809. totalScore += score;
  810. if (includeMatches) {
  811. const type = searcher.constructor.type;
  812. if (MultiMatchSet.has(type)) allIndices = [...allIndices, ...indices];
  813. else allIndices.push(indices);
  814. }
  815. } else {
  816. totalScore = 0;
  817. numMatches = 0;
  818. allIndices.length = 0;
  819. break;
  820. }
  821. }
  822. if (numMatches) {
  823. let result = {
  824. isMatch: true,
  825. score: totalScore / numMatches
  826. };
  827. if (includeMatches) result.indices = allIndices;
  828. return result;
  829. }
  830. }
  831. return {
  832. isMatch: false,
  833. score: 1
  834. };
  835. }
  836. };
  837. const registeredSearchers = [];
  838. function register(...args) {
  839. registeredSearchers.push(...args);
  840. }
  841. function createSearcher(pattern, options) {
  842. for (let i = 0, len = registeredSearchers.length; i < len; i += 1) {
  843. let searcherClass = registeredSearchers[i];
  844. if (searcherClass.condition(pattern, options)) return new searcherClass(pattern, options);
  845. }
  846. return new BitapSearch(pattern, options);
  847. }
  848. const LogicalOperator = {
  849. AND: "$and",
  850. OR: "$or"
  851. };
  852. const KeyType = {
  853. PATH: "$path",
  854. PATTERN: "$val"
  855. };
  856. const isExpression = (query) => !!(query[LogicalOperator.AND] || query[LogicalOperator.OR]);
  857. const isPath = (query) => !!query[KeyType.PATH];
  858. const isLeaf = (query) => !isArray(query) && isObject(query) && !isExpression(query);
  859. const convertToExplicit = (query) => ({ [LogicalOperator.AND]: Object.keys(query).map((key) => ({ [key]: query[key] })) });
  860. function parse(query, options, { auto = true } = {}) {
  861. const next = (query$1) => {
  862. let keys = Object.keys(query$1);
  863. const isQueryPath = isPath(query$1);
  864. if (!isQueryPath && keys.length > 1 && !isExpression(query$1)) return next(convertToExplicit(query$1));
  865. if (isLeaf(query$1)) {
  866. const key = isQueryPath ? query$1[KeyType.PATH] : keys[0];
  867. const pattern = isQueryPath ? query$1[KeyType.PATTERN] : query$1[key];
  868. if (!isString(pattern)) throw new Error(LOGICAL_SEARCH_INVALID_QUERY_FOR_KEY(key));
  869. const obj = {
  870. keyId: createKeyId(key),
  871. pattern
  872. };
  873. if (auto) obj.searcher = createSearcher(pattern, options);
  874. return obj;
  875. }
  876. let node = {
  877. children: [],
  878. operator: keys[0]
  879. };
  880. keys.forEach((key) => {
  881. const value = query$1[key];
  882. if (isArray(value)) value.forEach((item) => {
  883. node.children.push(next(item));
  884. });
  885. });
  886. return node;
  887. };
  888. if (!isExpression(query)) query = convertToExplicit(query);
  889. return next(query);
  890. }
  891. function computeScore(results, { ignoreFieldNorm = Config.ignoreFieldNorm }) {
  892. results.forEach((result) => {
  893. let totalScore = 1;
  894. result.matches.forEach(({ key, norm: norm$1, score }) => {
  895. const weight = key ? key.weight : null;
  896. totalScore *= Math.pow(score === 0 && weight ? Number.EPSILON : score, (weight || 1) * (ignoreFieldNorm ? 1 : norm$1));
  897. });
  898. result.score = totalScore;
  899. });
  900. }
  901. function transformMatches(result, data) {
  902. const matches = result.matches;
  903. data.matches = [];
  904. if (!isDefined(matches)) return;
  905. matches.forEach((match) => {
  906. if (!isDefined(match.indices) || !match.indices.length) return;
  907. const { indices, value } = match;
  908. let obj = {
  909. indices,
  910. value
  911. };
  912. if (match.key) obj.key = match.key.src;
  913. if (match.idx > -1) obj.refIndex = match.idx;
  914. data.matches.push(obj);
  915. });
  916. }
  917. function transformScore(result, data) {
  918. data.score = result.score;
  919. }
  920. function format(results, docs, { includeMatches = Config.includeMatches, includeScore = Config.includeScore } = {}) {
  921. const transformers = [];
  922. if (includeMatches) transformers.push(transformMatches);
  923. if (includeScore) transformers.push(transformScore);
  924. return results.map((result) => {
  925. const { idx } = result;
  926. const data = {
  927. item: docs[idx],
  928. refIndex: idx
  929. };
  930. if (transformers.length) transformers.forEach((transformer) => {
  931. transformer(result, data);
  932. });
  933. return data;
  934. });
  935. }
  936. var Fuse = class {
  937. constructor(docs, options = {}, index) {
  938. this.options = {
  939. ...Config,
  940. ...options
  941. };
  942. if (this.options.useExtendedSearch && false);
  943. this._keyStore = new KeyStore(this.options.keys);
  944. this.setCollection(docs, index);
  945. }
  946. setCollection(docs, index) {
  947. this._docs = docs;
  948. if (index && !(index instanceof FuseIndex)) throw new Error(INCORRECT_INDEX_TYPE);
  949. this._myIndex = index || createIndex(this.options.keys, this._docs, {
  950. getFn: this.options.getFn,
  951. fieldNormWeight: this.options.fieldNormWeight
  952. });
  953. }
  954. add(doc) {
  955. if (!isDefined(doc)) return;
  956. this._docs.push(doc);
  957. this._myIndex.add(doc);
  958. }
  959. remove(predicate = () => false) {
  960. const results = [];
  961. for (let i = 0, len = this._docs.length; i < len; i += 1) {
  962. const doc = this._docs[i];
  963. if (predicate(doc, i)) {
  964. this.removeAt(i);
  965. i -= 1;
  966. len -= 1;
  967. results.push(doc);
  968. }
  969. }
  970. return results;
  971. }
  972. removeAt(idx) {
  973. this._docs.splice(idx, 1);
  974. this._myIndex.removeAt(idx);
  975. }
  976. getIndex() {
  977. return this._myIndex;
  978. }
  979. search(query, { limit = -1 } = {}) {
  980. const { includeMatches, includeScore, shouldSort, sortFn, ignoreFieldNorm } = this.options;
  981. let results = isString(query) ? isString(this._docs[0]) ? this._searchStringList(query) : this._searchObjectList(query) : this._searchLogical(query);
  982. computeScore(results, { ignoreFieldNorm });
  983. if (shouldSort) results.sort(sortFn);
  984. if (isNumber(limit) && limit > -1) results = results.slice(0, limit);
  985. return format(results, this._docs, {
  986. includeMatches,
  987. includeScore
  988. });
  989. }
  990. _searchStringList(query) {
  991. const searcher = createSearcher(query, this.options);
  992. const { records } = this._myIndex;
  993. const results = [];
  994. records.forEach(({ v: text, i: idx, n: norm$1 }) => {
  995. if (!isDefined(text)) return;
  996. const { isMatch, score, indices } = searcher.searchIn(text);
  997. if (isMatch) results.push({
  998. item: text,
  999. idx,
  1000. matches: [{
  1001. score,
  1002. value: text,
  1003. norm: norm$1,
  1004. indices
  1005. }]
  1006. });
  1007. });
  1008. return results;
  1009. }
  1010. _searchLogical(query) {
  1011. const expression = parse(query, this.options);
  1012. const evaluate = (node, item, idx) => {
  1013. if (!node.children) {
  1014. const { keyId, searcher } = node;
  1015. const matches = this._findMatches({
  1016. key: this._keyStore.get(keyId),
  1017. value: this._myIndex.getValueForItemAtKeyId(item, keyId),
  1018. searcher
  1019. });
  1020. if (matches && matches.length) return [{
  1021. idx,
  1022. item,
  1023. matches
  1024. }];
  1025. return [];
  1026. }
  1027. const res = [];
  1028. for (let i = 0, len = node.children.length; i < len; i += 1) {
  1029. const child = node.children[i];
  1030. const result = evaluate(child, item, idx);
  1031. if (result.length) res.push(...result);
  1032. else if (node.operator === LogicalOperator.AND) return [];
  1033. }
  1034. return res;
  1035. };
  1036. const records = this._myIndex.records;
  1037. const resultMap = {};
  1038. const results = [];
  1039. records.forEach(({ $: item, i: idx }) => {
  1040. if (isDefined(item)) {
  1041. let expResults = evaluate(expression, item, idx);
  1042. if (expResults.length) {
  1043. if (!resultMap[idx]) {
  1044. resultMap[idx] = {
  1045. idx,
  1046. item,
  1047. matches: []
  1048. };
  1049. results.push(resultMap[idx]);
  1050. }
  1051. expResults.forEach(({ matches }) => {
  1052. resultMap[idx].matches.push(...matches);
  1053. });
  1054. }
  1055. }
  1056. });
  1057. return results;
  1058. }
  1059. _searchObjectList(query) {
  1060. const searcher = createSearcher(query, this.options);
  1061. const { keys, records } = this._myIndex;
  1062. const results = [];
  1063. records.forEach(({ $: item, i: idx }) => {
  1064. if (!isDefined(item)) return;
  1065. let matches = [];
  1066. keys.forEach((key, keyIndex) => {
  1067. matches.push(...this._findMatches({
  1068. key,
  1069. value: item[keyIndex],
  1070. searcher
  1071. }));
  1072. });
  1073. if (matches.length) results.push({
  1074. idx,
  1075. item,
  1076. matches
  1077. });
  1078. });
  1079. return results;
  1080. }
  1081. _findMatches({ key, value, searcher }) {
  1082. if (!isDefined(value)) return [];
  1083. let matches = [];
  1084. if (isArray(value)) value.forEach(({ v: text, i: idx, n: norm$1 }) => {
  1085. if (!isDefined(text)) return;
  1086. const { isMatch, score, indices } = searcher.searchIn(text);
  1087. if (isMatch) matches.push({
  1088. score,
  1089. key,
  1090. value: text,
  1091. idx,
  1092. norm: norm$1,
  1093. indices
  1094. });
  1095. });
  1096. else {
  1097. const { v: text, n: norm$1 } = value;
  1098. const { isMatch, score, indices } = searcher.searchIn(text);
  1099. if (isMatch) matches.push({
  1100. score,
  1101. key,
  1102. value: text,
  1103. norm: norm$1,
  1104. indices
  1105. });
  1106. }
  1107. return matches;
  1108. }
  1109. };
  1110. Fuse.version = "7.1.0";
  1111. Fuse.createIndex = createIndex;
  1112. Fuse.parseIndex = parseIndex;
  1113. Fuse.config = Config;
  1114. Fuse.parseQuery = parse;
  1115. register(ExtendedSearch);
  1116. const useSearchResults = defineStore("search", () => {
  1117. const state = useOptionsStore();
  1118. const data = usePayloadStore();
  1119. const filtered = computed(() => {
  1120. let modules = data.modules || [];
  1121. if (!state.search.includeUnreached) modules = modules.filter((item) => item.sourceSize);
  1122. if (!state.search.includeNodeModules) modules = modules.filter((item) => !item.id.includes("/node_modules/"));
  1123. if (!state.search.includeVirtual) modules = modules.filter((item) => !item.virtual);
  1124. return modules;
  1125. });
  1126. const results = computed(() => {
  1127. const modules = filtered.value;
  1128. if (!state.search.text) return modules;
  1129. if (state.search.exactSearch) return modules.filter((item) => item.id.includes(state.search.text) || item.plugins.some((plugin) => plugin.name.includes(state.search.text)));
  1130. else {
  1131. const fuse = new Fuse(modules, {
  1132. shouldSort: true,
  1133. keys: ["id", "plugins"]
  1134. });
  1135. return fuse.search(state.search.text).map((i) => i.item);
  1136. }
  1137. });
  1138. const resultsSorted = computed(() => {
  1139. if (state.search.text) return results.value;
  1140. const cloned = [...results.value];
  1141. if (state.view.sort === "time-asc") cloned.sort((a, b) => b.totalTime - a.totalTime);
  1142. if (state.view.sort === "time-desc") cloned.sort((a, b) => a.totalTime - b.totalTime);
  1143. return cloned;
  1144. });
  1145. return {
  1146. results,
  1147. resultsSorted,
  1148. filtered
  1149. };
  1150. });
  1151. export { useSearchResults };