@flesh-and-blood/search 5.3.1 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -14,19 +14,19 @@ npm i @flesh-and-blood/search @flesh-and-blood/types
14
14
 
15
15
  ```ts
16
16
  import Searcher from "@flesh-and-blood/search";
17
- import { cards } from "@flesh-and-blood/cards";
17
+ import { cards, releases } from "@flesh-and-blood/cards";
18
18
 
19
- const searcher = new Searcher(cards);
19
+ const searcher = new Searcher(cards, { releases });
20
20
  const { searchResults } = searcher.search("rhinar go again");
21
21
  ```
22
22
 
23
- - `new Searcher(cards, additionalHeroes?, additionalSets?)`
23
+ - `new Searcher(cards, { releases, additionalHeroes? })`, or `{ index }` to share a catalogue index
24
+ built with `getCatalogueIndex(cards, releases)`
24
25
  - `.search(text)` → `SearchResults`: `{ searchResults: SearchCard[], appliedFilters, keywords, attributes }`
25
26
 
26
27
  Data-only modules are available as subpath imports (handy for lazy-loaded UI like a search-bar dropdown):
27
28
 
28
29
  ```ts
29
- import { abbreviations } from "@flesh-and-blood/search/abbreviations";
30
30
  import { shorthands } from "@flesh-and-blood/search/shorthands";
31
31
  ```
32
32
 
@@ -34,7 +34,7 @@ import { shorthands } from "@flesh-and-blood/search/shorthands";
34
34
 
35
35
  - Default export: **`Searcher`**, the search engine
36
36
  - Types: `SearchResults`, `SearchCard`
37
- - Data modules (subpath imports): `abbreviations`, `shorthands`, `memes`
37
+ - Data modules (subpath imports): `shorthands`, `memes`
38
38
  - Filter / meta-filter / helper utilities (`filters`, `metaFilters`, `helpers`, `constants`, `related`)
39
39
 
40
40
  ## Working with this project
@@ -1,4 +1,4 @@
1
- export declare const PUNCTUATION: RegExp;
1
+ export { PUNCTUATION } from "@flesh-and-blood/types";
2
2
  /**
3
3
  * The markdown emphasis that wraps keywords in a card's functional text. Kept
4
4
  * out of `PUNCTUATION` because an asterisk is also a printed card value:
package/dist/constants.js CHANGED
@@ -1,4 +1,4 @@
1
- const PUNCTUATION = /[!"#$%&'’(),./:;<=>?@[\]^_`|~]/g;
1
+ import { PUNCTUATION } from "@flesh-and-blood/types";
2
2
  const MARKUP = /\*/g;
3
3
  export {
4
4
  MARKUP,
@@ -1,4 +1,4 @@
1
- import { Bond, Card, Class, Flow, Foiling, Fusion, Hero, Keyword, Meta, Printing, Rarity, Release, Shorthand, Subtype, Talent, Trait, Treatment, Type } from "@flesh-and-blood/types";
1
+ import { Bond, Card, Class, Flow, Foiling, Fusion, Hero, Keyword, Meta, Printing, Rarity, Shorthand, Subtype, Talent, Trait, Treatment, Type } from "@flesh-and-blood/types";
2
2
  /**
3
3
  * Which filter a key names, rather than how it was spelled: every alias of a
4
4
  * filter answers with the one category, and a key naming no filter answers
@@ -11,9 +11,10 @@ export declare const FilterCategory: {
11
11
  readonly Artist: "artist";
12
12
  readonly Banned: "banned";
13
13
  readonly Bond: "bond";
14
- readonly Chain: "chain";
15
14
  readonly Class: "class";
16
15
  readonly Cost: "cost";
16
+ readonly CreatedBy: "createdby";
17
+ readonly Creates: "creates";
17
18
  readonly Defense: "defense";
18
19
  readonly Flow: "flow";
19
20
  readonly Foiling: "foiling";
@@ -168,8 +169,9 @@ export interface FilterToPropertyMapping extends CardPropertyMapping {
168
169
  * It is not the set of spellings the parse accepts, which is wider, since
169
170
  * the foiling, treatment, rarity, legality and meta resolvers each take
170
171
  * abbreviations of their own. A filter reading free text (`artist`, `name`,
171
- * `text`, `typetext`), a card name (`chain`, `references`, `referencedby`),
172
- * a set identifier (`print`), a date (`year`) or a number carries none.
172
+ * `text`, `typetext`), a card name or group (`creates`, `createdby`,
173
+ * `references`, `referencedby`), a set identifier (`print`), a date
174
+ * (`year`) or a number carries none.
173
175
  */
174
176
  vocabulary?: readonly string[];
175
177
  }
@@ -274,12 +276,6 @@ export declare const filtersToCardPropertyMappings: {
274
276
  isArray: true;
275
277
  partialMatch: true;
276
278
  };
277
- chain: {
278
- category: "chain";
279
- canonicalAlias: string;
280
- kind: "partialMatch";
281
- property: "n/a";
282
- };
283
279
  co: {
284
280
  category: "cost";
285
281
  canonicalAlias: string;
@@ -298,6 +294,18 @@ export declare const filtersToCardPropertyMappings: {
298
294
  isNumber: true;
299
295
  partialMatch: true;
300
296
  };
297
+ createdby: {
298
+ category: "createdby";
299
+ canonicalAlias: string;
300
+ kind: "partialMatch";
301
+ property: "n/a";
302
+ };
303
+ creates: {
304
+ category: "creates";
305
+ canonicalAlias: string;
306
+ kind: "partialMatch";
307
+ property: "n/a";
308
+ };
301
309
  color: {
302
310
  category: "pitch";
303
311
  canonicalAlias: string;
@@ -457,6 +465,18 @@ export declare const filtersToCardPropertyMappings: {
457
465
  specialProperty: "specialLife";
458
466
  isNumber: true;
459
467
  };
468
+ madeby: {
469
+ category: "createdby";
470
+ canonicalAlias: string;
471
+ kind: "partialMatch";
472
+ property: "n/a";
473
+ };
474
+ makes: {
475
+ category: "creates";
476
+ canonicalAlias: string;
477
+ kind: "partialMatch";
478
+ property: "n/a";
479
+ };
460
480
  meta: {
461
481
  category: "is";
462
482
  canonicalAlias: string;
@@ -591,7 +611,6 @@ export declare const filtersToCardPropertyMappings: {
591
611
  category: "set";
592
612
  canonicalAlias: string;
593
613
  kind: "partialMatch";
594
- vocabulary: Release[];
595
614
  property: "sets";
596
615
  isArray: true;
597
616
  partialMatch: true;
@@ -600,7 +619,6 @@ export declare const filtersToCardPropertyMappings: {
600
619
  category: "set";
601
620
  canonicalAlias: string;
602
621
  kind: "partialMatch";
603
- vocabulary: Release[];
604
622
  property: "sets";
605
623
  isArray: true;
606
624
  partialMatch: true;
@@ -9,7 +9,6 @@ import {
9
9
  Keyword,
10
10
  Meta,
11
11
  Rarity,
12
- Release,
13
12
  Shorthand,
14
13
  Subtype,
15
14
  Talent,
@@ -23,9 +22,10 @@ const FilterCategory = {
23
22
  Artist: "artist",
24
23
  Banned: "banned",
25
24
  Bond: "bond",
26
- Chain: "chain",
27
25
  Class: "class",
28
26
  Cost: "cost",
27
+ CreatedBy: "createdby",
28
+ Creates: "creates",
29
29
  Defense: "defense",
30
30
  Flow: "flow",
31
31
  Foiling: "foiling",
@@ -102,12 +102,6 @@ const bondFilter = {
102
102
  property: "bonds",
103
103
  isArray: true
104
104
  };
105
- const chainFilter = {
106
- category: FilterCategory.Chain,
107
- canonicalAlias: "chain",
108
- kind: FilterKind.PartialMatch,
109
- property: NO_CARD_PROPERTY
110
- };
111
105
  const classFilter = {
112
106
  category: FilterCategory.Class,
113
107
  canonicalAlias: "c",
@@ -126,6 +120,18 @@ const costFilter = {
126
120
  isNumber: true,
127
121
  partialMatch: true
128
122
  };
123
+ const createdByFilter = {
124
+ category: FilterCategory.CreatedBy,
125
+ canonicalAlias: "createdby",
126
+ kind: FilterKind.PartialMatch,
127
+ property: NO_CARD_PROPERTY
128
+ };
129
+ const createsFilter = {
130
+ category: FilterCategory.Creates,
131
+ canonicalAlias: "creates",
132
+ kind: FilterKind.PartialMatch,
133
+ property: NO_CARD_PROPERTY
134
+ };
129
135
  const defenseFilter = {
130
136
  category: FilterCategory.Defense,
131
137
  canonicalAlias: "d",
@@ -254,7 +260,6 @@ const setFilter = {
254
260
  category: FilterCategory.Set,
255
261
  canonicalAlias: "s",
256
262
  kind: FilterKind.PartialMatch,
257
- vocabulary: Object.values(Release),
258
263
  property: "sets",
259
264
  isArray: true,
260
265
  partialMatch: true
@@ -358,9 +363,10 @@ const filtersToCardPropertyMappings = {
358
363
  bonds: bondFilter,
359
364
  c: classFilter,
360
365
  class: classFilter,
361
- chain: chainFilter,
362
366
  co: costFilter,
363
367
  cost: costFilter,
368
+ createdby: createdByFilter,
369
+ creates: createsFilter,
364
370
  color: pitchFilter,
365
371
  d: defenseFilter,
366
372
  def: defenseFilter,
@@ -381,6 +387,8 @@ const filtersToCardPropertyMappings = {
381
387
  hero: legalFilter,
382
388
  li: lifeFilter,
383
389
  life: lifeFilter,
390
+ madeby: createdByFilter,
391
+ makes: createsFilter,
384
392
  meta: metaFilter,
385
393
  n: nameFilter,
386
394
  name: nameFilter,
@@ -26,7 +26,6 @@ export interface FilterTerm {
26
26
  /** What a resolver reads besides the term itself. */
27
27
  export interface FilterResolverContext {
28
28
  additionalHeroes: Hero[];
29
- additionalSets: Release[];
30
29
  index: CatalogueIndex;
31
30
  today: string;
32
31
  }
@@ -2,10 +2,7 @@ import {
2
2
  Foiling,
3
3
  Meta,
4
4
  Rarity,
5
- Release,
6
- setIdentifierToSetMappings,
7
- Treatment,
8
- Type
5
+ Treatment
9
6
  } from "@flesh-and-blood/types";
10
7
  import {
11
8
  FilterCategory,
@@ -15,11 +12,6 @@ import {
15
12
  } from "./filterMappings.js";
16
13
  import { getNormalizedFilterValue, getTextWithoutMarkup } from "./helpers.js";
17
14
  import { getMetaFilterResolution } from "./metaFilters.js";
18
- import {
19
- getCardsByName,
20
- getCardsReferencedBy,
21
- getCardsReferencing
22
- } from "./searchIndex.js";
23
15
  const getSharedModifier = (filterValues) => {
24
16
  const [firstValue] = filterValues;
25
17
  const firstModifier = firstValue?.modifier;
@@ -133,34 +125,24 @@ const getPitchResolution = (term) => {
133
125
  unresolvedValues: []
134
126
  };
135
127
  };
136
- const releasesByName = /* @__PURE__ */ new Map();
137
- for (const release of Object.values(Release)) {
138
- const name = getNormalizedFilterValue(release);
139
- const releaseWithSameName = releasesByName.get(name);
140
- if (releaseWithSameName === void 0) {
141
- releasesByName.set(name, release);
142
- } else {
143
- throw new Error(
144
- `${releaseWithSameName} and ${release} are one name as a filter reads it, so a set filter naming it could reach either`
145
- );
146
- }
147
- }
148
- const getReleasesFromLookup = (lookup, value) => {
149
- const release = lookup.get(value);
150
- return release ? [release] : [];
151
- };
152
- const getMatchingReleasesFromValue = (value, additionalSets) => {
128
+ const getMatchingReleasesFromValue = (value, index) => {
153
129
  const rungs = [
154
- () => getReleasesFromLookup(releasesByName, value),
155
- () => getReleasesFromLookup(setIdentifierToSetMappings, value),
156
- () => Object.values(Release).filter(
157
- (release) => release.toLowerCase().includes(value)
158
- ),
159
130
  () => {
160
- const additionalSetFromValue = additionalSets.find(
161
- (additionalSet) => getNormalizedFilterValue(additionalSet) === value
162
- );
163
- return additionalSetFromValue ? [additionalSetFromValue] : [];
131
+ const releaseInfo = index.getReleaseByName(value);
132
+ return releaseInfo ? [releaseInfo.release] : [];
133
+ },
134
+ () => {
135
+ const releaseInfo = index.getReleaseBySetIdentifier(value);
136
+ return releaseInfo ? [releaseInfo.release] : [];
137
+ },
138
+ () => {
139
+ const releasesNamingValue = [];
140
+ for (const { release } of index.releases) {
141
+ if (release.toLowerCase().includes(value)) {
142
+ releasesNamingValue.push(release);
143
+ }
144
+ }
145
+ return releasesNamingValue;
164
146
  }
165
147
  ];
166
148
  const releases = [];
@@ -171,10 +153,10 @@ const getMatchingReleasesFromValue = (value, additionalSets) => {
171
153
  }
172
154
  return releases;
173
155
  };
174
- const getSetResolution = (term, { additionalSets }) => getVocabularyResolution(
156
+ const getSetResolution = (term, { index }) => getVocabularyResolution(
175
157
  term,
176
158
  "releases",
177
- (value) => getMatchingReleasesFromValue(value, additionalSets)
159
+ (value) => getMatchingReleasesFromValue(value, index)
178
160
  );
179
161
  const foilingValuesMapping = new Map(
180
162
  Object.entries({
@@ -401,55 +383,28 @@ const cardIdentifierFilter = {
401
383
  isString: true,
402
384
  isNormalized: true
403
385
  };
404
- const CHAIN_EXPANSION_LIMIT = 20;
405
- const getChainedCardIdentifiers = (index, names) => {
406
- const cardIdentifiers = /* @__PURE__ */ new Set();
407
- const cardsToExpand = [];
408
- const namesToExpand = /* @__PURE__ */ new Set();
409
- const unresolvedValues = [];
410
- const addToChain = (card) => {
411
- cardIdentifiers.add(card.cardIdentifier);
412
- if (!namesToExpand.has(card.name)) {
413
- namesToExpand.add(card.name);
414
- cardsToExpand.push(card);
415
- }
416
- };
417
- const addRelatedCardToChain = (card) => {
418
- if (!card.types.includes(Type.Hero)) {
419
- addToChain(card);
420
- }
421
- };
422
- for (const name of names) {
423
- const seedCards = getCardsByName(index, name);
424
- for (const seedCard of seedCards) {
425
- addToChain(seedCard);
426
- }
427
- if (seedCards.length === 0) {
428
- unresolvedValues.push(name);
429
- }
386
+ const getCardsByNameOrGroup = (index, value) => {
387
+ let cards = index.getCardsByExactName(value);
388
+ if (cards.length === 0) {
389
+ cards = index.getCardsByGroup(value);
430
390
  }
431
- let expansions = 0;
432
- while (expansions < cardsToExpand.length && expansions <= CHAIN_EXPANSION_LIMIT) {
433
- const cardToExpand = cardsToExpand[expansions];
434
- for (const referencedCard of getCardsReferencedBy(index, cardToExpand)) {
435
- addRelatedCardToChain(referencedCard);
436
- }
437
- const isSeed = expansions === 0;
438
- if (isSeed) {
439
- for (const referencingCard of getCardsReferencing(index, cardToExpand)) {
440
- addRelatedCardToChain(referencingCard);
441
- }
442
- }
443
- expansions++;
391
+ if (cards.length === 0) {
392
+ cards = index.getCardsByName(value);
444
393
  }
445
- return { cardIdentifiers, unresolvedValues };
394
+ return cards;
446
395
  };
447
- const getRelatedCardIdentifiers = (index, name, isNamedByFilter) => {
396
+ const getRelatedCardIdentifiers = (index, value, readRelation) => {
448
397
  const relatedCardIdentifiers = /* @__PURE__ */ new Set();
449
- for (const namedCard of getCardsByName(index, name)) {
450
- const cardsInRelation = isNamedByFilter ? getCardsReferencedBy(index, namedCard) : getCardsReferencing(index, namedCard);
451
- for (const relatedCard of cardsInRelation) {
452
- relatedCardIdentifiers.add(relatedCard.cardIdentifier);
398
+ for (const card of getCardsByNameOrGroup(index, value)) {
399
+ for (const relatedCard of readRelation(index, card.cardIdentifier)) {
400
+ const isCycleAdded = relatedCardIdentifiers.has(
401
+ relatedCard.cardIdentifier
402
+ );
403
+ if (!isCycleAdded) {
404
+ for (const pitch of index.getPitchCycle(relatedCard.cardIdentifier)) {
405
+ relatedCardIdentifiers.add(pitch.cardIdentifier);
406
+ }
407
+ }
453
408
  }
454
409
  }
455
410
  return relatedCardIdentifiers;
@@ -482,11 +437,15 @@ const getCardIdentifiersFilter = (cardIdentifiers, isExcluded) => ({
482
437
  isExcluded,
483
438
  isOr: true
484
439
  });
485
- const getRelationResolution = ({ filterValues, isAnd, isExcluded }, getCardIdentifiersFromValue) => {
440
+ const getRelationResolver = (readRelation) => ({ filterValues, isAnd, isExcluded }, { index }) => {
486
441
  const cardIdentifiersByValue = [];
487
442
  const unresolvedValues = [];
488
443
  for (const { value } of filterValues) {
489
- const cardIdentifiers = getCardIdentifiersFromValue(value);
444
+ const cardIdentifiers = getRelatedCardIdentifiers(
445
+ index,
446
+ value,
447
+ readRelation
448
+ );
490
449
  cardIdentifiersByValue.push(cardIdentifiers);
491
450
  if (cardIdentifiers.size === 0) {
492
451
  unresolvedValues.push(value);
@@ -502,38 +461,39 @@ const getRelationResolution = ({ filterValues, isAnd, isExcluded }, getCardIdent
502
461
  unresolvedValues
503
462
  };
504
463
  };
505
- const getChainResolution = (term, { index }) => {
506
- const { cardIdentifiers, unresolvedValues } = getChainedCardIdentifiers(
507
- index,
508
- term.filterValues.map(({ value }) => value)
509
- );
510
- return {
511
- appliedFilters: [
512
- getCardIdentifiersFilter(cardIdentifiers, term.isExcluded)
513
- ],
514
- unresolvedValues
515
- };
516
- };
517
- const getReferencedByResolution = (term, { index }) => getRelationResolution(
518
- term,
519
- (value) => getRelatedCardIdentifiers(index, value, true)
520
- );
521
- const getReferencesResolution = (term, { index }) => getRelationResolution(
522
- term,
523
- (value) => getRelatedCardIdentifiers(index, value, false)
524
- );
525
464
  const resolverByFilterCategory = /* @__PURE__ */ new Map([
526
465
  [FilterCategory.Artist, getArtistResolution],
527
466
  [FilterCategory.Banned, getLegalityResolution],
528
- [FilterCategory.Chain, getChainResolution],
467
+ [
468
+ FilterCategory.CreatedBy,
469
+ getRelationResolver(
470
+ (index, cardIdentifier) => index.getCreates(cardIdentifier)
471
+ )
472
+ ],
473
+ [
474
+ FilterCategory.Creates,
475
+ getRelationResolver(
476
+ (index, cardIdentifier) => index.getCreatedBy(cardIdentifier)
477
+ )
478
+ ],
529
479
  [FilterCategory.Foiling, getFoilingResolution],
530
480
  [FilterCategory.Is, getMetaResolution],
531
481
  [FilterCategory.Legal, getLegalityResolution],
532
482
  [FilterCategory.Pitch, getPitchResolution],
533
483
  [FilterCategory.Print, getPrintResolution],
534
484
  [FilterCategory.Rarity, getRarityResolution],
535
- [FilterCategory.ReferencedBy, getReferencedByResolution],
536
- [FilterCategory.References, getReferencesResolution],
485
+ [
486
+ FilterCategory.ReferencedBy,
487
+ getRelationResolver(
488
+ (index, cardIdentifier) => index.getReferences(cardIdentifier)
489
+ )
490
+ ],
491
+ [
492
+ FilterCategory.References,
493
+ getRelationResolver(
494
+ (index, cardIdentifier) => index.getReferencedBy(cardIdentifier)
495
+ )
496
+ ],
537
497
  [FilterCategory.Set, getSetResolution],
538
498
  [FilterCategory.Treatment, getTreatmentResolution]
539
499
  ]);
package/dist/filters.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Hero, Release } from "@flesh-and-blood/types";
1
+ import { Hero } from "@flesh-and-blood/types";
2
2
  import type { AppliedFilter } from "./filterMappings.js";
3
3
  import type { QueryAttributes } from "./filterResolvers.js";
4
4
  import { CatalogueIndex } from "./searchIndex.js";
@@ -10,7 +10,7 @@ export { RARITY_VALUES_MAPPING } from "./filterResolvers.js";
10
10
  * themselves as well, for a reader asking what a query means without running
11
11
  * it.
12
12
  */
13
- export declare const getKeywordsAndAppliedFiltersFromText: (text: string, index: CatalogueIndex, additionalHeroes?: Hero[], additionalSets?: Release[], today?: string) => {
13
+ export declare const getKeywordsAndAppliedFiltersFromText: (text: string, index: CatalogueIndex, additionalHeroes?: Hero[], today?: string) => {
14
14
  appliedFilters: AppliedFilter[];
15
15
  attributes: QueryAttributes;
16
16
  keywords: string[];
package/dist/filters.js CHANGED
@@ -1,9 +1,8 @@
1
1
  import { getParsedQuery } from "./queryParse.js";
2
2
  import { RARITY_VALUES_MAPPING } from "./filterResolvers.js";
3
- const getKeywordsAndAppliedFiltersFromText = (text, index, additionalHeroes = [], additionalSets = [], today) => {
3
+ const getKeywordsAndAppliedFiltersFromText = (text, index, additionalHeroes = [], today) => {
4
4
  const { appliedFilters, attributes, keywords } = getParsedQuery(text, index, {
5
5
  additionalHeroes,
6
- additionalSets,
7
6
  today
8
7
  });
9
8
  return { appliedFilters, attributes, keywords };
package/dist/helpers.d.ts CHANGED
@@ -1,11 +1,6 @@
1
+ export { getNormalizedFilterValue } from "@flesh-and-blood/types";
1
2
  export declare const getCleanText: (text: string) => string;
2
3
  export declare const getNormalizedText: (text: string) => string;
3
- /**
4
- * A filter value as a filter reads it, which is how a query's values arrive
5
- * and how the values a filter declares have to be compared against them:
6
- * neither the case nor the punctuation a value was written with is part of it.
7
- */
8
- export declare const getNormalizedFilterValue: (value: string) => string;
9
4
  export declare const getTextWithoutMarkup: (text: string) => string;
10
5
  /**
11
6
  * Text built into a pattern rather than matched by one. A hyphen is escaped
package/dist/helpers.js CHANGED
@@ -1,7 +1,8 @@
1
- import { MARKUP, PUNCTUATION } from "./constants.js";
1
+ import { PUNCTUATION } from "@flesh-and-blood/types";
2
+ import { MARKUP } from "./constants.js";
3
+ import { getNormalizedFilterValue } from "@flesh-and-blood/types";
2
4
  const getCleanText = (text) => getNormalizedText(text.toLowerCase().trim().replace(PUNCTUATION, ""));
3
5
  const getNormalizedText = (text) => text.normalize("NFD").replace(/\p{Diacritic}/gu, "");
4
- const getNormalizedFilterValue = (value) => value.toLowerCase().replace(PUNCTUATION, "");
5
6
  const getTextWithoutMarkup = (text) => text.replace(MARKUP, "");
6
7
  const getEscapedForRegExp = (text) => text.replace(/[.*+?^${}()|[\]\\-]/g, "\\$&");
7
8
  export {
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var Kt=Object.create;var le=Object.defineProperty;var _t=Object.getOwnPropertyDescriptor;var $t=Object.getOwnPropertyNames;var zt=Object.getPrototypeOf,Gt=Object.prototype.hasOwnProperty;var Wt=(e,t)=>{for(var r in t)le(e,r,{get:t[r],enumerable:!0})},Ye=(e,t,r,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of $t(t))!Gt.call(e,a)&&a!==r&&le(e,a,{get:()=>t[a],enumerable:!(s=_t(t,a))||s.enumerable});return e};var Yt=(e,t,r)=>(r=e!=null?Kt(zt(e)):{},Ye(t||!e||!e.__esModule?le(r,"default",{value:e,enumerable:!0}):r,e)),qt=e=>Ye(le({},"__esModule",{value:!0}),e);var Ls={};Wt(Ls,{FilterCategory:()=>l,FilterKind:()=>m,FilterProperty:()=>G,MARKUP:()=>Me,NO_CARD_PROPERTY:()=>K,PUNCTUATION:()=>k,RARITY_VALUES_MAPPING:()=>De,aliasesByFilterCategory:()=>J,availableExclusions:()=>_,availableModifiers:()=>Se,default:()=>Ht,filterCard:()=>jt,filtersToCardPropertyMappings:()=>Z,getCardsByName:()=>ye,getCardsReferencedBy:()=>Ce,getCardsReferencing:()=>me,getCatalogueIndex:()=>we,getCleanText:()=>B,getEscapedForRegExp:()=>X,getExcludedMetaFilters:()=>Ie,getFilterCategory:()=>re,getFilterMapping:()=>ge,getFilterTokenSpansForKey:()=>us,getFilterValue:()=>je,getIncompleteFilterToken:()=>He,getIsExcludedToken:()=>ps,getIsValueInFilterVocabulary:()=>ke,getKeywordsAndAppliedFiltersFromText:()=>Bs,getMetaFilterResolution:()=>se,getMetaFilters:()=>fr,getNormalizedFilterValue:()=>V,getNormalizedText:()=>z,getParsedQuery:()=>ie,getQueryFilterToken:()=>Fe,getQueryTokenSpans:()=>he,getQuotedValue:()=>fs,getResolvedFilterKey:()=>Qe,getSuggestedFilterKey:()=>Ve,getTextWithoutMarkup:()=>q,getTokensReferencedByCards:()=>Os,getUnquotedValue:()=>Te,getValuePartsFromFilterValue:()=>Ot,getValuesFromFilterValue:()=>Ue,multiWordShorthands:()=>_e,shorthands:()=>Ke,singleWordShorthands:()=>$e});module.exports=qt(Ls);var xe=require("@flesh-and-blood/types"),We=Yt(require("fuse.js"),1);var k=/[!"#$%&'’(),./:;<=>?@[\]^_`|~]/g,Me=/\*/g;var T=require("@flesh-and-blood/types");var B=e=>z(e.toLowerCase().trim().replace(k,"")),z=e=>e.normalize("NFD").replace(/\p{Diacritic}/gu,""),V=e=>e.toLowerCase().replace(k,""),q=e=>e.replace(Me,""),X=e=>e.replace(/[.*+?^${}()|[\]\\-]/g,"\\$&");var l={Arcane:"arcane",Artist:"artist",Banned:"banned",Bond:"bond",Chain:"chain",Class:"class",Cost:"cost",Defense:"defense",Flow:"flow",Foiling:"foiling",Fusion:"fusion",Intellect:"intellect",Is:"is",Keyword:"keyword",Legal:"legal",Life:"life",Name:"name",Pitch:"pitch",Power:"power",Print:"print",Rarity:"rarity",ReferencedBy:"referencedby",References:"references",Set:"set",Shorthand:"shorthand",Specialization:"specialization",Subtype:"subtype",Talent:"talent",Text:"text",Trait:"trait",Treatment:"treatment",Type:"type",TypeText:"typetext",Year:"year"},m={Comparator:"comparator",ExactMatch:"exactMatch",PartialMatch:"partialMatch"},Se=[">=",">","<=","<"],_=["!","-"],K="n/a",gt=[...Object.values(T.Format),...Object.values(T.Hero)],Xt={category:l.Arcane,canonicalAlias:"arcane",kind:m.Comparator,property:"arcane",specialProperty:"specialArcane",isNumber:!0,partialMatch:!0},be={category:l.Artist,canonicalAlias:"art",kind:m.PartialMatch,property:"artists",isArray:!0,partialMatch:!0},qe={category:l.Banned,canonicalAlias:"banned",kind:m.ExactMatch,vocabulary:gt,property:K,isMeta:!0},Xe={category:l.Bond,canonicalAlias:"bond",kind:m.ExactMatch,vocabulary:Object.values(T.Bond),property:"bonds",isArray:!0},Zt={category:l.Chain,canonicalAlias:"chain",kind:m.PartialMatch,property:K},Ze={category:l.Class,canonicalAlias:"c",kind:m.PartialMatch,vocabulary:Object.values(T.Class),property:"classes",isArray:!0,partialMatch:!0},Je={category:l.Cost,canonicalAlias:"co",kind:m.Comparator,property:"cost",specialProperty:"specialCost",isNumber:!0,partialMatch:!0},te={category:l.Defense,canonicalAlias:"d",kind:m.Comparator,property:"defense",specialProperty:"specialDefense",isNumber:!0},et={category:l.Flow,canonicalAlias:"flow",kind:m.ExactMatch,vocabulary:Object.values(T.Flow),property:"flows",isArray:!0},tt={category:l.Foiling,canonicalAlias:"foil",kind:m.ExactMatch,vocabulary:Object.values(T.Foiling),nestedProperty:"foiling",property:"printings",isArray:!0},rt={category:l.Fusion,canonicalAlias:"f",kind:m.ExactMatch,vocabulary:Object.values(T.Fusion),property:"fusions",isArray:!0},st={category:l.Intellect,canonicalAlias:"i",kind:m.Comparator,property:"intellect",isNumber:!0},at={category:l.Keyword,canonicalAlias:"k",kind:m.ExactMatch,vocabulary:Object.values(T.Keyword),property:"keywords",isArray:!0},Ae={category:l.Legal,canonicalAlias:"l",kind:m.ExactMatch,vocabulary:gt,property:K,isMeta:!0},it={category:l.Life,canonicalAlias:"li",kind:m.Comparator,property:"life",specialProperty:"specialLife",isNumber:!0},nt={category:l.Is,canonicalAlias:"is",kind:m.ExactMatch,vocabulary:Object.values(T.Meta),property:"meta",isArray:!0},ot={category:l.Name,canonicalAlias:"name",kind:m.PartialMatch,property:"name",isString:!0,partialMatch:!0},Pe={category:l.Pitch,canonicalAlias:"p",kind:m.Comparator,property:"pitch",isNumber:!0},de={category:l.Power,canonicalAlias:"pwr",kind:m.Comparator,property:"power",specialProperty:"specialPower",isNumber:!0},ce={category:l.Print,canonicalAlias:"print",kind:m.PartialMatch,property:"setIdentifiers",isArray:!0,partialMatch:!0},lt={category:l.Rarity,canonicalAlias:"r",kind:m.ExactMatch,vocabulary:Object.values(T.Rarity),property:K,isMeta:!0},Jt={category:l.ReferencedBy,canonicalAlias:"referencedby",kind:m.PartialMatch,property:K},er={category:l.References,canonicalAlias:"references",kind:m.PartialMatch,property:K},dt={category:l.Set,canonicalAlias:"s",kind:m.PartialMatch,vocabulary:Object.values(T.Release),property:"sets",isArray:!0,partialMatch:!0},ve={category:l.Shorthand,canonicalAlias:"short",kind:m.PartialMatch,vocabulary:Object.values(T.Shorthand),property:"shorthands",isArray:!0,partialMatch:!0},pe={category:l.Specialization,canonicalAlias:"sp",kind:m.PartialMatch,vocabulary:Object.values(T.Hero),property:"specializations",isArray:!0,partialMatch:!0},ct={category:l.Subtype,canonicalAlias:"st",kind:m.ExactMatch,vocabulary:Object.values(T.Subtype),property:"subtypes",isArray:!0},pt={category:l.Type,canonicalAlias:"t",kind:m.ExactMatch,vocabulary:Object.values(T.Type),property:"types",isArray:!0},Re={category:l.Talent,canonicalAlias:"tal",kind:m.ExactMatch,vocabulary:Object.values(T.Talent),property:"talents",isArray:!0},tr={category:l.Text,canonicalAlias:"text",kind:m.PartialMatch,property:"functionalText",hasMarkup:!0,isString:!0,partialMatch:!0},rr={category:l.Trait,canonicalAlias:"trait",kind:m.PartialMatch,vocabulary:Object.values(T.Trait),property:"traits",isArray:!0,partialMatch:!0},ut={category:l.TypeText,canonicalAlias:"x",kind:m.PartialMatch,property:"typeText",isString:!0,partialMatch:!0},ue={category:l.Treatment,canonicalAlias:"treatment",kind:m.ExactMatch,vocabulary:Object.values(T.Treatment),nestedProperty:"treatments",property:"printings",isArray:!0,isNestedPropertyArray:!0},sr={category:l.Year,canonicalAlias:"year",kind:m.PartialMatch,property:"firstReleaseDate",isString:!0,partialMatch:!0},Z={arcane:Xt,a:be,artist:be,art:be,attack:de,b:te,block:te,banned:qe,bond:Xe,bonds:Xe,c:Ze,class:Ze,chain:Zt,co:Je,cost:Je,color:Pe,d:te,def:te,defense:te,flow:et,flows:et,f:rt,fusion:rt,foil:tt,foiling:tt,i:st,intellect:st,is:nt,k:at,keyword:at,l:Ae,legal:Ae,hero:Ae,li:it,life:it,meta:nt,n:ot,name:ot,p:Pe,pitch:Pe,pwr:de,pow:de,power:de,print:ce,printing:ce,printings:ce,prints:ce,r:lt,rarity:lt,referencedby:Jt,references:er,rf:qe,s:dt,set:dt,short:ve,shorthand:ve,shorthands:ve,sp:pe,spec:pe,specialization:pe,specializations:pe,st:ct,subtype:ct,t:pt,type:pt,tal:Re,talent:Re,talents:Re,text:tr,trait:rr,treat:ue,treatment:ue,var:ue,variation:ue,x:ut,typetext:ut,year:sr},ar=new Map(Object.entries(Z)),ge=e=>ar.get(e.toLowerCase()),re=e=>ge(e)?.category,ir=()=>{let e=Object.create(null);for(let[t,{category:r}]of Object.entries(Z)){let s=e[r];s?s.push(t):e[r]=[t]}return e},J=ir(),nr=()=>{let e=new Map,t=new Set,r=Object.values(Z);for(let s of r){let{vocabulary:a}=s;if(a&&!t.has(s)){t.add(s);for(let i of a){let n=V(i),o=e.get(n);o?o.push(s):e.set(n,[s])}}}return e},ft=nr(),ke=(e,t)=>!!ft.get(V(t))?.some(r=>r.category===e),or=(e,t)=>{let r=[],s=!0;for(let a of t){let i=(ft.get(V(a))||[]).filter(n=>n.category!==e);r=s?i:r.filter(n=>i.includes(n)),s=!1}return r},Ve=(e,t)=>{let r=or(e,t),[s]=r;return r.length===1?s.canonicalAlias:void 0};var ae=require("@flesh-and-blood/types");var d=require("@flesh-and-blood/types");var E=require("@flesh-and-blood/types");var G={BannedFormats:"bannedFormats",LegalFormats:"legalFormats",LegalHeroes:"legalHeroes"},fe=Array.from(Array(50).keys()).map(e=>`${e}`),lr=[{format:E.Format.ClassicConstructed,nicknames:["cc","classic"]},{format:E.Format.LivingLegend,nicknames:["cc ll","classic constructed ll","ll cc","ll","living legend"]},{format:E.Format.SilverAge,nicknames:["sage"]},{format:E.Format.GoldenAge,nicknames:["gage"]},{format:E.Format.UltimatePitFight,nicknames:["upf"]}],dr=Object.values(E.Format).map(e=>{let t=lr.find(({format:s})=>s===e),r=e.toLowerCase().replaceAll(k,"");return t?{...t,format:r}:{format:r}}),cr=Object.values(E.Hero).map(B),yt=e=>e.replaceAll(" ",""),pr=(e,t)=>{let r=yt(e),s,a=[];for(let n of t){let o=yt(n);o===r?s=n:o.startsWith(r)&&a.push(n)}let i=a.length===1;return s??(i?a[0]:void 0)},mt=["common","rare","super rare","majestic","legendary","fabled"],ur=({modifier:e,value:t})=>{let r=[],s=e==="<"||e==="<=",a=e===">="||e==="<=",i=s?[...mt].reverse():mt,n=!1;for(let o of i)n?r.push(o):o===t&&(n=!0,a&&r.push(o));return r},gr=(e,t)=>{let r=[];for(let s of e)s.modifier?r.push(...ur(s)):r.push(s.value);return{filterToPropertyMapping:{nestedProperty:"rarity",property:"printings",isArray:!0},isExcluded:t,isOr:!0,values:r}},Ct=(e,t,r,s)=>{let a=new Set([...cr,...r.map(B)]),i=[],n=[],o=[],c=[];for(let{value:p}of e){let g=dr.find(({format:f,nicknames:C})=>f===p||!!C&&C.includes(p));if(g)n.push(g.format);else{let f=pr(p,a);f?o.push(f):c.push(p)}}return n.length>0&&i.push({filterToPropertyMapping:{property:s,isArray:!0},values:n,isOr:!0,isExcluded:t}),o.length>0&&i.push({filterToPropertyMapping:{property:G.LegalHeroes,isArray:!0},values:o,isOr:!0,isExcluded:t}),{appliedFilters:i,unresolvedValues:c}},se=(e,t,{additionalHeroes:r=[],isExcluded:s=!1}={})=>{let a=re(e),i={appliedFilters:[],unresolvedValues:[]};return a===l.Legal?i=Ct(t,s,r,G.LegalFormats):a===l.Banned?i=Ct(t,s,r,G.BannedFormats):a===l.Rarity&&(i={appliedFilters:[gr(t,s)],unresolvedValues:[]}),i},fr=(e,t,r,s,a,i)=>se(r,s.map(n=>({modifier:a,value:n})),{additionalHeroes:i,isExcluded:e}).appliedFilters,yr=[{filterToPropertyMapping:{property:"cost",isNumber:!0},isExcluded:!0,values:fe},{filterToPropertyMapping:{property:"specialCost",isString:!0,partialMatch:!0},isExcluded:!0,values:["*","x"]},{filterToPropertyMapping:{property:"types",isArray:!0,partialMatch:!0},isExcluded:!0,values:["equipment","hero","placeholder","token","weapon"]}],mr=[{filterToPropertyMapping:{property:"defense",isNumber:!0},isExcluded:!0,values:fe},{filterToPropertyMapping:{property:"specialDefense",isString:!0,partialMatch:!0},isExcluded:!0,values:["*","x"]},{filterToPropertyMapping:{property:"types",isArray:!0,partialMatch:!0},isExcluded:!0,values:["hero","placeholder","token","weapon"]}],Cr=[{filterToPropertyMapping:{property:"pitch",isNumber:!0},isExcluded:!0,values:fe},{filterToPropertyMapping:{property:"types",isArray:!0,partialMatch:!0},isExcluded:!0,values:["equipment","hero","placeholder","token","weapon"]},{filterToPropertyMapping:{property:"isCardBack",isBoolean:!0},isExcluded:!0,values:["true"]}],hr=[{filterToPropertyMapping:{property:"power",isNumber:!0},isExcluded:!0,values:fe},{filterToPropertyMapping:{property:"specialPower",isString:!0,partialMatch:!0},isExcluded:!0,values:["*","x"]},{filterToPropertyMapping:{property:"types",isArray:!0,partialMatch:!0},isExcluded:!0,values:["equipment","hero","placeholder","token"]}],Fr=[{filterToPropertyMapping:{property:"talents",isArray:!0},isExcluded:!0,values:Object.values(E.Talent).map(e=>e.toLowerCase())}],Tr=[{filterToPropertyMapping:{property:"classes",isArray:!0},isExcluded:!0,values:Object.values(E.Class).map(e=>e.toLowerCase())}],xr=[{category:l.Class,filters:Tr},{category:l.Cost,filters:yr},{category:l.Defense,filters:mr},{category:l.Pitch,filters:Cr},{category:l.Power,filters:hr},{category:l.Talent,filters:Fr}],Mr=()=>{let e=new Map;for(let{category:t,filters:r}of xr)for(let s of J[t])for(let a of _)e.set(`${a}${s}`,r);return e},br=Mr(),Ie=e=>{let t=[],r=br.get(e);return r&&t.push(...r),t};var W=require("@flesh-and-blood/types");var Ar=3,Pr=e=>{let t=z(e.toLowerCase()).replace(/[^a-z\s-]/g,""),r=new Set;for(let s of[/[\s-]+/,/\s+/]){let a="";for(let i of t.split(s)){let n=i.replaceAll("-","");n&&(a+=n[0])}a.length>=Ar&&r.add(a)}return[...r]},ht=e=>B(e).replaceAll("-",""),Ft=(e,t,r)=>{let s=e.get(t);s?s.push(r):e.set(t,[r])},Tt=new WeakMap,j=Object.freeze([]),vr=Number.MAX_SAFE_INTEGER,xt=(e,t)=>{let r=new Map;for(let s of e)for(let a of t(s)||[]){let i=r.get(a);i?i.push(s):r.set(a,[s])}return r},Rr=e=>{let t=new Map;for(let r of e){let s=r.types.includes(W.Type.Hero)&&!r.isCardBack,a=s?W.CardRole.Hero:(0,W.getCardRole)(r);if(s||a!==W.CardRole.Hero){let n=t.get(a);n?n.push(r):t.set(a,[r])}}return t},Sr=e=>{let t,r,s,a,i,n,o,c=()=>{if(!t){let u=new Map,y=new Map,h=[],F=new Map,M=0;for(let w of e){u.set(w.cardIdentifier,w),y.set(w.cardIdentifier,M),M++;let S=B(w.name),Y=F.get(S);Y?Y.push(w):(F.set(S,[w]),h.push(S))}t={cardByCardIdentifier:u,corpusPositionByCardIdentifier:y,cleanedNames:h,pitchCycleByCleanedName:F}}return t},p=u=>{let{corpusPositionByCardIdentifier:y}=c(),h=({cardIdentifier:F})=>y.get(F)??vr;return[...u].sort((F,M)=>h(F)-h(M))},g=u=>c().cardByCardIdentifier.get(u),f=u=>{let{cardByCardIdentifier:y}=c(),h=[];for(let F of u||[]){let M=y.get(F);M&&h.push(M)}return p(h)},C=u=>{let y=new Map;return h=>{let F=y.get(h);if(!F){let M=g(h),w=f(M&&u(M)),S=w.length>0;F=S?w:j,S&&y.set(h,F)}return F}},b=u=>{let{pitchCycleByCleanedName:y}=c(),h=g(u);return h?y.get(B(h.name))??j:j},D=u=>{let{cleanedNames:y,pitchCycleByCleanedName:h}=c(),F=B(u),M=h.get(F);if(!M&&F.length>0){let S=y.find(Y=>Y.includes(F));S&&(M=h.get(S))}return M??j},I=u=>{let{pitchCycleByCleanedName:y}=c();return y.get(B(u))??j},P=u=>{if(!n){n=new Map;for(let y of e)for(let h of y.nicknames??[])Ft(n,ht(h),y)}return n.get(ht(u))??j},O=u=>{if(!o){o=new Map;for(let y of e)for(let h of Pr(y.name))Ft(o,h,y)}return o.get(u)??j},N=()=>{if(!i){let u=new Set;for(let y of e)for(let h of y.artists)u.add(h);i=[...u].sort((y,h)=>y.localeCompare(h,"en",{sensitivity:"base"}))}return i},Q=C(({oppositeSideCardIdentifiers:u})=>u),U=C(({referencedCards:u})=>u),$=u=>(r||(r=xt(e,({referencedCards:y})=>y)),r.get(u)??j),H=C(({createdExtras:u})=>u);return{cards:e,getCard:g,getPitchCycle:b,getCardsByName:D,getCardsByExactName:I,getCardsByNickname:P,getCardsByInitials:O,getArtists:N,getOppositeSide:Q,getReferences:U,getReferencedBy:$,getCreates:H,getCreatedBy:u=>(s||(s=xt(e,({createdExtras:y})=>y)),s.get(u)??j),getCreatedClosure:u=>{let y=new Map,h=new Set,F=[...u];for(let M of F)if(!h.has(M)){h.add(M);for(let S of H(M))y.set(S.cardIdentifier,S),F.push(S.cardIdentifier)}return p([...y.values()])},getByRole:u=>(a||(a=Rr(e)),a.get(u)??j),getCardsInCorpusOrder:p}},we=e=>{let t=Tt.get(e);return t||(t=Sr(e),Tt.set(e,t)),t},Ee=(e,t)=>e.getPitchCycle(t.cardIdentifier),ye=(e,t)=>e.getCardsByName(t),Mt=(e,t)=>{let r=new Map;for(let s of t)for(let a of Ee(e,s))r.set(a.cardIdentifier,a);return e.getCardsInCorpusOrder([...r.values()])},me=(e,t)=>{let r=[];for(let s of Ee(e,t))r.push(...e.getReferencedBy(s.cardIdentifier));return Mt(e,r)},Ce=(e,t)=>{let r=[];for(let s of Ee(e,t))r.push(...e.getReferences(s.cardIdentifier));return Mt(e,r)};var kr=e=>{let[t]=e,r=t?.modifier;return e.every(({modifier:a})=>a===r)?r:void 0},Be=({filterValues:e,isAnd:t,isExcluded:r,mapping:s})=>{let a=[];for(let{value:i}of e)a.push(s.hasMarkup?q(i):i);return{filterToPropertyMapping:s,filterValues:e,isAnd:t,isExcluded:r,isOr:!t&&a.length>1,modifier:kr(e),values:a}},vt=({isAnd:e,isExcluded:t,mapping:r},s)=>({filterToPropertyMapping:r,isAnd:e,isExcluded:t,isOr:!e&&s.length>1,values:s}),Vr=({category:e,filterValues:t,mapping:r})=>{let s=[];if(r.kind===m.ExactMatch&&!!r.vocabulary)for(let{value:i}of t)ke(e,i)||s.push(i);return s},Ir=e=>({appliedFilters:[Be(e)],unresolvedValues:Vr(e)}),Oe=({isExcluded:e},t,r)=>e?void 0:{[t]:r},Rt=(e,t)=>({appliedFilters:[Be(e)],attributes:Oe(e,t,e.filterValues.map(({value:r})=>r)),unresolvedValues:[]}),wr=e=>Rt(e,"artists"),Er=e=>Rt(e,"prints"),Le=(e,t,r)=>{let s=[],a=[],i=[];for(let{value:n}of e.filterValues){let o=r(n);if(o.length>0)for(let c of o)s.push(c),a.push(V(c));else i.push(n)}return{appliedFilters:[vt(e,a)],attributes:Oe(e,t,s),canonicalValues:a,unresolvedValues:i}},Nr=new Map(Object.entries({purple:4,blue:3,yellow:2,red:1,white:0})),Br=e=>{let t=[],r=[];for(let{modifier:s,value:a}of e.filterValues){let i=Nr.get(a),n=i===void 0?a:`${i}`;t.push({modifier:s,value:n}),r.push(n)}return{appliedFilters:[Be({...e,filterValues:t})],canonicalValues:r,unresolvedValues:[]}},Ne=new Map;for(let e of Object.values(d.Release)){let t=V(e),r=Ne.get(t);if(r===void 0)Ne.set(t,e);else throw new Error(`${r} and ${e} are one name as a filter reads it, so a set filter naming it could reach either`)}var bt=(e,t)=>{let r=e.get(t);return r?[r]:[]},Or=(e,t)=>{let r=[()=>bt(Ne,e),()=>bt(d.setIdentifierToSetMappings,e),()=>Object.values(d.Release).filter(a=>a.toLowerCase().includes(e)),()=>{let a=t.find(i=>V(i)===e);return a?[a]:[]}],s=[];for(let a of r)s.length===0&&s.push(...a());return s},Lr=(e,{additionalSets:t})=>Le(e,"releases",r=>Or(r,t)),Dr=new Map(Object.entries({r:d.Foiling.Rainbow,rf:d.Foiling.Rainbow,rainbow:d.Foiling.Rainbow,c:d.Foiling.Cold,cf:d.Foiling.Cold,cold:d.Foiling.Cold,g:d.Foiling.Gold,gf:d.Foiling.Gold,gold:d.Foiling.Gold})),Qr=e=>{let t=Dr.get(e);return t?[t]:[]},Hr=e=>Le(e,"foilings",Qr),St=new Map(Object.entries({aa:d.Treatment.AA,alt:d.Treatment.AA,"alt art":d.Treatment.AA,ab:d.Treatment.AB,"alt border":d.Treatment.AB,at:d.Treatment.AT,"alt text":d.Treatment.AT,ea:d.Treatment.EA,extended:d.Treatment.EA,"extended art":d.Treatment.EA,fa:d.Treatment.FA,full:d.Treatment.FA,"full art":d.Treatment.FA}));for(let e of Object.values(d.Treatment))St.set(e.toLowerCase(),e);var jr=new Map(Object.entries(d.Treatment)),Ur=e=>{let t=St.get(e)||jr.get(e.toUpperCase());return t?[t]:[]},Kr=e=>Le(e,"treatments",Ur),De=new Map(Object.entries({b:d.Rarity.Basic,c:d.Rarity.Common,f:d.Rarity.Fabled,l:d.Rarity.Legendary,m:d.Rarity.Majestic,p:d.Rarity.Promo,r:d.Rarity.Rare,s:d.Rarity.SuperRare,t:d.Rarity.Token,v:d.Rarity.Marvel})),_r=e=>De.get(e)||Object.values(d.Rarity).find(t=>t.toLowerCase()===e),$r=(e,{additionalHeroes:t})=>{let r=[],s=[],a=[],i=[];for(let{modifier:o,value:c}of e.filterValues){let p=_r(c);p?(r.push(p),s.push(p.toLowerCase()),a.push({modifier:o,value:p.toLowerCase()})):(i.push(c),a.push({modifier:o,value:c}))}let{appliedFilters:n}=se(e.key,a,{additionalHeroes:t,isExcluded:e.isExcluded});return{appliedFilters:n,attributes:Oe(e,"rarities",r),canonicalValues:s,unresolvedValues:i}},At=({filterValues:e,isExcluded:t,key:r},{additionalHeroes:s})=>{let{appliedFilters:a,unresolvedValues:i}=se(r,e,{additionalHeroes:s,isExcluded:t}),n=[];for(let{values:o}of a)n.push(...o);return{appliedFilters:a,canonicalValues:n,unresolvedValues:i}},zr=["unique"],Gr=["preview","spoiler","unreleased"],Wr=["released"],Pt={property:"firstReleaseDate",isDate:!0},Yr=new Map(Object.entries({dual:d.Meta.DualClass,exp:d.Meta.Expansion,expansion:d.Meta.Expansion,rainbow:d.Meta.Rainbow,reprint:d.Meta.Reprint,reprints:d.Meta.Reprint})),qr=e=>{let t=[],r=[];for(let a of e){let i=Yr.get(a);i?t.push(i):r.push(a)}let s=[];if(t.length===0){let a=new Set;for(let i of Object.values(d.Meta)){let n=!1;for(let o of r)i.toLowerCase().includes(o)&&(n=!0,a.add(o));n&&t.push(i)}for(let i of r)a.has(i)||s.push(i)}else s.push(...r);return{unresolvedValues:s,values:t}},Xr=(e,{today:t})=>{let{filterValues:r,isAnd:s,isExcluded:a}=e,i=[],n=[],o=[],c=[],p=[];for(let{value:P}of r)zr.includes(P)?n.push(P):Gr.includes(P)?o.push(P):Wr.includes(P)?c.push(P):p.push(P);let g=!s&&r.length>1;n.length>0&&i.push({filterToPropertyMapping:Z.is,values:[V(d.Meta.Reprint)],isAnd:s,isOr:g,isExcluded:!a}),o.length>0&&i.push({filterToPropertyMapping:Pt,values:[t],isAnd:s,isOr:g,isExcluded:a}),c.length>0&&i.push({filterToPropertyMapping:Pt,values:[t],isAnd:s,isOr:g,isExcluded:!a});let{unresolvedValues:f,values:C}=qr(p),b=[...n,...o,...c,...C.map(V)];(p.length>0||i.length===0)&&i.push(vt(e,C.map(V)));let I=C.includes(d.Meta.Expansion)&&!a;return{appliedFilters:i,attributes:I?{isExpansionSlot:I}:void 0,canonicalValues:b,unresolvedValues:f}},Zr={property:"cardIdentifier",isString:!0,isNormalized:!0},Jr=20,es=(e,t)=>{let r=new Set,s=[],a=new Set,i=[],n=p=>{r.add(p.cardIdentifier),a.has(p.name)||(a.add(p.name),s.push(p))},o=p=>{p.types.includes(d.Type.Hero)||n(p)};for(let p of t){let g=ye(e,p);for(let f of g)n(f);g.length===0&&i.push(p)}let c=0;for(;c<s.length&&c<=Jr;){let p=s[c];for(let f of Ce(e,p))o(f);if(c===0)for(let f of me(e,p))o(f);c++}return{cardIdentifiers:r,unresolvedValues:i}},kt=(e,t,r)=>{let s=new Set;for(let a of ye(e,t)){let i=r?Ce(e,a):me(e,a);for(let n of i)s.add(n.cardIdentifier)}return s},ts=(e,t)=>{let r=new Set,[s=new Set,...a]=e;if(t)for(let i of s)a.every(o=>o.has(i))&&r.add(i);else for(let i of e)for(let n of i)r.add(n);return r},Vt=(e,t)=>({filterToPropertyMapping:Zr,values:[...e],valuesSet:e,isExcluded:t,isOr:!0}),It=({filterValues:e,isAnd:t,isExcluded:r},s)=>{let a=[],i=[];for(let{value:n}of e){let o=s(n);a.push(o),o.size===0&&i.push(n)}return{appliedFilters:[Vt(ts(a,t),r)],unresolvedValues:i}},rs=(e,{index:t})=>{let{cardIdentifiers:r,unresolvedValues:s}=es(t,e.filterValues.map(({value:a})=>a));return{appliedFilters:[Vt(r,e.isExcluded)],unresolvedValues:s}},ss=(e,{index:t})=>It(e,r=>kt(t,r,!0)),as=(e,{index:t})=>It(e,r=>kt(t,r,!1)),is=new Map([[l.Artist,wr],[l.Banned,At],[l.Chain,rs],[l.Foiling,Hr],[l.Is,Xr],[l.Legal,At],[l.Pitch,Br],[l.Print,Er],[l.Rarity,$r],[l.ReferencedBy,ss],[l.References,as],[l.Set,Lr],[l.Treatment,Kr]]),wt=(e,t)=>(is.get(e.category)||Ir)(e,t);var Nt=_.map(X).join(""),ns=/(?:[^\s"]+|"[^"]*(?:"|$))+/g,os=new RegExp(`^([${Nt}])?([A-Za-z]+):(.+)$`),ls=new RegExp(`^([${Nt}])?([A-Za-z]+):$`),ds=",",Et="+",cs='"',Bt=e=>{let t=[],r=!1,s="",a=!1;for(let i of e)i===cs?(a=!a,s+=i):!a&&(i===ds||i===Et)?(r=r||i===Et,s&&t.push(s),s=""):s+=i;return s&&t.push(s),{isAndList:r,parts:t}},he=e=>{let t=[];for(let r of e.matchAll(ns))t.push({end:r.index+r[0].length,start:r.index,token:r[0]});return t},ps=e=>_.some(t=>e.startsWith(t)),Fe=e=>{let t=e.match(os),r;if(t){let[,s,a,i]=t;r={isAndList:Bt(i).isAndList,isExcluded:!!s,key:a,valueText:i}}return r},He=e=>{let t=e.match(ls),r;return t&&(r={isAndList:!1,isExcluded:!!t[1],key:t[2],valueText:""}),r},je=e=>{let t=e.trim(),r=Se.find(s=>t.startsWith(s));return{modifier:r,value:r?t.slice(r.length).trim():t}},Qe=e=>re(e)??e.toLowerCase(),us=(e,t)=>{let r=Qe(t),s=[];for(let{end:a,start:i,token:n}of he(e)){let o=Fe(n);o&&Qe(o.key)===r&&s.push({...o,end:a,start:i,token:n})}return s},Ot=e=>Bt(e).parts,Te=e=>e.replace(/^"|"$/g,""),Ue=e=>{let t=[];for(let r of Ot(e)){let s=Te(r);s&&t.push(s)}return t},gs=/[\s,:+"]/,fs=e=>{let t=e.replaceAll('"',"");return gs.test(e)?`"${t}"`:t};var L=require("@flesh-and-blood/types"),Ke=[{description:"Attack actions",expanded:["st:attack"],filters:{subtypes:[L.Subtype.Attack]},isCardProperty:!1,shorthands:["AA"]},{description:"Arcane barrier",expanded:['k:"arcane barrier"'],filters:{keywords:[L.Keyword.ArcaneBarrier]},isCardProperty:!1,shorthands:["AB"]},{description:"Attack reactions",expanded:['t:"attack reaction"'],filters:{types:[L.Type.AttackReaction]},isCardProperty:!1,shorthands:["AR"]},{description:"Defense reactions",expanded:['t:"defense reaction"'],filters:{types:[L.Type.DefenseReaction]},isCardProperty:!1,shorthands:["DR"]},{description:"Gain life",expanded:["gain {h}"],filters:{functionalText:"gain {h}"},isCardProperty:!1,shorthands:["Gain life","Gains life"]},{description:"Go again",expanded:['k:"go again"'],filters:{keywords:[L.Keyword.GoAgain]},isCardProperty:!1,shorthands:["GA"]},{description:"Non-attack actions",expanded:["t:action","st:non-attack"],filters:{subtypes:[L.Subtype.NonAttack],types:[L.Type.Action]},isCardProperty:!1,shorthands:["NAA"]},{description:"Plus defense",expanded:["+ {d}"],filters:{functionalText:"+ {d}"},isCardProperty:!1,shorthands:["Pump defense","Pumps defense","Buff defense","Buffs defense"]},{description:"Spellvoid",expanded:['k:"spellvoid"'],filters:{keywords:[L.Keyword.Spellvoid]},isCardProperty:!1,shorthands:["SV"]}],_e=Ke.filter(({shorthands:e})=>e.some(t=>t.includes(" "))).map(e=>({...e,shorthands:e.shorthands.filter(t=>t.includes(" ")).map(t=>t.toLowerCase()).sort((t,r)=>r.length-t.length)})),$e=Ke.filter(({shorthands:e})=>e.some(t=>!t.includes(" "))).map(e=>({...e,shorthands:e.shorthands.filter(t=>!t.includes(" ")).map(t=>t.toLowerCase()).sort((t,r)=>r.length-t.length)}));var ys=["\u201C","\u201D"],ms=[{text:ae.Release.ClassicBattlesRhinarDorinthea.toLowerCase(),override:ae.Release.ClassicBattlesRhinarDorinthea.toLowerCase().replaceAll(k,"")}],ze=new Map([...ae.setToSetIdentifierMappings].map(([e,t])=>[e.toLowerCase(),t])),Cs=[...J[l.Set],...J[l.Print]],hs=_.map(X).join(""),Fs=[...ze.keys()].sort((e,t)=>t.length-e.length).map(X).join("|"),Ts=new RegExp(`(?<=^|\\s)([${hs}]?(?:${Cs.join("|")}):(?:[^\\s]*[,+])?"?)(${Fs})(?="?(?:[,+]|\\s|$))`,"g"),xs=(e,t)=>{let r=e.trim().toLowerCase();for(let i of ys)r=r.replaceAll(i,'"');for(let{expanded:i,shorthands:n}of _e)for(let o of n)if(r.includes(o)){r=r.replace(o,i.join(" "));break}r=r.replace(Ts,(i,n,o)=>{let c=ze.get(o);return c?`${n}${c[0]}`:i});let s=ze.get(r),a=t.getCardsByExactName(r).length>0;s&&!a&&(r=`set:${s[0]}`);for(let{override:i,text:n}of ms)r.includes(n)&&(r=r.replace(n,i));return r},Ms=e=>{let t=$e.find(({shorthands:s})=>s.includes(e)),r=!!t&&!t.isCardProperty;return{isExpanded:r,tokens:r?t.expanded:[e]}},bs=e=>{let t=[];for(let{end:r,start:s,token:a}of he(e)){let{isExpanded:i,tokens:n}=Ms(a);for(let o of n)t.push({end:r,isExpanded:i,start:s,token:o})}return t},As=e=>{let t=[];for(let r of e){let{modifier:s,value:a}=je(r),i=V(a);i&&t.push({modifier:s,value:i})}return t},Ps=(e,t,r)=>{let s={key:e,reason:"value",values:r},a=Ve(t,r);return a&&(s.suggestedKey=a),s},vs=()=>{let e=new Date,t=`${e.getMonth()+1}`.padStart(2,"0"),r=`${e.getDate()}`.padStart(2,"0");return`${e.getFullYear()}-${t}-${r}`},ie=(e,t,{additionalHeroes:r=[],additionalSets:s=[],today:a=vs()}={})=>{let i=xs(e,t),n={additionalHeroes:r,additionalSets:s,index:t,today:a},o=[],c={artists:[],foilings:[],isExpansionSlot:!1,prints:[],rarities:[],releases:[],treatments:[]},p=[],g=[],f=[];for(let C of bs(i)){let b=Fe(C.token)||He(C.token);if(b){let{isAndList:D,isExcluded:I,key:P,valueText:O}=b,N=ge(P),Q=N?.category,U=Ue(O),$=As(U),H={...C,canonicalValues:$.map(({value:x})=>x),category:Q,filterValues:$,isAnd:D,isExcluded:I,isFilter:!0,isResolved:!0,key:P};if(U.length>0)if(N&&Q){let x=U;if($.length>0){let v=wt({category:Q,filterValues:$,isAnd:H.isAnd,isExcluded:I,key:P,mapping:N},n);o.push(...v.appliedFilters),v.canonicalValues&&(H.canonicalValues=v.canonicalValues),v.attributes&&Object.assign(c,v.attributes),x=v.unresolvedValues}x.length>0&&(H.isResolved=!1,f.push(Ps(P,Q,x)))}else H.isResolved=!1,f.push({key:P,reason:"key",values:[]});g.push(H)}else{let{end:D,start:I,token:P}=C;g.push({end:D,isFilter:!1,start:I,token:P});let O=Te(C.token),N=Ie(O);N.length>0?o.push(...N):O&&p.push(O.replace(k,""))}}return{appliedFilters:o,attributes:c,keywords:p,nodes:g,text:i,unresolvedFilters:f}};var A=require("@flesh-and-blood/types"),Lt={artists:["Hoodwill"],cardIdentifier:"fangs-a-lot-blue",classes:[A.Class.Generic],defaultImage:"FNG000",firstReleaseDate:"2022-06-02",functionalText:"If Fangs A Lot is put into your banished zone from your graveyard, instead put it into your hand.",legalFormats:[],legalHeroes:[A.Hero.Kayo,A.Hero.Levia,A.Hero.Rhinar],printings:[{artists:["Hoodwill"],identifier:"FNG000",image:"FNG000",print:"FNG000",rarity:A.Rarity.Rare,set:A.Release.Promos},{artists:["Hoodwill"],identifier:"FNG000",image:"FNG000_Marvel",print:`FNG000-${A.Treatment.FA}`,rarity:A.Rarity.Marvel,set:A.Release.Promos,treatments:[A.Treatment.FA]}],name:"Fangs A Lot",rarities:[A.Rarity.Rare,A.Rarity.Marvel],rarity:A.Rarity.Rare,sets:[A.Release.Promos],setIdentifiers:["FNG000"],specialImage:"FNG000_Marvel",subtypes:[A.Subtype.Attack],types:[A.Type.Action],typeText:"Generic Action - Attack"},Dt=[{keyword:Lt.name.toLowerCase(),card:Lt}];var Rs={getFn:(e,t)=>{let r=We.default.config.getFn(e,t),s=r;if(Array.isArray(r))s=r.map(a=>{let i=typeof a=="string"?a:a.v;return z(i.replace(k,""))});else if(r){let a=z(r).replace(k,"");s=t.includes("functionalText")?q(a):a}return s},ignoreLocation:!0,includeScore:!0,keys:[{name:"name",weight:10},{name:"functionalText",weight:6},{name:"shorthands",weight:4},{name:"setIdentifiers",weight:2},{name:"traits",weight:4},{name:"typeText",weight:6}],threshold:.15,useExtendedSearch:!0},Ge=class{constructor(t,r=[],s=[]){this.getFuse=()=>(this.fuse||(this.fuse=new We.default(this.cards,Rs)),this.fuse);this.getPoolCards=t=>{this.poolCardByCardIdentifier||(this.poolCardByCardIdentifier=new Map(this.cards.map(s=>[s.cardIdentifier,s])));let r=[];for(let{cardIdentifier:s}of t){let a=this.poolCardByCardIdentifier.get(s);a&&r.push(a)}return r};this.search=(t,r)=>{let s,a,{appliedFilters:i,attributes:n,keywords:o,unresolvedFilters:c}=ie(t,this.index,{additionalHeroes:this.additionalHeroes,additionalSets:this.additionalSets}),p=o.join(" "),g=r?Dt.filter(x=>x.keyword===p):[],f=x=>i.length>0?x.filter(v=>v&&jt(v,i)):x;if(g.length>0)s=f(g.map(({card:x})=>x));else if(o.length){let x=B(p),v=this.getPoolCards(this.index.getCardsByNickname(x)),R=new Map;for(let F of[...this.getPoolCards(this.index.getCardsByExactName(x)),...v])R.set(F.cardIdentifier,F);let u=this.getFuse().search(p).map(F=>F.item).filter(({cardIdentifier:F})=>!R.has(F));s=f([...R.values(),...u]),s.some(F=>v.includes(F))&&(a={kind:"nickname",text:x}),s.length===0&&o.length===1&&(s=f(this.getPoolCards(this.index.getCardsByInitials(x))),s.length>0&&(a={kind:"initials",text:x}))}else s=f([...this.cards]);if(!(o.length>0&&a?.kind!=="initials")){let x="";if(n.releases.length===1){let u=xe.setToSetIdentifierMappings.get(n.releases[0]);u?.length&&(x=u[0].toUpperCase())}if(!x&&n.prints.length===1){let u=n.prints[0];xe.setIdentifierToSetMappings.has(u)&&(x=u.toUpperCase())}x?s.sort((u,y)=>{let h=u.setIdentifiers.find(M=>M.includes(x))?.replace(x,""),F=y.setIdentifiers.find(M=>M.includes(x))?.replace(x,"");return h&&F?h.localeCompare(F):-1}):s.sort((u,y)=>u.name===y.name?`${u.pitch}`.localeCompare(`${y.pitch}`):u.name.localeCompare(y.name))}let b=[],{artists:D,isExpansionSlot:I,foilings:P,prints:O,rarities:N,releases:Q,treatments:U}=n;(D.length>0||I||P.length>0||O.length>0||N.length>0||Q.length>0||U.length>0)&&(b=s.map(x=>{let v=x.printings.filter(R=>{let u=!!R.image,y=D.length===0||D.some(ee=>R.artists.find(Ut=>Ut.replace(k,"").toLowerCase().includes(ee))),h=!I||I===R.isExpansionSlot,F=P.length===0||!!R.foiling&&P.includes(R.foiling),M=O.length===0||O.some(ee=>R.identifier.includes(ee.toUpperCase())),w=N.length===0||N.includes(R.rarity),S=Q.length===0||Q.includes(R.set),Y=U.length===0||R.treatments?.some(ee=>U.includes(ee));return u&&y&&h&&F&&M&&w&&S&&Y});return{...x,matchingPrintings:v}}));let H=b.length>0?b:s;return{alias:a,appliedFilters:i,attributes:n,keywords:o,searchResults:H,unresolvedFilters:c}};let a=Array.isArray(r)?{additionalHeroes:r,additionalSets:s}:r;this.additionalHeroes=a.additionalHeroes||[],this.additionalSets=a.additionalSets||[],this.cards=[...t],this.index=a.index||we(t)}},Ht=Ge,jt=(e,t)=>{let r=!0;for(let s of t){let{isNumber:a,isString:i,isArray:n,isBoolean:o,isDate:c}=s.filterToPropertyMapping;s.isOptional||(a?r=r&&Ss(e,s):i?r=r&&ks(e,s):n?r=r&&Vs(e,s,t):o?r=r&&Is(e,s):c&&(r=r&&ws(e,s)))}return r},Qt=(e,t,r)=>{let s=parseInt(t),a;switch(r){case">=":a=e>=s;break;case">":a=e>s;break;case"<=":a=e<=s;break;case"<":a=e<s;break;default:a=e===s}return a},Ss=(e,t)=>{let{filterValues:r,values:s,modifier:a,isExcluded:i,filterToPropertyMapping:{partialMatch:n}}=t,o=!0;if(oe(t,e)){let c=ne(e,t),p;if(c!=null&&!isNaN(c)){let g=parseInt(c);p=r?r.some(({modifier:f,value:C})=>Qt(g,C,f)):s.some(f=>Qt(g,f,a))}else{let g=Ns(e,t)?.toLowerCase();p=n?s.some(f=>!!g?.includes(f)):s.some(f=>g===f)}o=i?!p:p}return o},ks=(e,t)=>{if(oe(t,e)){let{values:r,valuesSet:s,isAnd:a,isExcluded:i,filterToPropertyMapping:{hasMarkup:n,isNormalized:o,partialMatch:c}}=t,p=ne(e,t),g=o?p:p?.replaceAll(k,"").toLowerCase(),f=n&&g?q(g):g;if(c){let C=a?r?.every(b=>f?.includes(b)):r?.some(b=>f?.includes(b));return i?!C:C}else{let C;return a?C=r?.every(b=>f===b):s?C=s.has(f):C=r?.some(b=>f===b),i?!C:C}}else return!0},Vs=(e,t,r)=>{if(oe(t,e)){let{values:s,isAnd:a,isExcluded:i,filterToPropertyMapping:{partialMatch:n}}=t,o=Es(e,t,r).map(c=>c?.replaceAll(k,""));if(n){let c=a?s.every(g=>o?.some(f=>f?.toLowerCase().includes(g))):s.some(g=>o?.some(f=>f?.toLowerCase().includes(g))),p=o.length===0;return i?!c||p:c}else{let c=a?s.every(p=>o?.some(g=>g?.toLowerCase()===p)):s.some(p=>o?.some(g=>g?.toLowerCase()===p));return i?!c:c}}else return!0},Is=(e,t)=>{if(oe(t,e)){let{isExcluded:r}=t,s=ne(e,t);return r?!s:s}else return!0},ws=(e,t)=>{if(oe(t,e)){let{values:r,isExcluded:s}=t,a=ne(e,t),i=r?.some(n=>a>n);return s?!i:i}else return!0},ne=(e,t)=>{let{filterToPropertyMapping:{property:r}}=t,s;return r!==K&&(s=e[r]),s},Es=(e,t,r)=>{let{filterToPropertyMapping:{isNestedPropertyArray:s,nestedProperty:a}}=t,i=[],n=Object.keys(e.legalOverrides||{}).length>0,o=t.filterToPropertyMapping.property===G.LegalHeroes,c=r.find(({filterToPropertyMapping:g})=>g.property===G.LegalFormats);if(n&&o&&!!c){let g=new Set;for(let{format:f,heroes:C}of e.legalOverrides||[])if(c.values.includes(f.toLowerCase()))for(let b of C)g.add(b);i=Array.from(g)}if(i.length===0)if(a){let g=new Set;for(let f of e.printings){let C=f[a];if(s){if(Array.isArray(C))for(let b of C)g.add(b)}else C&&typeof C=="string"&&g.add(C)}i=Array.from(g)}else{let g=ne(e,t);if(Array.isArray(g))for(let f of g)typeof f=="string"&&i.push(f)}return i},Ns=(e,t)=>{let{filterToPropertyMapping:{specialProperty:r}}=t,s;return r&&(s=e[r]),s},oe=({cardTypes:e},{types:t,subtypes:r})=>!e||e?.some(s=>t.map(a=>a.toLowerCase()).includes(s.toLowerCase())||r.map(a=>a.toLowerCase()).includes(s.toLowerCase()));var Bs=(e,t,r=[],s=[],a)=>{let{appliedFilters:i,attributes:n,keywords:o}=ie(e,t,{additionalHeroes:r,additionalSets:s,today:a});return{appliedFilters:i,attributes:n,keywords:o}};var Os=(e,t)=>{let r=new Set;for(let a of e)for(let i of a.createdExtras||[])r.add(i);let s=[];for(let a of t)r.has(a.cardIdentifier)&&s.push(a);return s};0&&(module.exports={FilterCategory,FilterKind,FilterProperty,MARKUP,NO_CARD_PROPERTY,PUNCTUATION,RARITY_VALUES_MAPPING,aliasesByFilterCategory,availableExclusions,availableModifiers,filterCard,filtersToCardPropertyMappings,getCardsByName,getCardsReferencedBy,getCardsReferencing,getCatalogueIndex,getCleanText,getEscapedForRegExp,getExcludedMetaFilters,getFilterCategory,getFilterMapping,getFilterTokenSpansForKey,getFilterValue,getIncompleteFilterToken,getIsExcludedToken,getIsValueInFilterVocabulary,getKeywordsAndAppliedFiltersFromText,getMetaFilterResolution,getMetaFilters,getNormalizedFilterValue,getNormalizedText,getParsedQuery,getQueryFilterToken,getQueryTokenSpans,getQuotedValue,getResolvedFilterKey,getSuggestedFilterKey,getTextWithoutMarkup,getTokensReferencedByCards,getUnquotedValue,getValuePartsFromFilterValue,getValuesFromFilterValue,multiWordShorthands,shorthands,singleWordShorthands});
1
+ "use strict";var _t=Object.create;var ge=Object.defineProperty;var Gt=Object.getOwnPropertyDescriptor;var zt=Object.getOwnPropertyNames;var $t=Object.getPrototypeOf,Wt=Object.prototype.hasOwnProperty;var Yt=(e,t)=>{for(var r in t)ge(e,r,{get:t[r],enumerable:!0})},Je=(e,t,r,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of zt(t))!Wt.call(e,a)&&a!==r&&ge(e,a,{get:()=>t[a],enumerable:!(s=Gt(t,a))||s.enumerable});return e};var qt=(e,t,r)=>(r=e!=null?_t($t(e)):{},Je(t||!e||!e.__esModule?ge(r,"default",{value:e,enumerable:!0}):r,e)),Xt=e=>Je(ge({},"__esModule",{value:!0}),e);var Os={};Yt(Os,{FilterCategory:()=>l,FilterKind:()=>m,FilterProperty:()=>J,MARKUP:()=>Re,NO_CARD_PROPERTY:()=>_,PUNCTUATION:()=>V.PUNCTUATION,RARITY_VALUES_MAPPING:()=>De,aliasesByFilterCategory:()=>ae,availableExclusions:()=>q,availableModifiers:()=>we,default:()=>jt,filterCard:()=>Ut,filtersToCardPropertyMappings:()=>se,getCardsByName:()=>Rs,getCatalogueIndex:()=>We,getCleanText:()=>O,getEscapedForRegExp:()=>re,getExcludedMetaFilters:()=>Ee,getFilterCategory:()=>ne,getFilterMapping:()=>he,getFilterTokenSpansForKey:()=>is,getFilterValue:()=>je,getIncompleteFilterToken:()=>He,getIsExcludedToken:()=>as,getIsValueInFilterVocabulary:()=>Ve,getKeywordsAndAppliedFiltersFromText:()=>Es,getMetaFilterResolution:()=>oe,getMetaFilters:()=>fr,getNormalizedFilterValue:()=>N.getNormalizedFilterValue,getNormalizedText:()=>Z,getParsedQuery:()=>le,getQueryFilterToken:()=>Me,getQueryTokenSpans:()=>xe,getQuotedValue:()=>os,getResolvedFilterKey:()=>Qe,getSuggestedFilterKey:()=>Ne,getTextWithoutMarkup:()=>te,getTokensReferencedByCards:()=>Bs,getUnquotedValue:()=>Ae,getValuePartsFromFilterValue:()=>Et,getValuesFromFilterValue:()=>Ue,multiWordShorthands:()=>_e,shorthands:()=>Ke,singleWordShorthands:()=>Ge});module.exports=Xt(Os);var qe=qt(require("fuse.js"),1);var V=require("@flesh-and-blood/types"),Re=/\*/g;var T=require("@flesh-and-blood/types");var et=require("@flesh-and-blood/types");var N=require("@flesh-and-blood/types"),O=e=>Z(e.toLowerCase().trim().replace(et.PUNCTUATION,"")),Z=e=>e.normalize("NFD").replace(/\p{Diacritic}/gu,""),te=e=>e.replace(Re,""),re=e=>e.replace(/[.*+?^${}()|[\]\\-]/g,"\\$&");var l={Arcane:"arcane",Artist:"artist",Banned:"banned",Bond:"bond",Class:"class",Cost:"cost",CreatedBy:"createdby",Creates:"creates",Defense:"defense",Flow:"flow",Foiling:"foiling",Fusion:"fusion",Intellect:"intellect",Is:"is",Keyword:"keyword",Legal:"legal",Life:"life",Name:"name",Pitch:"pitch",Power:"power",Print:"print",Rarity:"rarity",ReferencedBy:"referencedby",References:"references",Set:"set",Shorthand:"shorthand",Specialization:"specialization",Subtype:"subtype",Talent:"talent",Text:"text",Trait:"trait",Treatment:"treatment",Type:"type",TypeText:"typetext",Year:"year"},m={Comparator:"comparator",ExactMatch:"exactMatch",PartialMatch:"partialMatch"},we=[">=",">","<=","<"],q=["!","-"],_="n/a",Tt=[...Object.values(T.Format),...Object.values(T.Hero)],Zt={category:l.Arcane,canonicalAlias:"arcane",kind:m.Comparator,property:"arcane",specialProperty:"specialArcane",isNumber:!0,partialMatch:!0},Pe={category:l.Artist,canonicalAlias:"art",kind:m.PartialMatch,property:"artists",isArray:!0,partialMatch:!0},tt={category:l.Banned,canonicalAlias:"banned",kind:m.ExactMatch,vocabulary:Tt,property:_,isMeta:!0},rt={category:l.Bond,canonicalAlias:"bond",kind:m.ExactMatch,vocabulary:Object.values(T.Bond),property:"bonds",isArray:!0},st={category:l.Class,canonicalAlias:"c",kind:m.PartialMatch,vocabulary:Object.values(T.Class),property:"classes",isArray:!0,partialMatch:!0},at={category:l.Cost,canonicalAlias:"co",kind:m.Comparator,property:"cost",specialProperty:"specialCost",isNumber:!0,partialMatch:!0},it={category:l.CreatedBy,canonicalAlias:"createdby",kind:m.PartialMatch,property:_},nt={category:l.Creates,canonicalAlias:"creates",kind:m.PartialMatch,property:_},ie={category:l.Defense,canonicalAlias:"d",kind:m.Comparator,property:"defense",specialProperty:"specialDefense",isNumber:!0},ot={category:l.Flow,canonicalAlias:"flow",kind:m.ExactMatch,vocabulary:Object.values(T.Flow),property:"flows",isArray:!0},lt={category:l.Foiling,canonicalAlias:"foil",kind:m.ExactMatch,vocabulary:Object.values(T.Foiling),nestedProperty:"foiling",property:"printings",isArray:!0},dt={category:l.Fusion,canonicalAlias:"f",kind:m.ExactMatch,vocabulary:Object.values(T.Fusion),property:"fusions",isArray:!0},ct={category:l.Intellect,canonicalAlias:"i",kind:m.Comparator,property:"intellect",isNumber:!0},pt={category:l.Keyword,canonicalAlias:"k",kind:m.ExactMatch,vocabulary:Object.values(T.Keyword),property:"keywords",isArray:!0},ve={category:l.Legal,canonicalAlias:"l",kind:m.ExactMatch,vocabulary:Tt,property:_,isMeta:!0},ut={category:l.Life,canonicalAlias:"li",kind:m.Comparator,property:"life",specialProperty:"specialLife",isNumber:!0},gt={category:l.Is,canonicalAlias:"is",kind:m.ExactMatch,vocabulary:Object.values(T.Meta),property:"meta",isArray:!0},ft={category:l.Name,canonicalAlias:"name",kind:m.PartialMatch,property:"name",isString:!0,partialMatch:!0},ke={category:l.Pitch,canonicalAlias:"p",kind:m.Comparator,property:"pitch",isNumber:!0},fe={category:l.Power,canonicalAlias:"pwr",kind:m.Comparator,property:"power",specialProperty:"specialPower",isNumber:!0},ye={category:l.Print,canonicalAlias:"print",kind:m.PartialMatch,property:"setIdentifiers",isArray:!0,partialMatch:!0},yt={category:l.Rarity,canonicalAlias:"r",kind:m.ExactMatch,vocabulary:Object.values(T.Rarity),property:_,isMeta:!0},Jt={category:l.ReferencedBy,canonicalAlias:"referencedby",kind:m.PartialMatch,property:_},er={category:l.References,canonicalAlias:"references",kind:m.PartialMatch,property:_},mt={category:l.Set,canonicalAlias:"s",kind:m.PartialMatch,property:"sets",isArray:!0,partialMatch:!0},Ie={category:l.Shorthand,canonicalAlias:"short",kind:m.PartialMatch,vocabulary:Object.values(T.Shorthand),property:"shorthands",isArray:!0,partialMatch:!0},me={category:l.Specialization,canonicalAlias:"sp",kind:m.PartialMatch,vocabulary:Object.values(T.Hero),property:"specializations",isArray:!0,partialMatch:!0},Ct={category:l.Subtype,canonicalAlias:"st",kind:m.ExactMatch,vocabulary:Object.values(T.Subtype),property:"subtypes",isArray:!0},ht={category:l.Type,canonicalAlias:"t",kind:m.ExactMatch,vocabulary:Object.values(T.Type),property:"types",isArray:!0},Se={category:l.Talent,canonicalAlias:"tal",kind:m.ExactMatch,vocabulary:Object.values(T.Talent),property:"talents",isArray:!0},tr={category:l.Text,canonicalAlias:"text",kind:m.PartialMatch,property:"functionalText",hasMarkup:!0,isString:!0,partialMatch:!0},rr={category:l.Trait,canonicalAlias:"trait",kind:m.PartialMatch,vocabulary:Object.values(T.Trait),property:"traits",isArray:!0,partialMatch:!0},Ft={category:l.TypeText,canonicalAlias:"x",kind:m.PartialMatch,property:"typeText",isString:!0,partialMatch:!0},Ce={category:l.Treatment,canonicalAlias:"treatment",kind:m.ExactMatch,vocabulary:Object.values(T.Treatment),nestedProperty:"treatments",property:"printings",isArray:!0,isNestedPropertyArray:!0},sr={category:l.Year,canonicalAlias:"year",kind:m.PartialMatch,property:"firstReleaseDate",isString:!0,partialMatch:!0},se={arcane:Zt,a:Pe,artist:Pe,art:Pe,attack:fe,b:ie,block:ie,banned:tt,bond:rt,bonds:rt,c:st,class:st,co:at,cost:at,createdby:it,creates:nt,color:ke,d:ie,def:ie,defense:ie,flow:ot,flows:ot,f:dt,fusion:dt,foil:lt,foiling:lt,i:ct,intellect:ct,is:gt,k:pt,keyword:pt,l:ve,legal:ve,hero:ve,li:ut,life:ut,madeby:it,makes:nt,meta:gt,n:ft,name:ft,p:ke,pitch:ke,pwr:fe,pow:fe,power:fe,print:ye,printing:ye,printings:ye,prints:ye,r:yt,rarity:yt,referencedby:Jt,references:er,rf:tt,s:mt,set:mt,short:Ie,shorthand:Ie,shorthands:Ie,sp:me,spec:me,specialization:me,specializations:me,st:Ct,subtype:Ct,t:ht,type:ht,tal:Se,talent:Se,talents:Se,text:tr,trait:rr,treat:Ce,treatment:Ce,var:Ce,variation:Ce,x:Ft,typetext:Ft,year:sr},ar=new Map(Object.entries(se)),he=e=>ar.get(e.toLowerCase()),ne=e=>he(e)?.category,ir=()=>{let e=Object.create(null);for(let[t,{category:r}]of Object.entries(se)){let s=e[r];s?s.push(t):e[r]=[t]}return e},ae=ir(),nr=()=>{let e=new Map,t=new Set,r=Object.values(se);for(let s of r){let{vocabulary:a}=s;if(a&&!t.has(s)){t.add(s);for(let i of a){let n=(0,N.getNormalizedFilterValue)(i),o=e.get(n);o?o.push(s):e.set(n,[s])}}}return e},xt=nr(),Ve=(e,t)=>!!xt.get((0,N.getNormalizedFilterValue)(t))?.some(r=>r.category===e),or=(e,t)=>{let r=[],s=!0;for(let a of t){let i=(xt.get((0,N.getNormalizedFilterValue)(a))||[]).filter(n=>n.category!==e);r=s?i:r.filter(n=>i.includes(n)),s=!1}return r},Ne=(e,t)=>{let r=or(e,t),[s]=r;return r.length===1?s.canonicalAlias:void 0};var ze=require("@flesh-and-blood/types");var u=require("@flesh-and-blood/types");var E=require("@flesh-and-blood/types");var J={BannedFormats:"bannedFormats",LegalFormats:"legalFormats",LegalHeroes:"legalHeroes"},Fe=Array.from(Array(50).keys()).map(e=>`${e}`),lr=[{format:E.Format.ClassicConstructed,nicknames:["cc","classic"]},{format:E.Format.LivingLegend,nicknames:["cc ll","classic constructed ll","ll cc","ll","living legend"]},{format:E.Format.SilverAge,nicknames:["sage"]},{format:E.Format.GoldenAge,nicknames:["gage"]},{format:E.Format.UltimatePitFight,nicknames:["upf"]}],dr=Object.values(E.Format).map(e=>{let t=lr.find(({format:s})=>s===e),r=e.toLowerCase().replaceAll(V.PUNCTUATION,"");return t?{...t,format:r}:{format:r}}),cr=Object.values(E.Hero).map(O),Mt=e=>e.replaceAll(" ",""),pr=(e,t)=>{let r=Mt(e),s,a=[];for(let n of t){let o=Mt(n);o===r?s=n:o.startsWith(r)&&a.push(n)}let i=a.length===1;return s??(i?a[0]:void 0)},At=["common","rare","super rare","majestic","legendary","fabled"],ur=({modifier:e,value:t})=>{let r=[],s=e==="<"||e==="<=",a=e===">="||e==="<=",i=s?[...At].reverse():At,n=!1;for(let o of i)n?r.push(o):o===t&&(n=!0,a&&r.push(o));return r},gr=(e,t)=>{let r=[];for(let s of e)s.modifier?r.push(...ur(s)):r.push(s.value);return{filterToPropertyMapping:{nestedProperty:"rarity",property:"printings",isArray:!0},isExcluded:t,isOr:!0,values:r}},bt=(e,t,r,s)=>{let a=new Set([...cr,...r.map(O)]),i=[],n=[],o=[],d=[];for(let{value:f}of e){let c=dr.find(({format:g,nicknames:C})=>g===f||!!C&&C.includes(f));if(c)n.push(c.format);else{let g=pr(f,a);g?o.push(g):d.push(f)}}return n.length>0&&i.push({filterToPropertyMapping:{property:s,isArray:!0},values:n,isOr:!0,isExcluded:t}),o.length>0&&i.push({filterToPropertyMapping:{property:J.LegalHeroes,isArray:!0},values:o,isOr:!0,isExcluded:t}),{appliedFilters:i,unresolvedValues:d}},oe=(e,t,{additionalHeroes:r=[],isExcluded:s=!1}={})=>{let a=ne(e),i={appliedFilters:[],unresolvedValues:[]};return a===l.Legal?i=bt(t,s,r,J.LegalFormats):a===l.Banned?i=bt(t,s,r,J.BannedFormats):a===l.Rarity&&(i={appliedFilters:[gr(t,s)],unresolvedValues:[]}),i},fr=(e,t,r,s,a,i)=>oe(r,s.map(n=>({modifier:a,value:n})),{additionalHeroes:i,isExcluded:e}).appliedFilters,yr=[{filterToPropertyMapping:{property:"cost",isNumber:!0},isExcluded:!0,values:Fe},{filterToPropertyMapping:{property:"specialCost",isString:!0,partialMatch:!0},isExcluded:!0,values:["*","x"]},{filterToPropertyMapping:{property:"types",isArray:!0,partialMatch:!0},isExcluded:!0,values:["equipment","hero","placeholder","token","weapon"]}],mr=[{filterToPropertyMapping:{property:"defense",isNumber:!0},isExcluded:!0,values:Fe},{filterToPropertyMapping:{property:"specialDefense",isString:!0,partialMatch:!0},isExcluded:!0,values:["*","x"]},{filterToPropertyMapping:{property:"types",isArray:!0,partialMatch:!0},isExcluded:!0,values:["hero","placeholder","token","weapon"]}],Cr=[{filterToPropertyMapping:{property:"pitch",isNumber:!0},isExcluded:!0,values:Fe},{filterToPropertyMapping:{property:"types",isArray:!0,partialMatch:!0},isExcluded:!0,values:["equipment","hero","placeholder","token","weapon"]},{filterToPropertyMapping:{property:"isCardBack",isBoolean:!0},isExcluded:!0,values:["true"]}],hr=[{filterToPropertyMapping:{property:"power",isNumber:!0},isExcluded:!0,values:Fe},{filterToPropertyMapping:{property:"specialPower",isString:!0,partialMatch:!0},isExcluded:!0,values:["*","x"]},{filterToPropertyMapping:{property:"types",isArray:!0,partialMatch:!0},isExcluded:!0,values:["equipment","hero","placeholder","token"]}],Fr=[{filterToPropertyMapping:{property:"talents",isArray:!0},isExcluded:!0,values:Object.values(E.Talent).map(e=>e.toLowerCase())}],Tr=[{filterToPropertyMapping:{property:"classes",isArray:!0},isExcluded:!0,values:Object.values(E.Class).map(e=>e.toLowerCase())}],xr=[{category:l.Class,filters:Tr},{category:l.Cost,filters:yr},{category:l.Defense,filters:mr},{category:l.Pitch,filters:Cr},{category:l.Power,filters:hr},{category:l.Talent,filters:Fr}],Mr=()=>{let e=new Map;for(let{category:t,filters:r}of xr)for(let s of ae[t])for(let a of q)e.set(`${a}${s}`,r);return e},Ar=Mr(),Ee=e=>{let t=[],r=Ar.get(e);return r&&t.push(...r),t};var br=e=>{let[t]=e,r=t?.modifier;return e.every(({modifier:a})=>a===r)?r:void 0},Be=({filterValues:e,isAnd:t,isExcluded:r,mapping:s})=>{let a=[];for(let{value:i}of e)a.push(s.hasMarkup?te(i):i);return{filterToPropertyMapping:s,filterValues:e,isAnd:t,isExcluded:r,isOr:!t&&a.length>1,modifier:br(e),values:a}},vt=({isAnd:e,isExcluded:t,mapping:r},s)=>({filterToPropertyMapping:r,isAnd:e,isExcluded:t,isOr:!e&&s.length>1,values:s}),Rr=({category:e,filterValues:t,mapping:r})=>{let s=[];if(r.kind===m.ExactMatch&&!!r.vocabulary)for(let{value:i}of t)Ve(e,i)||s.push(i);return s},Pr=e=>({appliedFilters:[Be(e)],unresolvedValues:Rr(e)}),Oe=({isExcluded:e},t,r)=>e?void 0:{[t]:r},kt=(e,t)=>({appliedFilters:[Be(e)],attributes:Oe(e,t,e.filterValues.map(({value:r})=>r)),unresolvedValues:[]}),vr=e=>kt(e,"artists"),kr=e=>kt(e,"prints"),Le=(e,t,r)=>{let s=[],a=[],i=[];for(let{value:n}of e.filterValues){let o=r(n);if(o.length>0)for(let d of o)s.push(d),a.push((0,N.getNormalizedFilterValue)(d));else i.push(n)}return{appliedFilters:[vt(e,a)],attributes:Oe(e,t,s),canonicalValues:a,unresolvedValues:i}},Ir=new Map(Object.entries({purple:4,blue:3,yellow:2,red:1,white:0})),Sr=e=>{let t=[],r=[];for(let{modifier:s,value:a}of e.filterValues){let i=Ir.get(a),n=i===void 0?a:`${i}`;t.push({modifier:s,value:n}),r.push(n)}return{appliedFilters:[Be({...e,filterValues:t})],canonicalValues:r,unresolvedValues:[]}},wr=(e,t)=>{let r=[()=>{let a=t.getReleaseByName(e);return a?[a.release]:[]},()=>{let a=t.getReleaseBySetIdentifier(e);return a?[a.release]:[]},()=>{let a=[];for(let{release:i}of t.releases)i.toLowerCase().includes(e)&&a.push(i);return a}],s=[];for(let a of r)s.length===0&&s.push(...a());return s},Vr=(e,{index:t})=>Le(e,"releases",r=>wr(r,t)),Nr=new Map(Object.entries({r:u.Foiling.Rainbow,rf:u.Foiling.Rainbow,rainbow:u.Foiling.Rainbow,c:u.Foiling.Cold,cf:u.Foiling.Cold,cold:u.Foiling.Cold,g:u.Foiling.Gold,gf:u.Foiling.Gold,gold:u.Foiling.Gold})),Er=e=>{let t=Nr.get(e);return t?[t]:[]},Br=e=>Le(e,"foilings",Er),It=new Map(Object.entries({aa:u.Treatment.AA,alt:u.Treatment.AA,"alt art":u.Treatment.AA,ab:u.Treatment.AB,"alt border":u.Treatment.AB,at:u.Treatment.AT,"alt text":u.Treatment.AT,ea:u.Treatment.EA,extended:u.Treatment.EA,"extended art":u.Treatment.EA,fa:u.Treatment.FA,full:u.Treatment.FA,"full art":u.Treatment.FA}));for(let e of Object.values(u.Treatment))It.set(e.toLowerCase(),e);var Or=new Map(Object.entries(u.Treatment)),Lr=e=>{let t=It.get(e)||Or.get(e.toUpperCase());return t?[t]:[]},Dr=e=>Le(e,"treatments",Lr),De=new Map(Object.entries({b:u.Rarity.Basic,c:u.Rarity.Common,f:u.Rarity.Fabled,l:u.Rarity.Legendary,m:u.Rarity.Majestic,p:u.Rarity.Promo,r:u.Rarity.Rare,s:u.Rarity.SuperRare,t:u.Rarity.Token,v:u.Rarity.Marvel})),Qr=e=>De.get(e)||Object.values(u.Rarity).find(t=>t.toLowerCase()===e),Hr=(e,{additionalHeroes:t})=>{let r=[],s=[],a=[],i=[];for(let{modifier:o,value:d}of e.filterValues){let f=Qr(d);f?(r.push(f),s.push(f.toLowerCase()),a.push({modifier:o,value:f.toLowerCase()})):(i.push(d),a.push({modifier:o,value:d}))}let{appliedFilters:n}=oe(e.key,a,{additionalHeroes:t,isExcluded:e.isExcluded});return{appliedFilters:n,attributes:Oe(e,"rarities",r),canonicalValues:s,unresolvedValues:i}},Rt=({filterValues:e,isExcluded:t,key:r},{additionalHeroes:s})=>{let{appliedFilters:a,unresolvedValues:i}=oe(r,e,{additionalHeroes:s,isExcluded:t}),n=[];for(let{values:o}of a)n.push(...o);return{appliedFilters:a,canonicalValues:n,unresolvedValues:i}},jr=["unique"],Ur=["preview","spoiler","unreleased"],Kr=["released"],Pt={property:"firstReleaseDate",isDate:!0},_r=new Map(Object.entries({dual:u.Meta.DualClass,exp:u.Meta.Expansion,expansion:u.Meta.Expansion,rainbow:u.Meta.Rainbow,reprint:u.Meta.Reprint,reprints:u.Meta.Reprint})),Gr=e=>{let t=[],r=[];for(let a of e){let i=_r.get(a);i?t.push(i):r.push(a)}let s=[];if(t.length===0){let a=new Set;for(let i of Object.values(u.Meta)){let n=!1;for(let o of r)i.toLowerCase().includes(o)&&(n=!0,a.add(o));n&&t.push(i)}for(let i of r)a.has(i)||s.push(i)}else s.push(...r);return{unresolvedValues:s,values:t}},zr=(e,{today:t})=>{let{filterValues:r,isAnd:s,isExcluded:a}=e,i=[],n=[],o=[],d=[],f=[];for(let{value:b}of r)jr.includes(b)?n.push(b):Ur.includes(b)?o.push(b):Kr.includes(b)?d.push(b):f.push(b);let c=!s&&r.length>1;n.length>0&&i.push({filterToPropertyMapping:se.is,values:[(0,N.getNormalizedFilterValue)(u.Meta.Reprint)],isAnd:s,isOr:c,isExcluded:!a}),o.length>0&&i.push({filterToPropertyMapping:Pt,values:[t],isAnd:s,isOr:c,isExcluded:a}),d.length>0&&i.push({filterToPropertyMapping:Pt,values:[t],isAnd:s,isOr:c,isExcluded:!a});let{unresolvedValues:g,values:C}=Gr(f),x=[...n,...o,...d,...C.map(N.getNormalizedFilterValue)];(f.length>0||i.length===0)&&i.push(vt(e,C.map(N.getNormalizedFilterValue)));let P=C.includes(u.Meta.Expansion)&&!a;return{appliedFilters:i,attributes:P?{isExpansionSlot:P}:void 0,canonicalValues:x,unresolvedValues:g}},$r={property:"cardIdentifier",isString:!0,isNormalized:!0},Wr=(e,t)=>{let r=e.getCardsByExactName(t);return r.length===0&&(r=e.getCardsByGroup(t)),r.length===0&&(r=e.getCardsByName(t)),r},Yr=(e,t,r)=>{let s=new Set;for(let a of Wr(e,t))for(let i of r(e,a.cardIdentifier))if(!s.has(i.cardIdentifier))for(let o of e.getPitchCycle(i.cardIdentifier))s.add(o.cardIdentifier);return s},qr=(e,t)=>{let r=new Set,[s=new Set,...a]=e;if(t)for(let i of s)a.every(o=>o.has(i))&&r.add(i);else for(let i of e)for(let n of i)r.add(n);return r},Xr=(e,t)=>({filterToPropertyMapping:$r,values:[...e],valuesSet:e,isExcluded:t,isOr:!0}),Te=e=>({filterValues:t,isAnd:r,isExcluded:s},{index:a})=>{let i=[],n=[];for(let{value:o}of t){let d=Yr(a,o,e);i.push(d),d.size===0&&n.push(o)}return{appliedFilters:[Xr(qr(i,r),s)],unresolvedValues:n}},Zr=new Map([[l.Artist,vr],[l.Banned,Rt],[l.CreatedBy,Te((e,t)=>e.getCreates(t))],[l.Creates,Te((e,t)=>e.getCreatedBy(t))],[l.Foiling,Br],[l.Is,zr],[l.Legal,Rt],[l.Pitch,Sr],[l.Print,kr],[l.Rarity,Hr],[l.ReferencedBy,Te((e,t)=>e.getReferences(t))],[l.References,Te((e,t)=>e.getReferencedBy(t))],[l.Set,Vr],[l.Treatment,Dr]]),St=(e,t)=>(Zr.get(e.category)||Pr)(e,t);var Vt=q.map(re).join(""),Jr=/(?:[^\s"]+|"[^"]*(?:"|$))+/g,es=new RegExp(`^([${Vt}])?([A-Za-z]+):(.+)$`),ts=new RegExp(`^([${Vt}])?([A-Za-z]+):$`),rs=",",wt="+",ss='"',Nt=e=>{let t=[],r=!1,s="",a=!1;for(let i of e)i===ss?(a=!a,s+=i):!a&&(i===rs||i===wt)?(r=r||i===wt,s&&t.push(s),s=""):s+=i;return s&&t.push(s),{isAndList:r,parts:t}},xe=e=>{let t=[];for(let r of e.matchAll(Jr))t.push({end:r.index+r[0].length,start:r.index,token:r[0]});return t},as=e=>q.some(t=>e.startsWith(t)),Me=e=>{let t=e.match(es),r;if(t){let[,s,a,i]=t;r={isAndList:Nt(i).isAndList,isExcluded:!!s,key:a,valueText:i}}return r},He=e=>{let t=e.match(ts),r;return t&&(r={isAndList:!1,isExcluded:!!t[1],key:t[2],valueText:""}),r},je=e=>{let t=e.trim(),r=we.find(s=>t.startsWith(s));return{modifier:r,value:r?t.slice(r.length).trim():t}},Qe=e=>ne(e)??e.toLowerCase(),is=(e,t)=>{let r=Qe(t),s=[];for(let{end:a,start:i,token:n}of xe(e)){let o=Me(n);o&&Qe(o.key)===r&&s.push({...o,end:a,start:i,token:n})}return s},Et=e=>Nt(e).parts,Ae=e=>e.replace(/^"|"$/g,""),Ue=e=>{let t=[];for(let r of Et(e)){let s=Ae(r);s&&t.push(s)}return t},ns=/[\s,:+"]/,os=e=>{let t=e.replaceAll('"',"");return ns.test(e)?`"${t}"`:t};var H=require("@flesh-and-blood/types"),Ke=[{description:"Attack actions",expanded:["st:attack"],filters:{subtypes:[H.Subtype.Attack]},isCardProperty:!1,shorthands:["AA"]},{description:"Arcane barrier",expanded:['k:"arcane barrier"'],filters:{keywords:[H.Keyword.ArcaneBarrier]},isCardProperty:!1,shorthands:["AB"]},{description:"Attack reactions",expanded:['t:"attack reaction"'],filters:{types:[H.Type.AttackReaction]},isCardProperty:!1,shorthands:["AR"]},{description:"Defense reactions",expanded:['t:"defense reaction"'],filters:{types:[H.Type.DefenseReaction]},isCardProperty:!1,shorthands:["DR"]},{description:"Gain life",expanded:["gain {h}"],filters:{functionalText:"gain {h}"},isCardProperty:!1,shorthands:["Gain life","Gains life"]},{description:"Go again",expanded:['k:"go again"'],filters:{keywords:[H.Keyword.GoAgain]},isCardProperty:!1,shorthands:["GA"]},{description:"Non-attack actions",expanded:["t:action","st:non-attack"],filters:{subtypes:[H.Subtype.NonAttack],types:[H.Type.Action]},isCardProperty:!1,shorthands:["NAA"]},{description:"Plus defense",expanded:["+ {d}"],filters:{functionalText:"+ {d}"},isCardProperty:!1,shorthands:["Pump defense","Pumps defense","Buff defense","Buffs defense"]},{description:"Spellvoid",expanded:['k:"spellvoid"'],filters:{keywords:[H.Keyword.Spellvoid]},isCardProperty:!1,shorthands:["SV"]}],_e=Ke.filter(({shorthands:e})=>e.some(t=>t.includes(" "))).map(e=>({...e,shorthands:e.shorthands.filter(t=>t.includes(" ")).map(t=>t.toLowerCase()).sort((t,r)=>r.length-t.length)})),Ge=Ke.filter(({shorthands:e})=>e.some(t=>!t.includes(" "))).map(e=>({...e,shorthands:e.shorthands.filter(t=>!t.includes(" ")).map(t=>t.toLowerCase()).sort((t,r)=>r.length-t.length)}));var ls=["\u201C","\u201D"],ds=[{text:ze.Release.ClassicBattlesRhinarDorinthea.toLowerCase(),override:ze.Release.ClassicBattlesRhinarDorinthea.toLowerCase().replaceAll(V.PUNCTUATION,"")}],cs=[...ae[l.Set],...ae[l.Print]],ps=q.map(re).join(""),Bt=new WeakMap,us=e=>{let t=Bt.get(e);if(!t){let r=new Map;for(let{release:a,setIdentifiers:i}of e)r.set(a.toLowerCase(),i);let s=[...r.keys()].sort((a,i)=>i.length-a.length).map(re).join("|");t={setNameInSetFilterPattern:new RegExp(`(?<=^|\\s)([${ps}]?(?:${cs.join("|")}):(?:[^\\s]*[,+])?"?)(${s})(?="?(?:[,+]|\\s|$))`,"g"),setIdentifiersBySetName:r},Bt.set(e,t)}return t},gs=(e,t)=>{let r=e.trim().toLowerCase();for(let o of ls)r=r.replaceAll(o,'"');for(let{expanded:o,shorthands:d}of _e)for(let f of d)if(r.includes(f)){r=r.replace(f,o.join(" "));break}let{setIdentifiersBySetName:s,setNameInSetFilterPattern:a}=us(t.releases);r=r.replace(a,(o,d,f)=>{let c=s.get(f);return c?`${d}${c[0]}`:o});let i=s.get(r),n=t.getCardsByExactName(r).length>0;i&&!n&&(r=`set:${i[0]}`);for(let{override:o,text:d}of ds)r.includes(d)&&(r=r.replace(d,o));return r},fs=e=>{let t=Ge.find(({shorthands:s})=>s.includes(e)),r=!!t&&!t.isCardProperty;return{isExpanded:r,tokens:r?t.expanded:[e]}},ys=e=>{let t=[];for(let{end:r,start:s,token:a}of xe(e)){let{isExpanded:i,tokens:n}=fs(a);for(let o of n)t.push({end:r,isExpanded:i,start:s,token:o})}return t},ms=e=>{let t=[];for(let r of e){let{modifier:s,value:a}=je(r),i=(0,N.getNormalizedFilterValue)(a);i&&t.push({modifier:s,value:i})}return t},Cs=(e,t,r)=>{let s={key:e,reason:"value",values:r},a=Ne(t,r);return a&&(s.suggestedKey=a),s},hs=()=>{let e=new Date,t=`${e.getMonth()+1}`.padStart(2,"0"),r=`${e.getDate()}`.padStart(2,"0");return`${e.getFullYear()}-${t}-${r}`},le=(e,t,{additionalHeroes:r=[],today:s=hs()}={})=>{let a=gs(e,t),i={additionalHeroes:r,index:t,today:s},n=[],o={artists:[],foilings:[],isExpansionSlot:!1,prints:[],rarities:[],releases:[],treatments:[]},d=[],f=[],c=[];for(let g of ys(a)){let C=Me(g.token)||He(g.token);if(C){let{isAndList:x,isExcluded:S,key:P,valueText:b}=C,B=he(P),j=B?.category,z=Ue(b),U=ms(z),Y={...g,canonicalValues:U.map(({value:$})=>$),category:j,filterValues:U,isAnd:x,isExcluded:S,isFilter:!0,isResolved:!0,key:P};if(z.length>0)if(B&&j){let $=z;if(U.length>0){let h=St({category:j,filterValues:U,isAnd:Y.isAnd,isExcluded:S,key:P,mapping:B},i);n.push(...h.appliedFilters),h.canonicalValues&&(Y.canonicalValues=h.canonicalValues),h.attributes&&Object.assign(o,h.attributes),$=h.unresolvedValues}$.length>0&&(Y.isResolved=!1,c.push(Cs(P,j,$)))}else Y.isResolved=!1,c.push({key:P,reason:"key",values:[]});f.push(Y)}else{let{end:x,start:S,token:P}=g;f.push({end:x,isFilter:!1,start:S,token:P});let b=Ae(g.token),B=Ee(b);B.length>0?n.push(...B):b&&d.push(b.replace(V.PUNCTUATION,""))}}return{appliedFilters:n,attributes:o,keywords:d,nodes:f,text:a,unresolvedFilters:c}};var A=require("@flesh-and-blood/types"),Ot={artists:["Hoodwill"],cardIdentifier:"fangs-a-lot-blue",classes:[A.Class.Generic],defaultImage:"FNG000",firstReleaseDate:"2022-06-02",functionalText:"If Fangs A Lot is put into your banished zone from your graveyard, instead put it into your hand.",legalFormats:[],legalHeroes:[A.Hero.Kayo,A.Hero.Levia,A.Hero.Rhinar],printings:[{artists:["Hoodwill"],identifier:"FNG000",image:"FNG000",print:"FNG000",rarity:A.Rarity.Rare,set:A.Release.Promos},{artists:["Hoodwill"],identifier:"FNG000",image:"FNG000_Marvel",print:`FNG000-${A.Treatment.FA}`,rarity:A.Rarity.Marvel,set:A.Release.Promos,treatments:[A.Treatment.FA]}],name:"Fangs A Lot",rarities:[A.Rarity.Rare,A.Rarity.Marvel],rarity:A.Rarity.Rare,sets:[A.Release.Promos],setIdentifiers:["FNG000"],specialImage:"FNG000_Marvel",subtypes:[A.Subtype.Attack],types:[A.Type.Action],typeText:"Generic Action - Attack"},Lt=[{keyword:Ot.name.toLowerCase(),card:Ot}];var G=require("@flesh-and-blood/types");var Fs=3,Ts=e=>{let t=Z(e.toLowerCase()).replace(/[^a-z\s-]/g,""),r=new Set;for(let s of[/[\s-]+/,/\s+/]){let a="";for(let i of t.split(s)){let n=i.replaceAll("-","");n&&(a+=n[0])}a.length>=Fs&&r.add(a)}return[...r]},be=e=>O(e).replaceAll("-",""),$e=(e,t,r)=>{let s=e.get(t);s?s.push(r):e.set(t,[r])},Dt=new WeakMap,L=Object.freeze([]),xs=Number.MAX_SAFE_INTEGER,Qt=(e,t)=>{let r=new Map;for(let s of e)for(let a of t(s)||[]){let i=r.get(a);i?i.push(s):r.set(a,[s])}return r},Ms=e=>{let t=new Map;for(let r of e){let s=r.types.includes(G.Type.Hero)&&!r.isCardBack,a=s?G.CardRole.Hero:(0,G.getCardRole)(r);if(s||a!==G.CardRole.Hero){let n=t.get(a);n?n.push(r):t.set(a,[r])}}return t},As=e=>{let t=new Map,r=new Map,s=new Map;for(let a of e){t.set((0,G.getNormalizedFilterValue)(a.release),a),r.set(a.release,a);for(let i of a.setIdentifiers)s.set(i.toLowerCase(),a)}return{releaseByFilterName:t,releaseByRelease:r,releaseBySetIdentifier:s}},bs=(e,t)=>{let r,s=new Map,a,i,n,o,d,f,c,g,C=()=>{if(!a){let p=new Map,y=new Map,F=[],M=new Map,R=0;for(let Q of e){p.set(Q.cardIdentifier,Q),y.set(Q.cardIdentifier,R),R++;let w=O(Q.name),ue=M.get(w);ue?ue.push(Q):(M.set(w,[Q]),F.push(w))}a={cardByCardIdentifier:p,corpusPositionByCardIdentifier:y,cleanedNames:F,pitchCycleByCleanedName:M}}return a},x=p=>{let{corpusPositionByCardIdentifier:y}=C(),F=({cardIdentifier:M})=>y.get(M)??xs;return[...p].sort((M,R)=>F(M)-F(R))},S=p=>C().cardByCardIdentifier.get(p),P=p=>{let{cardByCardIdentifier:y}=C(),F=[];for(let M of p||[]){let R=y.get(M);R&&F.push(R)}return x(F)},b=p=>{let y=new Map;return F=>{let M=y.get(F);if(!M){let R=S(F),Q=P(R&&p(R)),w=Q.length>0;M=w?Q:L,w&&y.set(F,M)}return M}},B=p=>{let{pitchCycleByCleanedName:y}=C(),F=S(p);return F?y.get(O(F.name))??L:L},j=p=>{let{cleanedNames:y,pitchCycleByCleanedName:F}=C(),M=O(p),R=F.get(M);if(!R&&M.length>0){let w=y.find(ue=>ue.includes(M));w&&(R=F.get(w))}return R??L},z=p=>{let{pitchCycleByCleanedName:y}=C();return y.get(O(p))??L},U=p=>{if(!f){f=new Map;for(let y of e)for(let F of y.nicknames??[])$e(f,be(F),y)}return f.get(be(p))??L},Y=p=>{if(!c){c=new Map;for(let y of e)for(let F of[...y.types,...y.subtypes,...y.traits??[]])$e(c,be(F),y)}return c.get(be(p))??L},$=p=>{if(!g){g=new Map;for(let y of e)for(let F of Ts(y.name))$e(g,F,y)}return g.get(p)??L},h=()=>{if(!d){let p=new Set;for(let y of e)for(let F of y.artists)p.add(F);d=[...p].sort((y,F)=>y.localeCompare(F,"en",{sensitivity:"base"}))}return d},K=b(({oppositeSideCardIdentifiers:p})=>p),k=b(({referencedCards:p})=>p),v=p=>(i||(i=Qt(e,({referencedCards:y})=>y)),i.get(p)??L),D=b(({createdExtras:p})=>p),X=p=>(n||(n=Qt(e,({createdExtras:y})=>y)),n.get(p)??L),I=p=>{let y=new Map,F=new Set,M=[...p];for(let R of M)if(!F.has(R)){F.add(R);for(let w of D(R))y.set(w.cardIdentifier,w),M.push(w.cardIdentifier)}return x([...y.values()])},W=()=>(r||(r=As(t)),r),pe=p=>W().releaseByRelease.get(p);return{cards:e,releases:t,getCard:S,getRelease:pe,getReleaseByName:p=>W().releaseByFilterName.get((0,G.getNormalizedFilterValue)(p)),getReleaseBySetIdentifier:p=>W().releaseBySetIdentifier.get(p.toLowerCase()),getReleaseHeroCards:p=>{let y=s.get(p);if(!y){let F=pe(p),M=P(F?.heroIdentifiers),R=M.length>0;y=R?M:L,R&&s.set(p,y)}return y},getPitchCycle:B,getCardsByName:j,getCardsByExactName:z,getCardsByNickname:U,getCardsByGroup:Y,getCardsByInitials:$,getArtists:h,getOppositeSide:K,getReferences:k,getReferencedBy:v,getCreates:D,getCreatedBy:X,getCreatedClosure:I,getByRole:p=>(o||(o=Ms(e)),o.get(p)??L),getCardsInCorpusOrder:x}},We=(e,t)=>{let r=Dt.get(e);r||(r=new WeakMap,Dt.set(e,r));let s=r.get(t);return s||(s=bs(e,t),r.set(t,s)),s},Rs=(e,t)=>e.getCardsByName(t);var Ps={getFn:(e,t)=>{let r=qe.default.config.getFn(e,t),s=r;if(Array.isArray(r))s=r.map(a=>{let i=typeof a=="string"?a:a.v;return Z(i.replace(V.PUNCTUATION,""))});else if(r){let a=Z(r).replace(V.PUNCTUATION,"");s=t.includes("functionalText")?te(a):a}return s},ignoreLocation:!0,includeScore:!0,keys:[{name:"name",weight:10},{name:"functionalText",weight:6},{name:"shorthands",weight:4},{name:"setIdentifiers",weight:2},{name:"traits",weight:4},{name:"typeText",weight:6}],threshold:.15,useExtendedSearch:!0},Ye=class{constructor(t,r){this.getFuse=()=>(this.fuse||(this.fuse=new qe.default(this.cards,Ps)),this.fuse);this.getPoolCards=t=>{this.poolCardByCardIdentifier||(this.poolCardByCardIdentifier=new Map(this.cards.map(s=>[s.cardIdentifier,s])));let r=[];for(let{cardIdentifier:s}of t){let a=this.poolCardByCardIdentifier.get(s);a&&r.push(a)}return r};this.search=(t,r)=>{let s,a,{appliedFilters:i,attributes:n,keywords:o,unresolvedFilters:d}=le(t,this.index,{additionalHeroes:this.additionalHeroes}),f=o.join(" "),c=r?Lt.filter(h=>h.keyword===f):[],g=h=>i.length>0?h.filter(K=>K&&Ut(K,i)):h;if(c.length>0)s=g(c.map(({card:h})=>h));else if(o.length){let h=O(f),K=this.getPoolCards(this.index.getCardsByNickname(h)),k=new Map;for(let I of[...this.getPoolCards(this.index.getCardsByExactName(h)),...K])k.set(I.cardIdentifier,I);let v=this.getFuse().search(f).map(I=>I.item).filter(({cardIdentifier:I})=>!k.has(I));s=g([...k.values(),...v]),s.some(I=>K.includes(I))&&(a={kind:"nickname",text:h}),s.length===0&&o.length===1&&(s=g(this.getPoolCards(this.index.getCardsByInitials(h))),s.length>0&&(a={kind:"initials",text:h}))}else s=g([...this.cards]);if(!(o.length>0&&a?.kind!=="initials")){let h="";if(n.releases.length===1){let v=this.index.getRelease(n.releases[0])?.setIdentifiers;v?.length&&(h=v[0].toUpperCase())}if(!h&&n.prints.length===1){let v=n.prints[0];this.index.getReleaseBySetIdentifier(v)&&(h=v.toUpperCase())}h?s.sort((v,D)=>{let X=v.setIdentifiers.find(W=>W.includes(h))?.replace(h,""),I=D.setIdentifiers.find(W=>W.includes(h))?.replace(h,"");return X&&I?X.localeCompare(I):-1}):s.sort((v,D)=>v.name===D.name?`${v.pitch}`.localeCompare(`${D.pitch}`):v.name.localeCompare(D.name))}let x=[],{artists:S,isExpansionSlot:P,foilings:b,prints:B,rarities:j,releases:z,treatments:U}=n;(S.length>0||P||b.length>0||B.length>0||j.length>0||z.length>0||U.length>0)&&(x=s.map(h=>{let K=h.printings.filter(k=>{let v=!!k.image,D=S.length===0||S.some(ee=>k.artists.find(p=>p.replace(V.PUNCTUATION,"").toLowerCase().includes(ee))),X=!P||P===k.isExpansionSlot,I=b.length===0||!!k.foiling&&b.includes(k.foiling),W=B.length===0||B.some(ee=>k.identifier.includes(ee.toUpperCase())),pe=j.length===0||j.includes(k.rarity),Xe=z.length===0||z.includes(k.set),Ze=U.length===0||k.treatments?.some(ee=>U.includes(ee));return v&&D&&X&&I&&W&&pe&&Xe&&Ze});return{...h,matchingPrintings:K}}));let $=x.length>0?x:s;return{alias:a,appliedFilters:i,attributes:n,keywords:o,searchResults:$,unresolvedFilters:d}};this.additionalHeroes=r.additionalHeroes||[],this.cards=[...t],this.index=r.index||We(t,r.releases)}},jt=Ye,Ut=(e,t)=>{let r=!0;for(let s of t){let{isNumber:a,isString:i,isArray:n,isBoolean:o,isDate:d}=s.filterToPropertyMapping;s.isOptional||(a?r=r&&vs(e,s):i?r=r&&ks(e,s):n?r=r&&Is(e,s,t):o?r=r&&Ss(e,s):d&&(r=r&&ws(e,s)))}return r},Ht=(e,t,r)=>{let s=parseInt(t),a;switch(r){case">=":a=e>=s;break;case">":a=e>s;break;case"<=":a=e<=s;break;case"<":a=e<s;break;default:a=e===s}return a},vs=(e,t)=>{let{filterValues:r,values:s,modifier:a,isExcluded:i,filterToPropertyMapping:{partialMatch:n}}=t,o=!0;if(ce(t,e)){let d=de(e,t),f;if(d!=null&&!isNaN(d)){let c=parseInt(d);f=r?r.some(({modifier:g,value:C})=>Ht(c,C,g)):s.some(g=>Ht(c,g,a))}else{let c=Ns(e,t)?.toLowerCase();f=n?s.some(g=>!!c?.includes(g)):s.some(g=>c===g)}o=i?!f:f}return o},ks=(e,t)=>{if(ce(t,e)){let{values:r,valuesSet:s,isAnd:a,isExcluded:i,filterToPropertyMapping:{hasMarkup:n,isNormalized:o,partialMatch:d}}=t,f=de(e,t),c=o?f:f?.replaceAll(V.PUNCTUATION,"").toLowerCase(),g=n&&c?te(c):c;if(d){let C=a?r?.every(x=>g?.includes(x)):r?.some(x=>g?.includes(x));return i?!C:C}else{let C;return a?C=r?.every(x=>g===x):s?C=s.has(g):C=r?.some(x=>g===x),i?!C:C}}else return!0},Is=(e,t,r)=>{if(ce(t,e)){let{values:s,isAnd:a,isExcluded:i,filterToPropertyMapping:{partialMatch:n}}=t,o=Vs(e,t,r).map(d=>d?.replaceAll(V.PUNCTUATION,""));if(n){let d=a?s.every(c=>o?.some(g=>g?.toLowerCase().includes(c))):s.some(c=>o?.some(g=>g?.toLowerCase().includes(c))),f=o.length===0;return i?!d||f:d}else{let d=a?s.every(f=>o?.some(c=>c?.toLowerCase()===f)):s.some(f=>o?.some(c=>c?.toLowerCase()===f));return i?!d:d}}else return!0},Ss=(e,t)=>{if(ce(t,e)){let{isExcluded:r}=t,s=de(e,t);return r?!s:s}else return!0},ws=(e,t)=>{if(ce(t,e)){let{values:r,isExcluded:s}=t,a=de(e,t),i=r?.some(n=>a>n);return s?!i:i}else return!0},de=(e,t)=>{let{filterToPropertyMapping:{property:r}}=t,s;return r!==_&&(s=e[r]),s},Vs=(e,t,r)=>{let{filterToPropertyMapping:{isNestedPropertyArray:s,nestedProperty:a}}=t,i=[],n=Object.keys(e.legalOverrides||{}).length>0,o=t.filterToPropertyMapping.property===J.LegalHeroes,d=r.find(({filterToPropertyMapping:c})=>c.property===J.LegalFormats);if(n&&o&&!!d){let c=new Set;for(let{format:g,heroes:C}of e.legalOverrides||[])if(d.values.includes(g.toLowerCase()))for(let x of C)c.add(x);i=Array.from(c)}if(i.length===0)if(a){let c=new Set;for(let g of e.printings){let C=g[a];if(s){if(Array.isArray(C))for(let x of C)c.add(x)}else C&&typeof C=="string"&&c.add(C)}i=Array.from(c)}else{let c=de(e,t);if(Array.isArray(c))for(let g of c)typeof g=="string"&&i.push(g)}return i},Ns=(e,t)=>{let{filterToPropertyMapping:{specialProperty:r}}=t,s;return r&&(s=e[r]),s},ce=({cardTypes:e},{types:t,subtypes:r})=>!e||e?.some(s=>t.map(a=>a.toLowerCase()).includes(s.toLowerCase())||r.map(a=>a.toLowerCase()).includes(s.toLowerCase()));var Es=(e,t,r=[],s)=>{let{appliedFilters:a,attributes:i,keywords:n}=le(e,t,{additionalHeroes:r,today:s});return{appliedFilters:a,attributes:i,keywords:n}};var Bs=(e,t)=>{let r=new Set;for(let a of e)for(let i of a.createdExtras||[])r.add(i);let s=[];for(let a of t)r.has(a.cardIdentifier)&&s.push(a);return s};0&&(module.exports={FilterCategory,FilterKind,FilterProperty,MARKUP,NO_CARD_PROPERTY,PUNCTUATION,RARITY_VALUES_MAPPING,aliasesByFilterCategory,availableExclusions,availableModifiers,filterCard,filtersToCardPropertyMappings,getCardsByName,getCatalogueIndex,getCleanText,getEscapedForRegExp,getExcludedMetaFilters,getFilterCategory,getFilterMapping,getFilterTokenSpansForKey,getFilterValue,getIncompleteFilterToken,getIsExcludedToken,getIsValueInFilterVocabulary,getKeywordsAndAppliedFiltersFromText,getMetaFilterResolution,getMetaFilters,getNormalizedFilterValue,getNormalizedText,getParsedQuery,getQueryFilterToken,getQueryTokenSpans,getQuotedValue,getResolvedFilterKey,getSuggestedFilterKey,getTextWithoutMarkup,getTokensReferencedByCards,getUnquotedValue,getValuePartsFromFilterValue,getValuesFromFilterValue,multiWordShorthands,shorthands,singleWordShorthands});
@@ -1,4 +1,4 @@
1
- import { Hero, Release } from "@flesh-and-blood/types";
1
+ import { Hero } from "@flesh-and-blood/types";
2
2
  import { FilterCategory, type AppliedFilter, type FilterValue } from "./filterMappings.js";
3
3
  import { type QueryAttributes } from "./filterResolvers.js";
4
4
  import { type QueryTokenSpan } from "./queryTokens.js";
@@ -64,8 +64,7 @@ export interface ParsedQuery {
64
64
  }
65
65
  export interface ParseOptions {
66
66
  additionalHeroes?: Hero[];
67
- additionalSets?: Release[];
68
67
  /** Today, for the filters that compare a release date against it. */
69
68
  today?: string;
70
69
  }
71
- export declare const getParsedQuery: (text: string, index: CatalogueIndex, { additionalHeroes, additionalSets, today, }?: ParseOptions) => ParsedQuery;
70
+ export declare const getParsedQuery: (text: string, index: CatalogueIndex, { additionalHeroes, today }?: ParseOptions) => ParsedQuery;
@@ -1,7 +1,4 @@
1
- import {
2
- Release,
3
- setToSetIdentifierMappings
4
- } from "@flesh-and-blood/types";
1
+ import { Release } from "@flesh-and-blood/types";
5
2
  import { PUNCTUATION } from "./constants.js";
6
3
  import {
7
4
  aliasesByFilterCategory,
@@ -34,26 +31,33 @@ const punctuationOverrides = [
34
31
  )
35
32
  }
36
33
  ];
37
- const setIdentifiersBySetName = new Map(
38
- [...setToSetIdentifierMappings].map(
39
- ([release, setIdentifiers]) => [
40
- release.toLowerCase(),
41
- setIdentifiers
42
- ]
43
- )
44
- );
45
34
  const SET_FILTER_KEYS = [
46
35
  ...aliasesByFilterCategory[FilterCategory.Set],
47
36
  ...aliasesByFilterCategory[FilterCategory.Print]
48
37
  ];
49
38
  const EXCLUSION_CHARACTERS = availableExclusions.map(getEscapedForRegExp).join("");
50
- const setNamesLongestFirst = [...setIdentifiersBySetName.keys()].sort((first, second) => second.length - first.length).map(getEscapedForRegExp).join("|");
51
- const setNameInSetFilterPattern = new RegExp(
52
- `(?<=^|\\s)([${EXCLUSION_CHARACTERS}]?(?:${SET_FILTER_KEYS.join(
53
- "|"
54
- )}):(?:[^\\s]*[,+])?"?)(${setNamesLongestFirst})(?="?(?:[,+]|\\s|$))`,
55
- "g"
56
- );
39
+ const setNameRewriteByReleases = /* @__PURE__ */ new WeakMap();
40
+ const getSetNameRewrite = (releases) => {
41
+ let setNameRewrite = setNameRewriteByReleases.get(releases);
42
+ if (!setNameRewrite) {
43
+ const setIdentifiersBySetName = /* @__PURE__ */ new Map();
44
+ for (const { release, setIdentifiers } of releases) {
45
+ setIdentifiersBySetName.set(release.toLowerCase(), setIdentifiers);
46
+ }
47
+ const setNamesLongestFirst = [...setIdentifiersBySetName.keys()].sort((first, second) => second.length - first.length).map(getEscapedForRegExp).join("|");
48
+ setNameRewrite = {
49
+ setNameInSetFilterPattern: new RegExp(
50
+ `(?<=^|\\s)([${EXCLUSION_CHARACTERS}]?(?:${SET_FILTER_KEYS.join(
51
+ "|"
52
+ )}):(?:[^\\s]*[,+])?"?)(${setNamesLongestFirst})(?="?(?:[,+]|\\s|$))`,
53
+ "g"
54
+ ),
55
+ setIdentifiersBySetName
56
+ };
57
+ setNameRewriteByReleases.set(releases, setNameRewrite);
58
+ }
59
+ return setNameRewrite;
60
+ };
57
61
  const getPreparedText = (text, index) => {
58
62
  let preparedText = text.trim().toLowerCase();
59
63
  for (const smartQuote of SMART_DOUBLE_QUOTES) {
@@ -67,6 +71,7 @@ const getPreparedText = (text, index) => {
67
71
  }
68
72
  }
69
73
  }
74
+ const { setIdentifiersBySetName, setNameInSetFilterPattern } = getSetNameRewrite(index.releases);
70
75
  preparedText = preparedText.replace(
71
76
  setNameInSetFilterPattern,
72
77
  (setNameInSetFilter, filterPrefix, setName) => {
@@ -131,15 +136,10 @@ const getTodayAsReleaseDate = () => {
131
136
  const dayOfMonth = `${now.getDate()}`.padStart(2, "0");
132
137
  return `${now.getFullYear()}-${month}-${dayOfMonth}`;
133
138
  };
134
- const getParsedQuery = (text, index, {
135
- additionalHeroes = [],
136
- additionalSets = [],
137
- today = getTodayAsReleaseDate()
138
- } = {}) => {
139
+ const getParsedQuery = (text, index, { additionalHeroes = [], today = getTodayAsReleaseDate() } = {}) => {
139
140
  const preparedText = getPreparedText(text, index);
140
141
  const context = {
141
142
  additionalHeroes,
142
- additionalSets,
143
143
  index,
144
144
  today
145
145
  };
package/dist/search.d.ts CHANGED
@@ -1,23 +1,29 @@
1
- import { Card, DoubleSidedCard, Hero, Printing, Release } from "@flesh-and-blood/types";
1
+ import { Card, DoubleSidedCard, Hero, Printing, ReleaseInfo } from "@flesh-and-blood/types";
2
2
  import { AppliedFilter } from "./filterMappings.js";
3
3
  import { QueryAttributes, UnresolvedFilter } from "./queryParse.js";
4
4
  import { CatalogueIndex } from "./searchIndex.js";
5
5
  export interface SearchCard extends DoubleSidedCard {
6
6
  matchingPrintings?: Printing[];
7
7
  }
8
- export interface SearchOptions {
8
+ /**
9
+ * The catalogue the parser resolves names, sets and relations against: an index
10
+ * built elsewhere, or the releases the corpus ships with, making the corpus its
11
+ * own catalogue. A pool searched out of a larger catalogue shares the
12
+ * catalogue's index, so a relation is answered from every card that carries it
13
+ * while the search still answers with the pool alone. The pool must be a subset
14
+ * of the catalogue the index was built over: a pool card the catalogue does not
15
+ * hold resolves to nothing, with no error.
16
+ */
17
+ type SearchCatalogue = {
18
+ index: CatalogueIndex;
19
+ releases?: never;
20
+ } | {
21
+ index?: never;
22
+ releases: readonly ReleaseInfo[];
23
+ };
24
+ export type SearchOptions = SearchCatalogue & {
9
25
  additionalHeroes?: Hero[];
10
- additionalSets?: Release[];
11
- /**
12
- * The catalogue the parser resolves names and relations against. A pool
13
- * searched out of a larger catalogue shares the catalogue's index, so a
14
- * relation is answered from every card that carries it while the search still
15
- * answers with the pool alone. Left out, the corpus is its own catalogue.
16
- * The pool must be a subset of the catalogue the index was built over: a pool
17
- * card the catalogue does not hold resolves to nothing, with no error.
18
- */
19
- index?: CatalogueIndex;
20
- }
26
+ };
21
27
  /** How the free text named cards other than by their names. */
22
28
  export interface SearchAlias {
23
29
  kind: "nickname" | "initials";
@@ -38,13 +44,11 @@ export interface SearchResults {
38
44
  }
39
45
  declare class Search {
40
46
  private additionalHeroes;
41
- private additionalSets;
42
47
  private cards;
43
48
  private fuse;
44
49
  private index;
45
50
  private poolCardByCardIdentifier;
46
- constructor(cards: DoubleSidedCard[], options?: SearchOptions);
47
- constructor(cards: DoubleSidedCard[], additionalHeroes?: Hero[], additionalSets?: Release[]);
51
+ constructor(cards: DoubleSidedCard[], options: SearchOptions);
48
52
  private getFuse;
49
53
  /**
50
54
  * The pool's own copies of index cards, dropping any the pool lacks, so a pool
package/dist/search.js CHANGED
@@ -1,7 +1,3 @@
1
- import {
2
- setIdentifierToSetMappings,
3
- setToSetIdentifierMappings
4
- } from "@flesh-and-blood/types";
5
1
  import Fuse from "fuse.js";
6
2
  import { PUNCTUATION } from "./constants.js";
7
3
  import {
@@ -47,7 +43,7 @@ const searchOptions = {
47
43
  useExtendedSearch: true
48
44
  };
49
45
  class Search {
50
- constructor(cards, additionalHeroesOrOptions = [], additionalSets = []) {
46
+ constructor(cards, options) {
51
47
  // Scoring the corpus is the costly half of a search, so a catalogue that is
52
48
  // only ever filtered never pays to index it.
53
49
  this.getFuse = () => {
@@ -79,8 +75,7 @@ class Search {
79
75
  let results;
80
76
  let alias;
81
77
  const { appliedFilters, attributes, keywords, unresolvedFilters } = getParsedQuery(text, this.index, {
82
- additionalHeroes: this.additionalHeroes,
83
- additionalSets: this.additionalSets
78
+ additionalHeroes: this.additionalHeroes
84
79
  });
85
80
  const keyword = keywords.join(" ");
86
81
  const matchingMemes = includeMemes ? memes.filter((meme) => meme.keyword === keyword) : [];
@@ -131,9 +126,9 @@ class Search {
131
126
  let setIdentifierToSortBy = "";
132
127
  const shouldSortByRelease = attributes.releases.length === 1;
133
128
  if (shouldSortByRelease) {
134
- const matchingSetIdentifiers = setToSetIdentifierMappings.get(
129
+ const matchingSetIdentifiers = this.index.getRelease(
135
130
  attributes.releases[0]
136
- );
131
+ )?.setIdentifiers;
137
132
  if (matchingSetIdentifiers?.length) {
138
133
  setIdentifierToSortBy = matchingSetIdentifiers[0].toUpperCase();
139
134
  }
@@ -141,7 +136,7 @@ class Search {
141
136
  const shouldSortByPrint = !setIdentifierToSortBy && attributes.prints.length === 1;
142
137
  if (shouldSortByPrint) {
143
138
  const setToSort = attributes.prints[0];
144
- if (setIdentifierToSetMappings.has(setToSort)) {
139
+ if (this.index.getReleaseBySetIdentifier(setToSort)) {
145
140
  setIdentifierToSortBy = setToSort.toUpperCase();
146
141
  }
147
142
  }
@@ -206,11 +201,9 @@ class Search {
206
201
  unresolvedFilters
207
202
  };
208
203
  };
209
- const options = Array.isArray(additionalHeroesOrOptions) ? { additionalHeroes: additionalHeroesOrOptions, additionalSets } : additionalHeroesOrOptions;
210
204
  this.additionalHeroes = options.additionalHeroes || [];
211
- this.additionalSets = options.additionalSets || [];
212
205
  this.cards = [...cards];
213
- this.index = options.index || getCatalogueIndex(cards);
206
+ this.index = options.index || getCatalogueIndex(cards, options.releases);
214
207
  }
215
208
  }
216
209
  var search_default = Search;
@@ -1,7 +1,7 @@
1
- import { Card, CardRole, DoubleSidedCard } from "@flesh-and-blood/types";
1
+ import { CardRole, DoubleSidedCard, ReleaseInfo } from "@flesh-and-blood/types";
2
2
  /**
3
- * Everything a corpus can be asked about its cards: lookups, the relations the
4
- * cards carry, and what each card is for. Every relation is identifier-level,
3
+ * Everything a corpus can be asked about its cards and releases: lookups, the
4
+ * relations the cards carry, and what each card is for. Every relation is identifier-level,
5
5
  * so a card named at one pitch answers for that pitch alone; widening a
6
6
  * relation to the whole name is the reader's rule rather than the corpus's.
7
7
  * Every list-returning read but `getCreatedClosure` and `getCardsInCorpusOrder`
@@ -11,7 +11,17 @@ import { Card, CardRole, DoubleSidedCard } from "@flesh-and-blood/types";
11
11
  */
12
12
  export interface CatalogueIndex<CardType extends DoubleSidedCard = DoubleSidedCard> {
13
13
  cards: readonly CardType[];
14
+ /** Every release the corpus ships with, in release order. */
15
+ releases: readonly ReleaseInfo[];
14
16
  getCard: (cardIdentifier: string) => CardType | undefined;
17
+ /** The release a card's sets name, matched exactly. */
18
+ getRelease: (release: string) => ReleaseInfo | undefined;
19
+ /** The release with the name, read as a filter reads it. */
20
+ getReleaseByName: (name: string) => ReleaseInfo | undefined;
21
+ /** The release carrying the set identifier, in any case. */
22
+ getReleaseBySetIdentifier: (setIdentifier: string) => ReleaseInfo | undefined;
23
+ /** The hero cards the release is for. */
24
+ getReleaseHeroCards: (release: string) => readonly CardType[];
15
25
  /** Every pitch of the card's name, the card itself among them. */
16
26
  getPitchCycle: (cardIdentifier: string) => readonly CardType[];
17
27
  /**
@@ -28,6 +38,11 @@ export interface CatalogueIndex<CardType extends DoubleSidedCard = DoubleSidedCa
28
38
  getCardsByExactName: (name: string) => readonly CardType[];
29
39
  /** Every card carrying the nickname, matched whole, hyphens ignored. */
30
40
  getCardsByNickname: (nickname: string) => readonly CardType[];
41
+ /**
42
+ * Every card carrying the type, subtype or trait, matched whole, hyphens
43
+ * ignored.
44
+ */
45
+ getCardsByGroup: (group: string) => readonly CardType[];
31
46
  /**
32
47
  * Every card whose name has the initials, in corpus order, counting a
33
48
  * hyphenated word both as one word and as the words the hyphens join.
@@ -64,15 +79,12 @@ export interface CatalogueIndex<CardType extends DoubleSidedCard = DoubleSidedCa
64
79
  getCardsInCorpusOrder: <OrderedCard extends DoubleSidedCard>(cardsToOrder: readonly OrderedCard[]) => OrderedCard[];
65
80
  }
66
81
  /**
67
- * The index for a corpus, one per array, so everything reading the same cards
68
- * shares its maps. Each map is built the first time a read asks for it. The
69
- * array is treated as immutable from that first read on: a caller that changes
70
- * which cards the catalogue holds builds a new array.
82
+ * The index for a corpus, one per pair of cards and releases arrays, so
83
+ * everything reading the same catalogue shares its maps. Each map is built the
84
+ * first time a read asks for it. Both arrays are treated as immutable from that
85
+ * first read on: a caller that changes what the catalogue holds builds a new
86
+ * array.
71
87
  */
72
- export declare const getCatalogueIndex: <CardType extends DoubleSidedCard = DoubleSidedCard>(cards: readonly CardType[]) => CatalogueIndex<CardType>;
88
+ export declare const getCatalogueIndex: <CardType extends DoubleSidedCard = DoubleSidedCard>(cards: readonly CardType[], releases: readonly ReleaseInfo[]) => CatalogueIndex<CardType>;
73
89
  /** {@link CatalogueIndex.getCardsByName}, as a free function over an index. */
74
90
  export declare const getCardsByName: (index: CatalogueIndex, name: string) => readonly DoubleSidedCard[];
75
- /** The cards naming the card, at every pitch of both. */
76
- export declare const getCardsReferencing: (index: CatalogueIndex, card: Card) => DoubleSidedCard[];
77
- /** The cards the card names, at every pitch of both. */
78
- export declare const getCardsReferencedBy: (index: CatalogueIndex, card: Card) => DoubleSidedCard[];
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  CardRole,
3
3
  getCardRole,
4
+ getNormalizedFilterValue,
4
5
  Type
5
6
  } from "@flesh-and-blood/types";
6
7
  import { getCleanText, getNormalizedText } from "./helpers.js";
@@ -25,7 +26,7 @@ const getInitialsOfName = (name) => {
25
26
  }
26
27
  return [...initialsOfName];
27
28
  };
28
- const getNicknameKey = (nickname) => getCleanText(nickname).replaceAll("-", "");
29
+ const getHyphenFreeKey = (text) => getCleanText(text).replaceAll("-", "");
29
30
  const addToCardList = (cardsByKey, key, card) => {
30
31
  const cardsForKey = cardsByKey.get(key);
31
32
  if (cardsForKey) {
@@ -34,7 +35,7 @@ const addToCardList = (cardsByKey, key, card) => {
34
35
  cardsByKey.set(key, [card]);
35
36
  }
36
37
  };
37
- const catalogueIndexByCards = /* @__PURE__ */ new WeakMap();
38
+ const catalogueIndexByReleasesByCards = /* @__PURE__ */ new WeakMap();
38
39
  const noCards = Object.freeze([]);
39
40
  const strayCorpusPosition = Number.MAX_SAFE_INTEGER;
40
41
  const getNamingCardsByNamedCardIdentifier = (cards, getNamedCardIdentifiers) => {
@@ -68,13 +69,32 @@ const getCardsByRole = (cards) => {
68
69
  }
69
70
  return cardsByRole;
70
71
  };
71
- const getNewCatalogueIndex = (cards) => {
72
+ const getNewReleaseLookups = (releases) => {
73
+ const releaseByFilterName = /* @__PURE__ */ new Map();
74
+ const releaseByRelease = /* @__PURE__ */ new Map();
75
+ const releaseBySetIdentifier = /* @__PURE__ */ new Map();
76
+ for (const releaseInfo of releases) {
77
+ releaseByFilterName.set(
78
+ getNormalizedFilterValue(releaseInfo.release),
79
+ releaseInfo
80
+ );
81
+ releaseByRelease.set(releaseInfo.release, releaseInfo);
82
+ for (const setIdentifier of releaseInfo.setIdentifiers) {
83
+ releaseBySetIdentifier.set(setIdentifier.toLowerCase(), releaseInfo);
84
+ }
85
+ }
86
+ return { releaseByFilterName, releaseByRelease, releaseBySetIdentifier };
87
+ };
88
+ const getNewCatalogueIndex = (cards, releases) => {
89
+ let releaseLookups;
90
+ const releaseHeroCardsByRelease = /* @__PURE__ */ new Map();
72
91
  let cardLookups;
73
92
  let referencingCardsByCardIdentifier;
74
93
  let creatingCardsByCardIdentifier;
75
94
  let cardsByRole;
76
95
  let artists;
77
96
  let cardsByNicknameKey;
97
+ let cardsByGroup;
78
98
  let cardsByInitials;
79
99
  const getCardLookups = () => {
80
100
  if (!cardLookups) {
@@ -169,11 +189,30 @@ const getNewCatalogueIndex = (cards) => {
169
189
  cardsByNicknameKey = /* @__PURE__ */ new Map();
170
190
  for (const card of cards) {
171
191
  for (const cardNickname of card.nicknames ?? []) {
172
- addToCardList(cardsByNicknameKey, getNicknameKey(cardNickname), card);
192
+ addToCardList(
193
+ cardsByNicknameKey,
194
+ getHyphenFreeKey(cardNickname),
195
+ card
196
+ );
197
+ }
198
+ }
199
+ }
200
+ return cardsByNicknameKey.get(getHyphenFreeKey(nickname)) ?? noCards;
201
+ };
202
+ const getCardsByGroup = (group) => {
203
+ if (!cardsByGroup) {
204
+ cardsByGroup = /* @__PURE__ */ new Map();
205
+ for (const card of cards) {
206
+ for (const cardGroup of [
207
+ ...card.types,
208
+ ...card.subtypes,
209
+ ...card.traits ?? []
210
+ ]) {
211
+ addToCardList(cardsByGroup, getHyphenFreeKey(cardGroup), card);
173
212
  }
174
213
  }
175
214
  }
176
- return cardsByNicknameKey.get(getNicknameKey(nickname)) ?? noCards;
215
+ return cardsByGroup.get(getHyphenFreeKey(group)) ?? noCards;
177
216
  };
178
217
  const getCardsByInitials = (initials) => {
179
218
  if (!cardsByInitials) {
@@ -244,6 +283,28 @@ const getNewCatalogueIndex = (cards) => {
244
283
  }
245
284
  return getCardsInCorpusOrder([...createdCardByCardIdentifier.values()]);
246
285
  };
286
+ const getReleaseLookups = () => {
287
+ if (!releaseLookups) {
288
+ releaseLookups = getNewReleaseLookups(releases);
289
+ }
290
+ return releaseLookups;
291
+ };
292
+ const getRelease = (release) => getReleaseLookups().releaseByRelease.get(release);
293
+ const getReleaseByName = (name) => getReleaseLookups().releaseByFilterName.get(getNormalizedFilterValue(name));
294
+ const getReleaseBySetIdentifier = (setIdentifier) => getReleaseLookups().releaseBySetIdentifier.get(setIdentifier.toLowerCase());
295
+ const getReleaseHeroCards = (release) => {
296
+ let releaseHeroCards = releaseHeroCardsByRelease.get(release);
297
+ if (!releaseHeroCards) {
298
+ const releaseInfo = getRelease(release);
299
+ const heroCards = getNamedCards(releaseInfo?.heroIdentifiers);
300
+ const namesHeroCards = heroCards.length > 0;
301
+ releaseHeroCards = namesHeroCards ? heroCards : noCards;
302
+ if (namesHeroCards) {
303
+ releaseHeroCardsByRelease.set(release, releaseHeroCards);
304
+ }
305
+ }
306
+ return releaseHeroCards;
307
+ };
247
308
  const getByRole = (role) => {
248
309
  if (!cardsByRole) {
249
310
  cardsByRole = getCardsByRole(cards);
@@ -252,11 +313,17 @@ const getNewCatalogueIndex = (cards) => {
252
313
  };
253
314
  return {
254
315
  cards,
316
+ releases,
255
317
  getCard,
318
+ getRelease,
319
+ getReleaseByName,
320
+ getReleaseBySetIdentifier,
321
+ getReleaseHeroCards,
256
322
  getPitchCycle,
257
323
  getCardsByName: getCardsByName2,
258
324
  getCardsByExactName,
259
325
  getCardsByNickname,
326
+ getCardsByGroup,
260
327
  getCardsByInitials,
261
328
  getArtists,
262
329
  getOppositeSide,
@@ -269,42 +336,21 @@ const getNewCatalogueIndex = (cards) => {
269
336
  getCardsInCorpusOrder
270
337
  };
271
338
  };
272
- const getCatalogueIndex = (cards) => {
273
- let catalogueIndex = catalogueIndexByCards.get(cards);
339
+ const getCatalogueIndex = (cards, releases) => {
340
+ let catalogueIndexByReleases = catalogueIndexByReleasesByCards.get(cards);
341
+ if (!catalogueIndexByReleases) {
342
+ catalogueIndexByReleases = /* @__PURE__ */ new WeakMap();
343
+ catalogueIndexByReleasesByCards.set(cards, catalogueIndexByReleases);
344
+ }
345
+ let catalogueIndex = catalogueIndexByReleases.get(releases);
274
346
  if (!catalogueIndex) {
275
- catalogueIndex = getNewCatalogueIndex(cards);
276
- catalogueIndexByCards.set(cards, catalogueIndex);
347
+ catalogueIndex = getNewCatalogueIndex(cards, releases);
348
+ catalogueIndexByReleases.set(releases, catalogueIndex);
277
349
  }
278
350
  return catalogueIndex;
279
351
  };
280
- const getPitchCycleOfCard = (index, card) => index.getPitchCycle(card.cardIdentifier);
281
352
  const getCardsByName = (index, name) => index.getCardsByName(name);
282
- const getCardsWithPitchSiblings = (index, cards) => {
283
- const cardByCardIdentifier = /* @__PURE__ */ new Map();
284
- for (const card of cards) {
285
- for (const pitch of getPitchCycleOfCard(index, card)) {
286
- cardByCardIdentifier.set(pitch.cardIdentifier, pitch);
287
- }
288
- }
289
- return index.getCardsInCorpusOrder([...cardByCardIdentifier.values()]);
290
- };
291
- const getCardsReferencing = (index, card) => {
292
- const referencingCards = [];
293
- for (const pitch of getPitchCycleOfCard(index, card)) {
294
- referencingCards.push(...index.getReferencedBy(pitch.cardIdentifier));
295
- }
296
- return getCardsWithPitchSiblings(index, referencingCards);
297
- };
298
- const getCardsReferencedBy = (index, card) => {
299
- const referencedCards = [];
300
- for (const pitch of getPitchCycleOfCard(index, card)) {
301
- referencedCards.push(...index.getReferences(pitch.cardIdentifier));
302
- }
303
- return getCardsWithPitchSiblings(index, referencedCards);
304
- };
305
353
  export {
306
354
  getCardsByName,
307
- getCardsReferencedBy,
308
- getCardsReferencing,
309
355
  getCatalogueIndex
310
356
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@flesh-and-blood/search",
3
3
  "description": "TypeScript search engine for Flesh and Blood cards",
4
- "version": "5.3.1",
4
+ "version": "6.0.0",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "main": "dist/index.cjs",
@@ -13,10 +13,6 @@
13
13
  "import": "./dist/index.js",
14
14
  "require": "./dist/index.cjs"
15
15
  },
16
- "./abbreviations": {
17
- "types": "./dist/abbreviations.d.ts",
18
- "import": "./dist/abbreviations.js"
19
- },
20
16
  "./shorthands": {
21
17
  "types": "./dist/shorthands.d.ts",
22
18
  "import": "./dist/shorthands.js"
@@ -47,8 +43,8 @@
47
43
  "@flesh-and-blood/types": "^5.0.0"
48
44
  },
49
45
  "devDependencies": {
50
- "@flesh-and-blood/cards": "^5.3.1",
51
- "@flesh-and-blood/types": "^5.3.0",
46
+ "@flesh-and-blood/cards": "^6.0.0",
47
+ "@flesh-and-blood/types": "^6.0.0",
52
48
  "@types/node": "^26.6.3",
53
49
  "esbuild": "^0.28.2",
54
50
  "typescript": "^7.0.2",
@@ -75,5 +71,5 @@
75
71
  "FAB",
76
72
  "FABTCG"
77
73
  ],
78
- "gitHead": "43349d8a88ac6e277f32c20b5cf36f373efb45e5"
74
+ "gitHead": "3d19edf0d4b060755686cb871a9283f8bdfcc438"
79
75
  }