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 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): whole match only
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 "12" vs target "123" → no match (target is short, needs exact)
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: 'whole') - how to match short numbers (≤threshold digits)
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 (it's a negative number). Use `--5` or `~5` to negate numbers.
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 (it's a negative number). Use `--5` or `~5` to negate numbers.
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)**: require exact (whole) match
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 "123" against code "123" (3 digits) → MATCH (exact)
359
- // Query "12" against code "123" (3 digits) → NO MATCH (short number needs exact)
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: "whole",
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 RE_LETTERS_DIGITS = /(^|\s)([a-zA-Z]+)(\d+)(?=\s|$)/g;
204
- var RE_DIGITS_LETTERS = /(^|\s)(\d+)([a-zA-Z]+)(?=\s|$)/g;
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-z]/i.test(token[1])) {
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-z]/i.test(str[1])) {
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: "whole",
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 RE_LETTERS_DIGITS = /(^|\s)([a-zA-Z]+)(\d+)(?=\s|$)/g;
119
- var RE_DIGITS_LETTERS = /(^|\s)(\d+)([a-zA-Z]+)(?=\s|$)/g;
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-z]/i.test(token[1])) {
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-z]/i.test(str[1])) {
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 RE_LETTERS_DIGITS = /(^|\s)([a-zA-Z]+)(\d+)(?=\s|$)/g;
172
- var RE_DIGITS_LETTERS = /(^|\s)(\d+)([a-zA-Z]+)(?=\s|$)/g;
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-z]/i.test(token[1])) {
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: "whole",
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-z]/i.test(t[1]));
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 RE_LETTERS_DIGITS = /(^|\s)([a-zA-Z]+)(\d+)(?=\s|$)/g;
102
- var RE_DIGITS_LETTERS = /(^|\s)(\d+)([a-zA-Z]+)(?=\s|$)/g;
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-z]/i.test(token[1])) {
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: "whole",
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-z]/i.test(t[1]));
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
  }
@@ -73,7 +73,7 @@ export interface SearchOpts {
73
73
  matchNumbers?: MatchMode;
74
74
  /**
75
75
  * How to match short numbers (digits <= matchNumbersThreshold)
76
- * @default 'whole'
76
+ * @default 'start'
77
77
  */
78
78
  matchNumbersShort?: MatchMode;
79
79
  /**
@@ -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,CA8DjF;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"}
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. Drops leading zeros from numbers (e.g., "007" → "7", "0,3" → ".3")
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. Inserts spaces at letter-to-digit boundaries (e.g., "SI123" → "SI 123", "123SI" → "123 SI")
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":"AASA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAqBtD"}
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",
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",