cry-search 1.0.3 → 1.0.5
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/CLAUDE.md +22 -4
- package/README.md +26 -4
- package/dist/index.cjs +16 -5
- package/dist/index.js +16 -5
- package/dist/string.cjs +13 -5
- package/dist/string.js +13 -5
- package/dist/types/index.d.ts +1 -1
- package/dist/utils/matchTokenNumeric.d.ts.map +1 -1
- package/dist/utils/preprocessString.d.ts +10 -3
- package/dist/utils/preprocessString.d.ts.map +1 -1
- package/package.json +1 -1
package/CLAUDE.md
CHANGED
|
@@ -62,8 +62,22 @@ The numeric implementation uses a global token registry (`src/utils/tokenRegistr
|
|
|
62
62
|
4. eg "abc 0.3x" -> "abc .3x"
|
|
63
63
|
5. eg "007" -> "7"
|
|
64
64
|
6. multiple periods stay as-is: "1.2.3" -> "1.2.3"
|
|
65
|
+
1b. strip decimal period from pure standalone numbers (digits on both sides of period)
|
|
66
|
+
1. eg "abc 11.22 x" -> "abc 1122 x"
|
|
67
|
+
2. eg "abc 12,3 x" -> "abc 123 x" (after comma->period, then strip)
|
|
68
|
+
3. mixed tokens with letters are NOT stripped: ".5kg" -> ".5kg", "12.3x" -> "12.3x"
|
|
69
|
+
4. standalone decimals without leading digits are NOT stripped: ".3" -> ".3"
|
|
70
|
+
5. multiple periods are NOT stripped: "1.2.3" -> "1.2.3"
|
|
65
71
|
2. we remove spaces in pattern digits - digits
|
|
66
72
|
1. eg. "12 - 25" => "12-25"
|
|
73
|
+
2b. we split tokens at letter-dash-digit, digit-dash-letter and letter-dash-letter boundaries
|
|
74
|
+
1. eg "ABC-123" -> "ABC 123"
|
|
75
|
+
2. eg "123-ABC" -> "123 ABC"
|
|
76
|
+
3. eg "ABC-00123" -> "ABC 123" (after leading zero removal)
|
|
77
|
+
4. eg "COVID-19" -> "COVID 19"
|
|
78
|
+
5. eg "Ioana-Gabriela" -> "Ioana Gabriela"
|
|
79
|
+
6. eg "Ioana-Maria-Sara" -> "Ioana Maria Sara" (chains split in one pass)
|
|
80
|
+
7. digit-dash-digit stays as-is: "12-25" -> "12-25"
|
|
67
81
|
3. we insert spaces between starting letters and digits (only at letter-to-digit boundaries)
|
|
68
82
|
1. eg "SI123" -> "SI 123"
|
|
69
83
|
2. eg "123SI" -> "123 SI"
|
|
@@ -79,9 +93,10 @@ The numeric implementation uses a global token registry (`src/utils/tokenRegistr
|
|
|
79
93
|
3. matching
|
|
80
94
|
1. we match words in any order
|
|
81
95
|
2. number matching depends on TARGET token length (not query length):
|
|
82
|
-
1. short numbers (≤6 digits in target):
|
|
96
|
+
1. short numbers (≤6 digits in target): start match (left-match)
|
|
97
|
+
- eg. query "12" vs target "1234" → match (starts with "12")
|
|
83
98
|
- eg. query "123" vs target "123" → match
|
|
84
|
-
- eg. query "
|
|
99
|
+
- eg. query "34" vs target "1234" → no match (not at start)
|
|
85
100
|
2. long numbers (>6 digits in target): startEnd match
|
|
86
101
|
- eg. query "60731" vs target "3838989760731" → match (13-digit barcode)
|
|
87
102
|
- eg. query "989" vs target "3838989760731" → no match (not at start/end)
|
|
@@ -180,7 +195,7 @@ The numeric implementation uses a global token registry (`src/utils/tokenRegistr
|
|
|
180
195
|
11. SearchOpts:
|
|
181
196
|
1. matchWords?: MatchMode (default: 'start') - how to match words
|
|
182
197
|
2. matchNumbers?: MatchMode (default: 'startEnd') - how to match long numbers (>threshold digits)
|
|
183
|
-
3. matchNumbersShort?: MatchMode (default: '
|
|
198
|
+
3. matchNumbersShort?: MatchMode (default: 'start') - how to match short numbers (≤threshold digits)
|
|
184
199
|
4. matchNumbersThreshold?: number (default: 6) - digit count threshold for short vs long
|
|
185
200
|
12. LinkedSearchResultWithMeta<TPrimary, TLinked>:
|
|
186
201
|
1. queryTokens: string[] - tokenized query
|
|
@@ -203,7 +218,7 @@ Override match behavior per token at search time. Priority: query prefix > field
|
|
|
203
218
|
| `--word` | negation | Exclude (works for words and numbers) | `--123` excludes items with "123" |
|
|
204
219
|
| `~word` | negation | Exclude (works for words and numbers) | `~iphone` or `~123` |
|
|
205
220
|
|
|
206
|
-
**Note:** `-5` is NOT negation
|
|
221
|
+
**Note:** `-5` is NOT negation — the leading dash is stripped, so `-5` searches for `5`. Use `--5` or `~5` to negate numbers.
|
|
207
222
|
|
|
208
223
|
### Programmatic prefixes
|
|
209
224
|
| Prefix | Mode |
|
|
@@ -223,6 +238,9 @@ Override match behavior per token at search time. Priority: query prefix > field
|
|
|
223
238
|
6. `"..nik"` → finds tokens ending with "nik" (usenik, krajnik)
|
|
224
239
|
7. `"60731"` → finds barcode "3838989760731" (13-digit target uses startEnd)
|
|
225
240
|
8. `"=9001"` → finds exact "9001" but NOT "035585249001" or "9001917"
|
|
241
|
+
9. `"12"` → finds "1234" (short number, start match by default)
|
|
242
|
+
10. `"-123"` → finds invoice "ABC-00123" (dash stripped → "123", metadata has split token "123")
|
|
243
|
+
11. `"abc 123"` → finds "ABC-00123" (letter-dash-digit split into separate tokens)
|
|
226
244
|
|
|
227
245
|
|
|
228
246
|
## Main Functions (Default = Numeric)
|
package/README.md
CHANGED
|
@@ -323,7 +323,7 @@ Override match behavior per token at search time using prefixes:
|
|
|
323
323
|
| `--word` | negation | Exclude results (works for words and numbers) |
|
|
324
324
|
| `~word` | negation | Exclude results (works for words and numbers) |
|
|
325
325
|
|
|
326
|
-
**Note:** `-5` is NOT negation
|
|
326
|
+
**Note:** `-5` is NOT negation — the leading dash is stripped, so `-5` searches for `5`. Use `--5` or `~5` to negate numbers.
|
|
327
327
|
|
|
328
328
|
**Detecting negation:** Linked search results include a `hasNegation: boolean` flag indicating if the query contained negation tokens.
|
|
329
329
|
|
|
@@ -350,13 +350,35 @@ searchInDataReturnObjects('=9001', metadata, data);
|
|
|
350
350
|
### Number Matching
|
|
351
351
|
|
|
352
352
|
Match mode for numbers is determined by the **target token's length** (not the query):
|
|
353
|
-
- **Short numbers (≤6 digits)**:
|
|
353
|
+
- **Short numbers (≤6 digits)**: start (left) match
|
|
354
354
|
- **Long numbers (>6 digits)**: allow start or end match (for barcodes)
|
|
355
355
|
|
|
356
356
|
```typescript
|
|
357
|
+
// Query "12" against code "1234" (4 digits) → MATCH (starts with 12)
|
|
357
358
|
// Query "60731" against barcode "3838989760731" (13 digits) → MATCH (ends with 60731)
|
|
358
|
-
// Query "
|
|
359
|
-
//
|
|
359
|
+
// Query "34" against code "1234" (4 digits) → NO MATCH (not at start)
|
|
360
|
+
// Use "=12" for exact match on short numbers
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
### Hyphen Splitting
|
|
364
|
+
|
|
365
|
+
Tokens are split at letter-dash-digit, digit-dash-letter and letter-dash-letter boundaries during preprocessing. Digit-dash-digit ranges (e.g., `12-25`) are preserved.
|
|
366
|
+
|
|
367
|
+
```typescript
|
|
368
|
+
// "ABC-00123" → tokens "abc" and "123"
|
|
369
|
+
// "Ioana-Gabriela" → tokens "ioana" and "gabriela"
|
|
370
|
+
// "COVID-19" → tokens "covid" and "19"
|
|
371
|
+
// "12-25" → token "12-25" (range preserved)
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
This enables matching by either part:
|
|
375
|
+
|
|
376
|
+
```typescript
|
|
377
|
+
// Query "123" against "ABC-00123" → MATCH (token "123" exists)
|
|
378
|
+
// Query "-123" against "ABC-00123" → MATCH (leading dash stripped → "123")
|
|
379
|
+
// Query "-0123" against "ABC-00123" → MATCH (leading zeros + dash stripped → "123")
|
|
380
|
+
// Query "abc 123" against "ABC-00123" → MATCH (both tokens match)
|
|
381
|
+
// Query "gabriela" against "Ioana-Gabriela" → MATCH (split into "ioana" and "gabriela")
|
|
360
382
|
```
|
|
361
383
|
|
|
362
384
|
Priority: query prefix > field match mode > global SearchOpts default.
|
package/dist/index.cjs
CHANGED
|
@@ -87,7 +87,7 @@ module.exports = __toCommonJS(exports_src);
|
|
|
87
87
|
var DEFAULT_SEARCH_OPTS = {
|
|
88
88
|
matchWords: "start",
|
|
89
89
|
matchNumbers: "startEnd",
|
|
90
|
-
matchNumbersShort: "
|
|
90
|
+
matchNumbersShort: "start",
|
|
91
91
|
matchNumbersThreshold: 6
|
|
92
92
|
};
|
|
93
93
|
function arrayToSearchableData(items) {
|
|
@@ -199,16 +199,24 @@ var RE_LEADING_ZEROS = /\b0+(\d)/g;
|
|
|
199
199
|
var RE_DECIMAL_COMMA = /(\d),(\d)/g;
|
|
200
200
|
var RE_STANDALONE_COMMA = /(?<!\d),(\d)/g;
|
|
201
201
|
var RE_ZERO_DECIMAL = /\b0+\./g;
|
|
202
|
+
var RE_PURE_DECIMAL = /(?<![a-zčćšžđñ\d.])(\d+)\.(\d+)(?![a-zčćšžđñ.\d])/gi;
|
|
202
203
|
var RE_DIGIT_DASH = /(\d)\s*-\s*(\d)/g;
|
|
203
|
-
var
|
|
204
|
-
var
|
|
204
|
+
var RE_LETTER_DASH_DIGIT = /([a-zčćšžđñ])-(\d)/gi;
|
|
205
|
+
var RE_DIGIT_DASH_LETTER = /(\d)-([a-zčćšžđñ])/gi;
|
|
206
|
+
var RE_LETTER_DASH_LETTER = /(?<=[a-zčćšžđñ])-(?=[a-zčćšžđñ])/gi;
|
|
207
|
+
var RE_LETTERS_DIGITS = /(^|\s)([a-zčćšžđñ]+)(\d+)(?=\s|$)/gi;
|
|
208
|
+
var RE_DIGITS_LETTERS = /(^|\s)(\d+)([a-zčćšžđñ]+)(?=\s|$)/gi;
|
|
205
209
|
function preprocessString(input) {
|
|
206
210
|
let result = input;
|
|
207
211
|
result = result.replace(RE_LEADING_ZEROS, "$1");
|
|
208
212
|
result = result.replace(RE_DECIMAL_COMMA, "$1.$2");
|
|
209
213
|
result = result.replace(RE_STANDALONE_COMMA, ".$1");
|
|
210
214
|
result = result.replace(RE_ZERO_DECIMAL, ".");
|
|
215
|
+
result = result.replace(RE_PURE_DECIMAL, "$1$2");
|
|
211
216
|
result = result.replace(RE_DIGIT_DASH, "$1-$2");
|
|
217
|
+
result = result.replace(RE_LETTER_DASH_DIGIT, "$1 $2");
|
|
218
|
+
result = result.replace(RE_DIGIT_DASH_LETTER, "$1 $2");
|
|
219
|
+
result = result.replace(RE_LETTER_DASH_LETTER, " ");
|
|
212
220
|
result = result.replace(RE_LETTERS_DIGITS, "$1$2 $3");
|
|
213
221
|
result = result.replace(RE_DIGITS_LETTERS, "$1$2 $3");
|
|
214
222
|
return result;
|
|
@@ -265,7 +273,7 @@ function tokenize(input, config) {
|
|
|
265
273
|
const replaced = config.replaceTokens.get(withoutPrefix);
|
|
266
274
|
return replaced ? "--" + replaced : token;
|
|
267
275
|
}
|
|
268
|
-
if (token.length > 1 && token[0] === "-" && /^[a-
|
|
276
|
+
if (token.length > 1 && token[0] === "-" && /^[a-zčćšžđñ]/i.test(token[1])) {
|
|
269
277
|
const withoutPrefix = token.slice(1);
|
|
270
278
|
const replaced = config.replaceTokens.get(withoutPrefix);
|
|
271
279
|
return replaced ? "-" + replaced : token;
|
|
@@ -614,7 +622,7 @@ function prepareQueryTokens(queryTokenStrs) {
|
|
|
614
622
|
if (str.length > 2 && str.startsWith("--")) {
|
|
615
623
|
negated = true;
|
|
616
624
|
cleanStr = str.slice(2);
|
|
617
|
-
} else if (str.length > 1 && str[0] === "-" && /^[a-
|
|
625
|
+
} else if (str.length > 1 && str[0] === "-" && /^[a-zčćšžđñ]/i.test(str[1])) {
|
|
618
626
|
negated = true;
|
|
619
627
|
cleanStr = str.slice(1);
|
|
620
628
|
} else if (str.length > 1 && str.startsWith("~")) {
|
|
@@ -639,6 +647,9 @@ function prepareQueryTokens(queryTokenStrs) {
|
|
|
639
647
|
cleanStr = str.slice(1);
|
|
640
648
|
}
|
|
641
649
|
}
|
|
650
|
+
if (!negated && cleanStr.length > 1 && cleanStr[0] === "-" && /\d/.test(cleanStr[1])) {
|
|
651
|
+
cleanStr = cleanStr.slice(1);
|
|
652
|
+
}
|
|
642
653
|
const result = {
|
|
643
654
|
str: cleanStr,
|
|
644
655
|
id: findTokenId(cleanStr),
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
var DEFAULT_SEARCH_OPTS = {
|
|
3
3
|
matchWords: "start",
|
|
4
4
|
matchNumbers: "startEnd",
|
|
5
|
-
matchNumbersShort: "
|
|
5
|
+
matchNumbersShort: "start",
|
|
6
6
|
matchNumbersThreshold: 6
|
|
7
7
|
};
|
|
8
8
|
function arrayToSearchableData(items) {
|
|
@@ -114,16 +114,24 @@ var RE_LEADING_ZEROS = /\b0+(\d)/g;
|
|
|
114
114
|
var RE_DECIMAL_COMMA = /(\d),(\d)/g;
|
|
115
115
|
var RE_STANDALONE_COMMA = /(?<!\d),(\d)/g;
|
|
116
116
|
var RE_ZERO_DECIMAL = /\b0+\./g;
|
|
117
|
+
var RE_PURE_DECIMAL = /(?<![a-zčćšžđñ\d.])(\d+)\.(\d+)(?![a-zčćšžđñ.\d])/gi;
|
|
117
118
|
var RE_DIGIT_DASH = /(\d)\s*-\s*(\d)/g;
|
|
118
|
-
var
|
|
119
|
-
var
|
|
119
|
+
var RE_LETTER_DASH_DIGIT = /([a-zčćšžđñ])-(\d)/gi;
|
|
120
|
+
var RE_DIGIT_DASH_LETTER = /(\d)-([a-zčćšžđñ])/gi;
|
|
121
|
+
var RE_LETTER_DASH_LETTER = /(?<=[a-zčćšžđñ])-(?=[a-zčćšžđñ])/gi;
|
|
122
|
+
var RE_LETTERS_DIGITS = /(^|\s)([a-zčćšžđñ]+)(\d+)(?=\s|$)/gi;
|
|
123
|
+
var RE_DIGITS_LETTERS = /(^|\s)(\d+)([a-zčćšžđñ]+)(?=\s|$)/gi;
|
|
120
124
|
function preprocessString(input) {
|
|
121
125
|
let result = input;
|
|
122
126
|
result = result.replace(RE_LEADING_ZEROS, "$1");
|
|
123
127
|
result = result.replace(RE_DECIMAL_COMMA, "$1.$2");
|
|
124
128
|
result = result.replace(RE_STANDALONE_COMMA, ".$1");
|
|
125
129
|
result = result.replace(RE_ZERO_DECIMAL, ".");
|
|
130
|
+
result = result.replace(RE_PURE_DECIMAL, "$1$2");
|
|
126
131
|
result = result.replace(RE_DIGIT_DASH, "$1-$2");
|
|
132
|
+
result = result.replace(RE_LETTER_DASH_DIGIT, "$1 $2");
|
|
133
|
+
result = result.replace(RE_DIGIT_DASH_LETTER, "$1 $2");
|
|
134
|
+
result = result.replace(RE_LETTER_DASH_LETTER, " ");
|
|
127
135
|
result = result.replace(RE_LETTERS_DIGITS, "$1$2 $3");
|
|
128
136
|
result = result.replace(RE_DIGITS_LETTERS, "$1$2 $3");
|
|
129
137
|
return result;
|
|
@@ -180,7 +188,7 @@ function tokenize(input, config) {
|
|
|
180
188
|
const replaced = config.replaceTokens.get(withoutPrefix);
|
|
181
189
|
return replaced ? "--" + replaced : token;
|
|
182
190
|
}
|
|
183
|
-
if (token.length > 1 && token[0] === "-" && /^[a-
|
|
191
|
+
if (token.length > 1 && token[0] === "-" && /^[a-zčćšžđñ]/i.test(token[1])) {
|
|
184
192
|
const withoutPrefix = token.slice(1);
|
|
185
193
|
const replaced = config.replaceTokens.get(withoutPrefix);
|
|
186
194
|
return replaced ? "-" + replaced : token;
|
|
@@ -529,7 +537,7 @@ function prepareQueryTokens(queryTokenStrs) {
|
|
|
529
537
|
if (str.length > 2 && str.startsWith("--")) {
|
|
530
538
|
negated = true;
|
|
531
539
|
cleanStr = str.slice(2);
|
|
532
|
-
} else if (str.length > 1 && str[0] === "-" && /^[a-
|
|
540
|
+
} else if (str.length > 1 && str[0] === "-" && /^[a-zčćšžđñ]/i.test(str[1])) {
|
|
533
541
|
negated = true;
|
|
534
542
|
cleanStr = str.slice(1);
|
|
535
543
|
} else if (str.length > 1 && str.startsWith("~")) {
|
|
@@ -554,6 +562,9 @@ function prepareQueryTokens(queryTokenStrs) {
|
|
|
554
562
|
cleanStr = str.slice(1);
|
|
555
563
|
}
|
|
556
564
|
}
|
|
565
|
+
if (!negated && cleanStr.length > 1 && cleanStr[0] === "-" && /\d/.test(cleanStr[1])) {
|
|
566
|
+
cleanStr = cleanStr.slice(1);
|
|
567
|
+
}
|
|
557
568
|
const result = {
|
|
558
569
|
str: cleanStr,
|
|
559
570
|
id: findTokenId(cleanStr),
|
package/dist/string.cjs
CHANGED
|
@@ -167,16 +167,24 @@ var RE_LEADING_ZEROS = /\b0+(\d)/g;
|
|
|
167
167
|
var RE_DECIMAL_COMMA = /(\d),(\d)/g;
|
|
168
168
|
var RE_STANDALONE_COMMA = /(?<!\d),(\d)/g;
|
|
169
169
|
var RE_ZERO_DECIMAL = /\b0+\./g;
|
|
170
|
+
var RE_PURE_DECIMAL = /(?<![a-zčćšžđñ\d.])(\d+)\.(\d+)(?![a-zčćšžđñ.\d])/gi;
|
|
170
171
|
var RE_DIGIT_DASH = /(\d)\s*-\s*(\d)/g;
|
|
171
|
-
var
|
|
172
|
-
var
|
|
172
|
+
var RE_LETTER_DASH_DIGIT = /([a-zčćšžđñ])-(\d)/gi;
|
|
173
|
+
var RE_DIGIT_DASH_LETTER = /(\d)-([a-zčćšžđñ])/gi;
|
|
174
|
+
var RE_LETTER_DASH_LETTER = /(?<=[a-zčćšžđñ])-(?=[a-zčćšžđñ])/gi;
|
|
175
|
+
var RE_LETTERS_DIGITS = /(^|\s)([a-zčćšžđñ]+)(\d+)(?=\s|$)/gi;
|
|
176
|
+
var RE_DIGITS_LETTERS = /(^|\s)(\d+)([a-zčćšžđñ]+)(?=\s|$)/gi;
|
|
173
177
|
function preprocessString(input) {
|
|
174
178
|
let result = input;
|
|
175
179
|
result = result.replace(RE_LEADING_ZEROS, "$1");
|
|
176
180
|
result = result.replace(RE_DECIMAL_COMMA, "$1.$2");
|
|
177
181
|
result = result.replace(RE_STANDALONE_COMMA, ".$1");
|
|
178
182
|
result = result.replace(RE_ZERO_DECIMAL, ".");
|
|
183
|
+
result = result.replace(RE_PURE_DECIMAL, "$1$2");
|
|
179
184
|
result = result.replace(RE_DIGIT_DASH, "$1-$2");
|
|
185
|
+
result = result.replace(RE_LETTER_DASH_DIGIT, "$1 $2");
|
|
186
|
+
result = result.replace(RE_DIGIT_DASH_LETTER, "$1 $2");
|
|
187
|
+
result = result.replace(RE_LETTER_DASH_LETTER, " ");
|
|
180
188
|
result = result.replace(RE_LETTERS_DIGITS, "$1$2 $3");
|
|
181
189
|
result = result.replace(RE_DIGITS_LETTERS, "$1$2 $3");
|
|
182
190
|
return result;
|
|
@@ -233,7 +241,7 @@ function tokenize(input, config) {
|
|
|
233
241
|
const replaced = config.replaceTokens.get(withoutPrefix);
|
|
234
242
|
return replaced ? "--" + replaced : token;
|
|
235
243
|
}
|
|
236
|
-
if (token.length > 1 && token[0] === "-" && /^[a-
|
|
244
|
+
if (token.length > 1 && token[0] === "-" && /^[a-zčćšžđñ]/i.test(token[1])) {
|
|
237
245
|
const withoutPrefix = token.slice(1);
|
|
238
246
|
const replaced = config.replaceTokens.get(withoutPrefix);
|
|
239
247
|
return replaced ? "-" + replaced : token;
|
|
@@ -488,7 +496,7 @@ function removeFromSearchMetadataBatch(metadata, objectIds) {
|
|
|
488
496
|
var DEFAULT_SEARCH_OPTS = {
|
|
489
497
|
matchWords: "start",
|
|
490
498
|
matchNumbers: "startEnd",
|
|
491
|
-
matchNumbersShort: "
|
|
499
|
+
matchNumbersShort: "start",
|
|
492
500
|
matchNumbersThreshold: 6
|
|
493
501
|
};
|
|
494
502
|
function arrayToSearchableData(items) {
|
|
@@ -627,7 +635,7 @@ function findInArray(query, data, metadata, limit = 10, opts) {
|
|
|
627
635
|
// src/common/findInLinkedArrays.ts
|
|
628
636
|
function findInLinkedArrays(query, linked, limit = 10, opts) {
|
|
629
637
|
const queryTokens = prepareStringForSearch(query);
|
|
630
|
-
const hasNegation = queryTokens.some((t) => t.startsWith("--") || t.startsWith("~") || t.length > 1 && t[0] === "-" && /^[a-
|
|
638
|
+
const hasNegation = queryTokens.some((t) => t.startsWith("--") || t.startsWith("~") || t.length > 1 && t[0] === "-" && /^[a-zčćšžđñ]/i.test(t[1]));
|
|
631
639
|
if (queryTokens.length === 0) {
|
|
632
640
|
return { queryTokens, results: [], hasNegation: false };
|
|
633
641
|
}
|
package/dist/string.js
CHANGED
|
@@ -97,16 +97,24 @@ var RE_LEADING_ZEROS = /\b0+(\d)/g;
|
|
|
97
97
|
var RE_DECIMAL_COMMA = /(\d),(\d)/g;
|
|
98
98
|
var RE_STANDALONE_COMMA = /(?<!\d),(\d)/g;
|
|
99
99
|
var RE_ZERO_DECIMAL = /\b0+\./g;
|
|
100
|
+
var RE_PURE_DECIMAL = /(?<![a-zčćšžđñ\d.])(\d+)\.(\d+)(?![a-zčćšžđñ.\d])/gi;
|
|
100
101
|
var RE_DIGIT_DASH = /(\d)\s*-\s*(\d)/g;
|
|
101
|
-
var
|
|
102
|
-
var
|
|
102
|
+
var RE_LETTER_DASH_DIGIT = /([a-zčćšžđñ])-(\d)/gi;
|
|
103
|
+
var RE_DIGIT_DASH_LETTER = /(\d)-([a-zčćšžđñ])/gi;
|
|
104
|
+
var RE_LETTER_DASH_LETTER = /(?<=[a-zčćšžđñ])-(?=[a-zčćšžđñ])/gi;
|
|
105
|
+
var RE_LETTERS_DIGITS = /(^|\s)([a-zčćšžđñ]+)(\d+)(?=\s|$)/gi;
|
|
106
|
+
var RE_DIGITS_LETTERS = /(^|\s)(\d+)([a-zčćšžđñ]+)(?=\s|$)/gi;
|
|
103
107
|
function preprocessString(input) {
|
|
104
108
|
let result = input;
|
|
105
109
|
result = result.replace(RE_LEADING_ZEROS, "$1");
|
|
106
110
|
result = result.replace(RE_DECIMAL_COMMA, "$1.$2");
|
|
107
111
|
result = result.replace(RE_STANDALONE_COMMA, ".$1");
|
|
108
112
|
result = result.replace(RE_ZERO_DECIMAL, ".");
|
|
113
|
+
result = result.replace(RE_PURE_DECIMAL, "$1$2");
|
|
109
114
|
result = result.replace(RE_DIGIT_DASH, "$1-$2");
|
|
115
|
+
result = result.replace(RE_LETTER_DASH_DIGIT, "$1 $2");
|
|
116
|
+
result = result.replace(RE_DIGIT_DASH_LETTER, "$1 $2");
|
|
117
|
+
result = result.replace(RE_LETTER_DASH_LETTER, " ");
|
|
110
118
|
result = result.replace(RE_LETTERS_DIGITS, "$1$2 $3");
|
|
111
119
|
result = result.replace(RE_DIGITS_LETTERS, "$1$2 $3");
|
|
112
120
|
return result;
|
|
@@ -163,7 +171,7 @@ function tokenize(input, config) {
|
|
|
163
171
|
const replaced = config.replaceTokens.get(withoutPrefix);
|
|
164
172
|
return replaced ? "--" + replaced : token;
|
|
165
173
|
}
|
|
166
|
-
if (token.length > 1 && token[0] === "-" && /^[a-
|
|
174
|
+
if (token.length > 1 && token[0] === "-" && /^[a-zčćšžđñ]/i.test(token[1])) {
|
|
167
175
|
const withoutPrefix = token.slice(1);
|
|
168
176
|
const replaced = config.replaceTokens.get(withoutPrefix);
|
|
169
177
|
return replaced ? "-" + replaced : token;
|
|
@@ -418,7 +426,7 @@ function removeFromSearchMetadataBatch(metadata, objectIds) {
|
|
|
418
426
|
var DEFAULT_SEARCH_OPTS = {
|
|
419
427
|
matchWords: "start",
|
|
420
428
|
matchNumbers: "startEnd",
|
|
421
|
-
matchNumbersShort: "
|
|
429
|
+
matchNumbersShort: "start",
|
|
422
430
|
matchNumbersThreshold: 6
|
|
423
431
|
};
|
|
424
432
|
function arrayToSearchableData(items) {
|
|
@@ -557,7 +565,7 @@ function findInArray(query, data, metadata, limit = 10, opts) {
|
|
|
557
565
|
// src/common/findInLinkedArrays.ts
|
|
558
566
|
function findInLinkedArrays(query, linked, limit = 10, opts) {
|
|
559
567
|
const queryTokens = prepareStringForSearch(query);
|
|
560
|
-
const hasNegation = queryTokens.some((t) => t.startsWith("--") || t.startsWith("~") || t.length > 1 && t[0] === "-" && /^[a-
|
|
568
|
+
const hasNegation = queryTokens.some((t) => t.startsWith("--") || t.startsWith("~") || t.length > 1 && t[0] === "-" && /^[a-zčćšžđñ]/i.test(t[1]));
|
|
561
569
|
if (queryTokens.length === 0) {
|
|
562
570
|
return { queryTokens, results: [], hasNegation: false };
|
|
563
571
|
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matchTokenNumeric.d.ts","sourceRoot":"","sources":["../../src/utils/matchTokenNumeric.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,sBAAsB,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAiC9E;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,OAAO,CAAC;IACnB,6EAA6E;IAC7E,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,uFAAuF;IACvF,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,cAAc,EAAE,kBAAkB,EAAE,GAAG,OAAO,CAE9E;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,kBAAkB,EAAE,
|
|
1
|
+
{"version":3,"file":"matchTokenNumeric.d.ts","sourceRoot":"","sources":["../../src/utils/matchTokenNumeric.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,sBAAsB,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAiC9E;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,OAAO,CAAC;IACnB,6EAA6E;IAC7E,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,uFAAuF;IACvF,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,cAAc,EAAE,kBAAkB,EAAE,GAAG,OAAO,CAE9E;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,kBAAkB,EAAE,CAqEjF;AAoED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAiB5E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,8BAA8B,CAC5C,aAAa,EAAE,kBAAkB,EACjC,YAAY,EAAE,sBAAsB,EACpC,IAAI,CAAC,EAAE,UAAU,GAChB,OAAO,CA4DT;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,6BAA6B,CAC3C,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,sBAAsB,EACpC,IAAI,CAAC,EAAE,UAAU,GAChB,OAAO,CAaT;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CACpC,cAAc,EAAE,kBAAkB,EAAE,EACpC,YAAY,EAAE,sBAAsB,EACpC,IAAI,CAAC,EAAE,UAAU,GAChB,OAAO,CAYT;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,eAAe,EAAE,MAAM,EAAE,EACzB,YAAY,EAAE,sBAAsB,EACpC,IAAI,CAAC,EAAE,UAAU,GAChB,OAAO,CAGT"}
|
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
* Preprocesses a string for search by normalizing number formats and splitting mixed alphanumeric tokens.
|
|
3
3
|
*
|
|
4
4
|
* Processing steps:
|
|
5
|
-
* 1. Replaces decimal commas with periods (e.g., "12,3" → "12.3")
|
|
6
|
-
* 2.
|
|
5
|
+
* 1. Replaces decimal commas with periods, drops leading zeros (e.g., "12,3" → "12.3", "007" → "7")
|
|
6
|
+
* 2. Strips decimal period from pure standalone numbers (e.g., "11.22" → "1122", ".3" → "3")
|
|
7
|
+
* Does NOT strip from mixed tokens (".5kg") or multi-period tokens ("1.2.3")
|
|
7
8
|
* 3. Removes spaces in digit-dash-digit patterns (e.g., "12 - 25" → "12-25")
|
|
8
|
-
* 4.
|
|
9
|
+
* 4. Splits at letter-dash-digit, digit-dash-letter, and letter-dash-letter boundaries
|
|
10
|
+
* (e.g., "ABC-123" → "ABC 123", "Ioana-Gabriela" → "Ioana Gabriela");
|
|
11
|
+
* digit-dash-digit ranges stay intact (e.g., "12-25")
|
|
12
|
+
* 5. Inserts spaces at letter-to-digit boundaries (e.g., "SI123" → "SI 123", "123SI" → "123 SI")
|
|
9
13
|
*
|
|
10
14
|
* @param input - The raw input string to preprocess
|
|
11
15
|
* @returns Preprocessed string ready for sanitization
|
|
@@ -15,6 +19,9 @@
|
|
|
15
19
|
* preprocessString('SI123 Čokolada 0,5kg')
|
|
16
20
|
* // Returns: 'SI 123 Čokolada .5kg'
|
|
17
21
|
*
|
|
22
|
+
* preprocessString('abc 11.22 def')
|
|
23
|
+
* // Returns: 'abc 1122 def'
|
|
24
|
+
*
|
|
18
25
|
* preprocessString('007')
|
|
19
26
|
* // Returns: '7'
|
|
20
27
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preprocessString.d.ts","sourceRoot":"","sources":["../../src/utils/preprocessString.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"preprocessString.d.ts","sourceRoot":"","sources":["../../src/utils/preprocessString.ts"],"names":[],"mappings":"AAaA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAgCtD"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cry-search",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "A fast, memory-efficient search library for large datasets with support for tokenized matching, linked collections, and per-field match modes.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|