@flesh-and-blood/search 5.3.0 → 5.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/filterMappings.d.ts +29 -9
- package/dist/filterMappings.js +18 -8
- package/dist/filterResolvers.js +49 -77
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/metaFilters.js +23 -38
- package/dist/queryParse.js +8 -23
- package/dist/search.d.ts +13 -0
- package/dist/search.js +66 -22
- package/dist/searchIndex.d.ts +13 -5
- package/dist/searchIndex.js +78 -27
- package/package.json +3 -3
- package/dist/abbreviations.d.ts +0 -9
- package/dist/abbreviations.js +0 -385
package/dist/queryParse.js
CHANGED
|
@@ -2,7 +2,6 @@ import {
|
|
|
2
2
|
Release,
|
|
3
3
|
setToSetIdentifierMappings
|
|
4
4
|
} from "@flesh-and-blood/types";
|
|
5
|
-
import { getAbbreviation } from "./abbreviations.js";
|
|
6
5
|
import { PUNCTUATION } from "./constants.js";
|
|
7
6
|
import {
|
|
8
7
|
aliasesByFilterCategory,
|
|
@@ -55,7 +54,7 @@ const setNameInSetFilterPattern = new RegExp(
|
|
|
55
54
|
)}):(?:[^\\s]*[,+])?"?)(${setNamesLongestFirst})(?="?(?:[,+]|\\s|$))`,
|
|
56
55
|
"g"
|
|
57
56
|
);
|
|
58
|
-
const
|
|
57
|
+
const getPreparedText = (text, index) => {
|
|
59
58
|
let preparedText = text.trim().toLowerCase();
|
|
60
59
|
for (const smartQuote of SMART_DOUBLE_QUOTES) {
|
|
61
60
|
preparedText = preparedText.replaceAll(smartQuote, '"');
|
|
@@ -85,12 +84,7 @@ const getPreparedQuery = (text, index) => {
|
|
|
85
84
|
preparedText = preparedText.replace(punctuatedName, override);
|
|
86
85
|
}
|
|
87
86
|
}
|
|
88
|
-
return
|
|
89
|
-
// A query that is nothing but a card's abbreviation names that card whole,
|
|
90
|
-
// so its own spaces and commas are not separators.
|
|
91
|
-
isWholeQueryAbbreviation: !!getAbbreviation(preparedText)?.card,
|
|
92
|
-
text: preparedText
|
|
93
|
-
};
|
|
87
|
+
return preparedText;
|
|
94
88
|
};
|
|
95
89
|
const getExpandedTokens = (token) => {
|
|
96
90
|
const matchingShorthand = singleWordShorthands.find(
|
|
@@ -102,13 +96,9 @@ const getExpandedTokens = (token) => {
|
|
|
102
96
|
tokens: isExpanded ? matchingShorthand.expanded : [token]
|
|
103
97
|
};
|
|
104
98
|
};
|
|
105
|
-
const getQueryTermSpans = ({
|
|
106
|
-
isWholeQueryAbbreviation,
|
|
107
|
-
text
|
|
108
|
-
}) => {
|
|
99
|
+
const getQueryTermSpans = (text) => {
|
|
109
100
|
const termSpans = [];
|
|
110
|
-
const
|
|
111
|
-
for (const { end, start, token } of tokenSpans) {
|
|
101
|
+
for (const { end, start, token } of getQueryTokenSpans(text)) {
|
|
112
102
|
const { isExpanded, tokens } = getExpandedTokens(token);
|
|
113
103
|
for (const expandedToken of tokens) {
|
|
114
104
|
termSpans.push({ end, isExpanded, start, token: expandedToken });
|
|
@@ -146,7 +136,7 @@ const getParsedQuery = (text, index, {
|
|
|
146
136
|
additionalSets = [],
|
|
147
137
|
today = getTodayAsReleaseDate()
|
|
148
138
|
} = {}) => {
|
|
149
|
-
const
|
|
139
|
+
const preparedText = getPreparedText(text, index);
|
|
150
140
|
const context = {
|
|
151
141
|
additionalHeroes,
|
|
152
142
|
additionalSets,
|
|
@@ -166,7 +156,7 @@ const getParsedQuery = (text, index, {
|
|
|
166
156
|
const keywords = [];
|
|
167
157
|
const nodes = [];
|
|
168
158
|
const unresolvedFilters = [];
|
|
169
|
-
for (const termSpan of getQueryTermSpans(
|
|
159
|
+
for (const termSpan of getQueryTermSpans(preparedText)) {
|
|
170
160
|
const filterToken = getQueryFilterToken(termSpan.token) || getIncompleteFilterToken(termSpan.token);
|
|
171
161
|
if (filterToken) {
|
|
172
162
|
const { isAndList, isExcluded, key, valueText } = filterToken;
|
|
@@ -225,13 +215,8 @@ const getParsedQuery = (text, index, {
|
|
|
225
215
|
const { end, start, token } = termSpan;
|
|
226
216
|
nodes.push({ end, isFilter: false, start, token });
|
|
227
217
|
const freeText = getUnquotedValue(termSpan.token);
|
|
228
|
-
const abbreviatedCard = getAbbreviation(freeText)?.card;
|
|
229
218
|
const excludedMetaFilters = getExcludedMetaFilters(freeText);
|
|
230
|
-
if (
|
|
231
|
-
keywords.push(
|
|
232
|
-
`"${abbreviatedCard.toLowerCase().replace(PUNCTUATION, "")}"`
|
|
233
|
-
);
|
|
234
|
-
} else if (excludedMetaFilters.length > 0) {
|
|
219
|
+
if (excludedMetaFilters.length > 0) {
|
|
235
220
|
appliedFilters.push(...excludedMetaFilters);
|
|
236
221
|
} else if (freeText) {
|
|
237
222
|
keywords.push(freeText.replace(PUNCTUATION, ""));
|
|
@@ -243,7 +228,7 @@ const getParsedQuery = (text, index, {
|
|
|
243
228
|
attributes,
|
|
244
229
|
keywords,
|
|
245
230
|
nodes,
|
|
246
|
-
text:
|
|
231
|
+
text: preparedText,
|
|
247
232
|
unresolvedFilters
|
|
248
233
|
};
|
|
249
234
|
};
|
package/dist/search.d.ts
CHANGED
|
@@ -18,7 +18,14 @@ export interface SearchOptions {
|
|
|
18
18
|
*/
|
|
19
19
|
index?: CatalogueIndex;
|
|
20
20
|
}
|
|
21
|
+
/** How the free text named cards other than by their names. */
|
|
22
|
+
export interface SearchAlias {
|
|
23
|
+
kind: "nickname" | "initials";
|
|
24
|
+
text: string;
|
|
25
|
+
}
|
|
21
26
|
export interface SearchResults {
|
|
27
|
+
/** Set when the free text was a nickname or the initials of the cards found. */
|
|
28
|
+
alias?: SearchAlias;
|
|
22
29
|
appliedFilters: AppliedFilter[];
|
|
23
30
|
keywords: string[];
|
|
24
31
|
attributes: QueryAttributes;
|
|
@@ -35,9 +42,15 @@ declare class Search {
|
|
|
35
42
|
private cards;
|
|
36
43
|
private fuse;
|
|
37
44
|
private index;
|
|
45
|
+
private poolCardByCardIdentifier;
|
|
38
46
|
constructor(cards: DoubleSidedCard[], options?: SearchOptions);
|
|
39
47
|
constructor(cards: DoubleSidedCard[], additionalHeroes?: Hero[], additionalSets?: Release[]);
|
|
40
48
|
private getFuse;
|
|
49
|
+
/**
|
|
50
|
+
* The pool's own copies of index cards, dropping any the pool lacks, so a pool
|
|
51
|
+
* searched out of a larger catalogue returns its cards alone.
|
|
52
|
+
*/
|
|
53
|
+
private getPoolCards;
|
|
41
54
|
search: (text: string, includeMemes?: boolean) => SearchResults;
|
|
42
55
|
}
|
|
43
56
|
export default Search;
|
package/dist/search.js
CHANGED
|
@@ -11,7 +11,11 @@ import {
|
|
|
11
11
|
getParsedQuery
|
|
12
12
|
} from "./queryParse.js";
|
|
13
13
|
import { memes } from "./memes.js";
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
getCleanText,
|
|
16
|
+
getNormalizedText,
|
|
17
|
+
getTextWithoutMarkup
|
|
18
|
+
} from "./helpers.js";
|
|
15
19
|
import { FilterProperty } from "./metaFilters.js";
|
|
16
20
|
import { getCatalogueIndex } from "./searchIndex.js";
|
|
17
21
|
const searchOptions = {
|
|
@@ -52,27 +56,78 @@ class Search {
|
|
|
52
56
|
}
|
|
53
57
|
return this.fuse;
|
|
54
58
|
};
|
|
59
|
+
/**
|
|
60
|
+
* The pool's own copies of index cards, dropping any the pool lacks, so a pool
|
|
61
|
+
* searched out of a larger catalogue returns its cards alone.
|
|
62
|
+
*/
|
|
63
|
+
this.getPoolCards = (indexCards) => {
|
|
64
|
+
if (!this.poolCardByCardIdentifier) {
|
|
65
|
+
this.poolCardByCardIdentifier = new Map(
|
|
66
|
+
this.cards.map((card) => [card.cardIdentifier, card])
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
const poolCards = [];
|
|
70
|
+
for (const { cardIdentifier } of indexCards) {
|
|
71
|
+
const poolCard = this.poolCardByCardIdentifier.get(cardIdentifier);
|
|
72
|
+
if (poolCard) {
|
|
73
|
+
poolCards.push(poolCard);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return poolCards;
|
|
77
|
+
};
|
|
55
78
|
this.search = (text, includeMemes) => {
|
|
56
79
|
let results;
|
|
80
|
+
let alias;
|
|
57
81
|
const { appliedFilters, attributes, keywords, unresolvedFilters } = getParsedQuery(text, this.index, {
|
|
58
82
|
additionalHeroes: this.additionalHeroes,
|
|
59
83
|
additionalSets: this.additionalSets
|
|
60
84
|
});
|
|
61
85
|
const keyword = keywords.join(" ");
|
|
62
86
|
const matchingMemes = includeMemes ? memes.filter((meme) => meme.keyword === keyword) : [];
|
|
87
|
+
const getFilteredCards = (cardsToFilter) => appliedFilters.length > 0 ? cardsToFilter.filter(
|
|
88
|
+
(card) => card && filterCard(card, appliedFilters)
|
|
89
|
+
) : cardsToFilter;
|
|
63
90
|
if (matchingMemes.length > 0) {
|
|
64
|
-
results = matchingMemes.map(({ card }) => card);
|
|
91
|
+
results = getFilteredCards(matchingMemes.map(({ card }) => card));
|
|
65
92
|
} else if (keywords.length) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
(
|
|
93
|
+
const freeText = getCleanText(keyword);
|
|
94
|
+
const nicknamedCards = this.getPoolCards(
|
|
95
|
+
this.index.getCardsByNickname(freeText)
|
|
96
|
+
);
|
|
97
|
+
const namedCardByCardIdentifier = /* @__PURE__ */ new Map();
|
|
98
|
+
for (const card of [
|
|
99
|
+
...this.getPoolCards(this.index.getCardsByExactName(freeText)),
|
|
100
|
+
...nicknamedCards
|
|
101
|
+
]) {
|
|
102
|
+
namedCardByCardIdentifier.set(card.cardIdentifier, card);
|
|
103
|
+
}
|
|
104
|
+
const textMatches = this.getFuse().search(keyword).map((result) => result.item).filter(
|
|
105
|
+
({ cardIdentifier }) => !namedCardByCardIdentifier.has(cardIdentifier)
|
|
73
106
|
);
|
|
107
|
+
results = getFilteredCards([
|
|
108
|
+
...namedCardByCardIdentifier.values(),
|
|
109
|
+
...textMatches
|
|
110
|
+
]);
|
|
111
|
+
const hasNicknamedResult = results.some(
|
|
112
|
+
(card) => nicknamedCards.includes(card)
|
|
113
|
+
);
|
|
114
|
+
if (hasNicknamedResult) {
|
|
115
|
+
alias = { kind: "nickname", text: freeText };
|
|
116
|
+
}
|
|
117
|
+
const canFallBackToInitials = results.length === 0 && keywords.length === 1;
|
|
118
|
+
if (canFallBackToInitials) {
|
|
119
|
+
results = getFilteredCards(
|
|
120
|
+
this.getPoolCards(this.index.getCardsByInitials(freeText))
|
|
121
|
+
);
|
|
122
|
+
if (results.length > 0) {
|
|
123
|
+
alias = { kind: "initials", text: freeText };
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
} else {
|
|
127
|
+
results = getFilteredCards([...this.cards]);
|
|
74
128
|
}
|
|
75
|
-
|
|
129
|
+
const isRankedByText = keywords.length > 0 && alias?.kind !== "initials";
|
|
130
|
+
if (!isRankedByText) {
|
|
76
131
|
let setIdentifierToSortBy = "";
|
|
77
132
|
const shouldSortByRelease = attributes.releases.length === 1;
|
|
78
133
|
if (shouldSortByRelease) {
|
|
@@ -101,18 +156,6 @@ class Search {
|
|
|
101
156
|
(c1, c2) => c1.name === c2.name ? `${c1.pitch}`.localeCompare(`${c2.pitch}`) : c1.name.localeCompare(c2.name)
|
|
102
157
|
);
|
|
103
158
|
}
|
|
104
|
-
} else {
|
|
105
|
-
const nameMatches = [];
|
|
106
|
-
const nonMatches = [];
|
|
107
|
-
const potentialCardName = keywords.map((keyword2) => keyword2.toLowerCase().replace(PUNCTUATION, "")).join(" ");
|
|
108
|
-
for (const card of results) {
|
|
109
|
-
if (card.name.toLowerCase().replace(PUNCTUATION, "") === potentialCardName) {
|
|
110
|
-
nameMatches.push(card);
|
|
111
|
-
} else {
|
|
112
|
-
nonMatches.push(card);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
results = [...nameMatches, ...nonMatches];
|
|
116
159
|
}
|
|
117
160
|
let searchResultsWithMatchingPrinting = [];
|
|
118
161
|
const {
|
|
@@ -155,6 +198,7 @@ class Search {
|
|
|
155
198
|
}
|
|
156
199
|
const searchResults = searchResultsWithMatchingPrinting.length > 0 ? searchResultsWithMatchingPrinting : results;
|
|
157
200
|
return {
|
|
201
|
+
alias,
|
|
158
202
|
appliedFilters,
|
|
159
203
|
attributes,
|
|
160
204
|
keywords,
|
package/dist/searchIndex.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CardRole, DoubleSidedCard } from "@flesh-and-blood/types";
|
|
2
2
|
/**
|
|
3
3
|
* Everything a corpus can be asked about its cards: lookups, the relations the
|
|
4
4
|
* cards carry, and what each card is for. Every relation is identifier-level,
|
|
@@ -26,6 +26,18 @@ export interface CatalogueIndex<CardType extends DoubleSidedCard = DoubleSidedCa
|
|
|
26
26
|
* a fragment of a name the corpus carries finds nothing.
|
|
27
27
|
*/
|
|
28
28
|
getCardsByExactName: (name: string) => readonly CardType[];
|
|
29
|
+
/** Every card carrying the nickname, matched whole, hyphens ignored. */
|
|
30
|
+
getCardsByNickname: (nickname: string) => readonly CardType[];
|
|
31
|
+
/**
|
|
32
|
+
* Every card carrying the type, subtype or trait, matched whole, hyphens
|
|
33
|
+
* ignored.
|
|
34
|
+
*/
|
|
35
|
+
getCardsByGroup: (group: string) => readonly CardType[];
|
|
36
|
+
/**
|
|
37
|
+
* Every card whose name has the initials, in corpus order, counting a
|
|
38
|
+
* hyphenated word both as one word and as the words the hyphens join.
|
|
39
|
+
*/
|
|
40
|
+
getCardsByInitials: (initials: string) => readonly CardType[];
|
|
29
41
|
/**
|
|
30
42
|
* Every artist the corpus credits, each once, ordered by the `en` locale
|
|
31
43
|
* ignoring case and diacritics so a browser and a server agree on the list.
|
|
@@ -65,7 +77,3 @@ export interface CatalogueIndex<CardType extends DoubleSidedCard = DoubleSidedCa
|
|
|
65
77
|
export declare const getCatalogueIndex: <CardType extends DoubleSidedCard = DoubleSidedCard>(cards: readonly CardType[]) => CatalogueIndex<CardType>;
|
|
66
78
|
/** {@link CatalogueIndex.getCardsByName}, as a free function over an index. */
|
|
67
79
|
export declare const getCardsByName: (index: CatalogueIndex, name: string) => readonly DoubleSidedCard[];
|
|
68
|
-
/** The cards naming the card, at every pitch of both. */
|
|
69
|
-
export declare const getCardsReferencing: (index: CatalogueIndex, card: Card) => DoubleSidedCard[];
|
|
70
|
-
/** The cards the card names, at every pitch of both. */
|
|
71
|
-
export declare const getCardsReferencedBy: (index: CatalogueIndex, card: Card) => DoubleSidedCard[];
|
package/dist/searchIndex.js
CHANGED
|
@@ -3,7 +3,37 @@ import {
|
|
|
3
3
|
getCardRole,
|
|
4
4
|
Type
|
|
5
5
|
} from "@flesh-and-blood/types";
|
|
6
|
-
import { getCleanText } from "./helpers.js";
|
|
6
|
+
import { getCleanText, getNormalizedText } from "./helpers.js";
|
|
7
|
+
const MINIMUM_INITIALS_LENGTH = 3;
|
|
8
|
+
const getInitialsOfName = (name) => {
|
|
9
|
+
const letters = getNormalizedText(name.toLowerCase()).replace(
|
|
10
|
+
/[^a-z\s-]/g,
|
|
11
|
+
""
|
|
12
|
+
);
|
|
13
|
+
const initialsOfName = /* @__PURE__ */ new Set();
|
|
14
|
+
for (const wordBreak of [/[\s-]+/, /\s+/]) {
|
|
15
|
+
let initials = "";
|
|
16
|
+
for (const word of letters.split(wordBreak)) {
|
|
17
|
+
const wordLetters = word.replaceAll("-", "");
|
|
18
|
+
if (wordLetters) {
|
|
19
|
+
initials += wordLetters[0];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
if (initials.length >= MINIMUM_INITIALS_LENGTH) {
|
|
23
|
+
initialsOfName.add(initials);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return [...initialsOfName];
|
|
27
|
+
};
|
|
28
|
+
const getHyphenFreeKey = (text) => getCleanText(text).replaceAll("-", "");
|
|
29
|
+
const addToCardList = (cardsByKey, key, card) => {
|
|
30
|
+
const cardsForKey = cardsByKey.get(key);
|
|
31
|
+
if (cardsForKey) {
|
|
32
|
+
cardsForKey.push(card);
|
|
33
|
+
} else {
|
|
34
|
+
cardsByKey.set(key, [card]);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
7
37
|
const catalogueIndexByCards = /* @__PURE__ */ new WeakMap();
|
|
8
38
|
const noCards = Object.freeze([]);
|
|
9
39
|
const strayCorpusPosition = Number.MAX_SAFE_INTEGER;
|
|
@@ -44,6 +74,9 @@ const getNewCatalogueIndex = (cards) => {
|
|
|
44
74
|
let creatingCardsByCardIdentifier;
|
|
45
75
|
let cardsByRole;
|
|
46
76
|
let artists;
|
|
77
|
+
let cardsByNicknameKey;
|
|
78
|
+
let cardsByGroup;
|
|
79
|
+
let cardsByInitials;
|
|
47
80
|
const getCardLookups = () => {
|
|
48
81
|
if (!cardLookups) {
|
|
49
82
|
const cardByCardIdentifier = /* @__PURE__ */ new Map();
|
|
@@ -132,6 +165,47 @@ const getNewCatalogueIndex = (cards) => {
|
|
|
132
165
|
const { pitchCycleByCleanedName } = getCardLookups();
|
|
133
166
|
return pitchCycleByCleanedName.get(getCleanText(name)) ?? noCards;
|
|
134
167
|
};
|
|
168
|
+
const getCardsByNickname = (nickname) => {
|
|
169
|
+
if (!cardsByNicknameKey) {
|
|
170
|
+
cardsByNicknameKey = /* @__PURE__ */ new Map();
|
|
171
|
+
for (const card of cards) {
|
|
172
|
+
for (const cardNickname of card.nicknames ?? []) {
|
|
173
|
+
addToCardList(
|
|
174
|
+
cardsByNicknameKey,
|
|
175
|
+
getHyphenFreeKey(cardNickname),
|
|
176
|
+
card
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return cardsByNicknameKey.get(getHyphenFreeKey(nickname)) ?? noCards;
|
|
182
|
+
};
|
|
183
|
+
const getCardsByGroup = (group) => {
|
|
184
|
+
if (!cardsByGroup) {
|
|
185
|
+
cardsByGroup = /* @__PURE__ */ new Map();
|
|
186
|
+
for (const card of cards) {
|
|
187
|
+
for (const cardGroup of [
|
|
188
|
+
...card.types,
|
|
189
|
+
...card.subtypes,
|
|
190
|
+
...card.traits ?? []
|
|
191
|
+
]) {
|
|
192
|
+
addToCardList(cardsByGroup, getHyphenFreeKey(cardGroup), card);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return cardsByGroup.get(getHyphenFreeKey(group)) ?? noCards;
|
|
197
|
+
};
|
|
198
|
+
const getCardsByInitials = (initials) => {
|
|
199
|
+
if (!cardsByInitials) {
|
|
200
|
+
cardsByInitials = /* @__PURE__ */ new Map();
|
|
201
|
+
for (const card of cards) {
|
|
202
|
+
for (const initialsOfName of getInitialsOfName(card.name)) {
|
|
203
|
+
addToCardList(cardsByInitials, initialsOfName, card);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return cardsByInitials.get(initials) ?? noCards;
|
|
208
|
+
};
|
|
135
209
|
const getArtists = () => {
|
|
136
210
|
if (!artists) {
|
|
137
211
|
const creditedArtists = /* @__PURE__ */ new Set();
|
|
@@ -202,6 +276,9 @@ const getNewCatalogueIndex = (cards) => {
|
|
|
202
276
|
getPitchCycle,
|
|
203
277
|
getCardsByName: getCardsByName2,
|
|
204
278
|
getCardsByExactName,
|
|
279
|
+
getCardsByNickname,
|
|
280
|
+
getCardsByGroup,
|
|
281
|
+
getCardsByInitials,
|
|
205
282
|
getArtists,
|
|
206
283
|
getOppositeSide,
|
|
207
284
|
getReferences,
|
|
@@ -221,34 +298,8 @@ const getCatalogueIndex = (cards) => {
|
|
|
221
298
|
}
|
|
222
299
|
return catalogueIndex;
|
|
223
300
|
};
|
|
224
|
-
const getPitchCycleOfCard = (index, card) => index.getPitchCycle(card.cardIdentifier);
|
|
225
301
|
const getCardsByName = (index, name) => index.getCardsByName(name);
|
|
226
|
-
const getCardsWithPitchSiblings = (index, cards) => {
|
|
227
|
-
const cardByCardIdentifier = /* @__PURE__ */ new Map();
|
|
228
|
-
for (const card of cards) {
|
|
229
|
-
for (const pitch of getPitchCycleOfCard(index, card)) {
|
|
230
|
-
cardByCardIdentifier.set(pitch.cardIdentifier, pitch);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
return index.getCardsInCorpusOrder([...cardByCardIdentifier.values()]);
|
|
234
|
-
};
|
|
235
|
-
const getCardsReferencing = (index, card) => {
|
|
236
|
-
const referencingCards = [];
|
|
237
|
-
for (const pitch of getPitchCycleOfCard(index, card)) {
|
|
238
|
-
referencingCards.push(...index.getReferencedBy(pitch.cardIdentifier));
|
|
239
|
-
}
|
|
240
|
-
return getCardsWithPitchSiblings(index, referencingCards);
|
|
241
|
-
};
|
|
242
|
-
const getCardsReferencedBy = (index, card) => {
|
|
243
|
-
const referencedCards = [];
|
|
244
|
-
for (const pitch of getPitchCycleOfCard(index, card)) {
|
|
245
|
-
referencedCards.push(...index.getReferences(pitch.cardIdentifier));
|
|
246
|
-
}
|
|
247
|
-
return getCardsWithPitchSiblings(index, referencedCards);
|
|
248
|
-
};
|
|
249
302
|
export {
|
|
250
303
|
getCardsByName,
|
|
251
|
-
getCardsReferencedBy,
|
|
252
|
-
getCardsReferencing,
|
|
253
304
|
getCatalogueIndex
|
|
254
305
|
};
|
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.
|
|
4
|
+
"version": "5.4.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"main": "dist/index.cjs",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"@flesh-and-blood/types": "^5.0.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@flesh-and-blood/cards": "^5.
|
|
50
|
+
"@flesh-and-blood/cards": "^5.4.0",
|
|
51
51
|
"@flesh-and-blood/types": "^5.3.0",
|
|
52
52
|
"@types/node": "^26.6.3",
|
|
53
53
|
"esbuild": "^0.28.2",
|
|
@@ -75,5 +75,5 @@
|
|
|
75
75
|
"FAB",
|
|
76
76
|
"FABTCG"
|
|
77
77
|
],
|
|
78
|
-
"gitHead": "
|
|
78
|
+
"gitHead": "b9859b97493dfa6b6d0990be6b19341ec54a315e"
|
|
79
79
|
}
|
package/dist/abbreviations.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { Card } from "@flesh-and-blood/types";
|
|
2
|
-
export interface Abbreviation {
|
|
3
|
-
abbreviations: string[];
|
|
4
|
-
card: string;
|
|
5
|
-
isHidden?: boolean;
|
|
6
|
-
}
|
|
7
|
-
export declare const getAbbreviation: (abbreviation: string) => Abbreviation | undefined;
|
|
8
|
-
export declare const getAbbreviationByCard: (c: Card) => Abbreviation | undefined;
|
|
9
|
-
export declare const abbreviations: Abbreviation[];
|