cmpstr 3.0.4 → 3.1.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.
Files changed (89) hide show
  1. package/README.md +2 -1
  2. package/dist/CmpStr.esm.js +345 -90
  3. package/dist/CmpStr.esm.js.map +1 -1
  4. package/dist/CmpStr.esm.min.js +3 -3
  5. package/dist/CmpStr.esm.min.js.map +1 -1
  6. package/dist/CmpStr.umd.js +342 -89
  7. package/dist/CmpStr.umd.js.map +1 -1
  8. package/dist/CmpStr.umd.min.js +3 -3
  9. package/dist/CmpStr.umd.min.js.map +1 -1
  10. package/dist/cjs/CmpStr.cjs +41 -1
  11. package/dist/cjs/CmpStr.cjs.map +1 -1
  12. package/dist/cjs/CmpStrAsync.cjs +38 -1
  13. package/dist/cjs/CmpStrAsync.cjs.map +1 -1
  14. package/dist/cjs/index.cjs +1 -1
  15. package/dist/cjs/metric/Cosine.cjs +1 -1
  16. package/dist/cjs/metric/DamerauLevenshtein.cjs +1 -1
  17. package/dist/cjs/metric/DiceSorensen.cjs +1 -1
  18. package/dist/cjs/metric/Hamming.cjs +1 -1
  19. package/dist/cjs/metric/Jaccard.cjs +1 -1
  20. package/dist/cjs/metric/JaroWinkler.cjs +1 -1
  21. package/dist/cjs/metric/LCS.cjs +1 -1
  22. package/dist/cjs/metric/Levenshtein.cjs +1 -1
  23. package/dist/cjs/metric/Metric.cjs +1 -1
  24. package/dist/cjs/metric/NeedlemanWunsch.cjs +1 -1
  25. package/dist/cjs/metric/SmithWaterman.cjs +1 -1
  26. package/dist/cjs/metric/qGram.cjs +1 -1
  27. package/dist/cjs/phonetic/Caverphone.cjs +1 -1
  28. package/dist/cjs/phonetic/Cologne.cjs +1 -1
  29. package/dist/cjs/phonetic/Metaphone.cjs +1 -1
  30. package/dist/cjs/phonetic/Phonetic.cjs +1 -1
  31. package/dist/cjs/phonetic/Soundex.cjs +1 -1
  32. package/dist/cjs/root.cjs +13 -1
  33. package/dist/cjs/root.cjs.map +1 -1
  34. package/dist/cjs/utils/DeepMerge.cjs +1 -1
  35. package/dist/cjs/utils/DiffChecker.cjs +1 -1
  36. package/dist/cjs/utils/Filter.cjs +1 -1
  37. package/dist/cjs/utils/HashTable.cjs +1 -1
  38. package/dist/cjs/utils/Normalizer.cjs +1 -1
  39. package/dist/cjs/utils/Pool.cjs +10 -1
  40. package/dist/cjs/utils/Pool.cjs.map +1 -1
  41. package/dist/cjs/utils/Profiler.cjs +1 -1
  42. package/dist/cjs/utils/Registry.cjs +1 -1
  43. package/dist/cjs/utils/StructuredData.cjs +145 -0
  44. package/dist/cjs/utils/StructuredData.cjs.map +1 -0
  45. package/dist/cjs/utils/TextAnalyzer.cjs +1 -1
  46. package/dist/esm/CmpStr.mjs +41 -1
  47. package/dist/esm/CmpStr.mjs.map +1 -1
  48. package/dist/esm/CmpStrAsync.mjs +38 -1
  49. package/dist/esm/CmpStrAsync.mjs.map +1 -1
  50. package/dist/esm/index.mjs +1 -1
  51. package/dist/esm/metric/Cosine.mjs +1 -1
  52. package/dist/esm/metric/DamerauLevenshtein.mjs +1 -1
  53. package/dist/esm/metric/DiceSorensen.mjs +1 -1
  54. package/dist/esm/metric/Hamming.mjs +1 -1
  55. package/dist/esm/metric/Jaccard.mjs +1 -1
  56. package/dist/esm/metric/JaroWinkler.mjs +1 -1
  57. package/dist/esm/metric/LCS.mjs +1 -1
  58. package/dist/esm/metric/Levenshtein.mjs +1 -1
  59. package/dist/esm/metric/Metric.mjs +1 -1
  60. package/dist/esm/metric/NeedlemanWunsch.mjs +1 -1
  61. package/dist/esm/metric/SmithWaterman.mjs +1 -1
  62. package/dist/esm/metric/qGram.mjs +1 -1
  63. package/dist/esm/phonetic/Caverphone.mjs +1 -1
  64. package/dist/esm/phonetic/Cologne.mjs +1 -1
  65. package/dist/esm/phonetic/Metaphone.mjs +1 -1
  66. package/dist/esm/phonetic/Phonetic.mjs +1 -1
  67. package/dist/esm/phonetic/Soundex.mjs +1 -1
  68. package/dist/esm/root.mjs +7 -1
  69. package/dist/esm/root.mjs.map +1 -1
  70. package/dist/esm/utils/DeepMerge.mjs +1 -1
  71. package/dist/esm/utils/DiffChecker.mjs +1 -1
  72. package/dist/esm/utils/Filter.mjs +1 -1
  73. package/dist/esm/utils/HashTable.mjs +1 -1
  74. package/dist/esm/utils/Normalizer.mjs +1 -1
  75. package/dist/esm/utils/Pool.mjs +10 -1
  76. package/dist/esm/utils/Pool.mjs.map +1 -1
  77. package/dist/esm/utils/Profiler.mjs +1 -1
  78. package/dist/esm/utils/Registry.mjs +1 -1
  79. package/dist/esm/utils/StructuredData.mjs +143 -0
  80. package/dist/esm/utils/StructuredData.mjs.map +1 -0
  81. package/dist/esm/utils/TextAnalyzer.mjs +1 -1
  82. package/dist/types/CmpStr.d.ts +90 -8
  83. package/dist/types/CmpStrAsync.d.ts +82 -8
  84. package/dist/types/index.d.ts +3 -2
  85. package/dist/types/root.d.ts +3 -2
  86. package/dist/types/utils/Pool.d.ts +2 -2
  87. package/dist/types/utils/StructuredData.d.ts +162 -0
  88. package/dist/types/utils/Types.d.ts +35 -1
  89. package/package.json +52 -17
@@ -1,7 +1,7 @@
1
1
  /**
2
- * CmpStr v3.0.4 build-74e65a5-250915
2
+ * CmpStr v3.1.0 build-76aadb9-260117
3
3
  * This is a lightweight, fast and well performing library for calculating string similarity.
4
- * (c) 2023-2025 Paul Köhler @komed3 / MIT License
4
+ * (c) 2023-2026 Paul Köhler @komed3 / MIT License
5
5
  * Visit https://github.com/komed3/cmpstr and https://npmjs.org/package/cmpstr
6
6
  */
7
7
  (function (global, factory) {
@@ -23,6 +23,12 @@
23
23
  function get(t, path, fallback) {
24
24
  return parse(path).reduce((o, k) => o?.[k] ?? fallback, t);
25
25
  }
26
+ function has(t, path) {
27
+ return (
28
+ parse(path).reduce((o, k) => (o && k in o ? o[k] : undefined), t) !==
29
+ undefined
30
+ );
31
+ }
26
32
  function set(t, path, value) {
27
33
  if (path === '') return value;
28
34
  const [k, ...r] = parse(path);
@@ -77,6 +83,15 @@
77
83
  return t;
78
84
  }
79
85
 
86
+ var DeepMerge = /*#__PURE__*/ Object.freeze({
87
+ __proto__: null,
88
+ get: get,
89
+ has: has,
90
+ merge: merge,
91
+ rmv: rmv,
92
+ set: set
93
+ });
94
+
80
95
  class Profiler {
81
96
  static ENV;
82
97
  static instance;
@@ -847,6 +862,244 @@
847
862
  }
848
863
  }
849
864
 
865
+ class RingPool {
866
+ maxSize;
867
+ buffers = [];
868
+ pointer = 0;
869
+ constructor(maxSize) {
870
+ this.maxSize = maxSize;
871
+ }
872
+ acquire(minSize, allowOversize) {
873
+ const len = this.buffers.length;
874
+ for (let i = 0; i < len; i++) {
875
+ const idx = (this.pointer + i) % len;
876
+ const item = this.buffers[idx];
877
+ if (item.size >= minSize) {
878
+ this.pointer = (idx + 1) % len;
879
+ return allowOversize || item.size === minSize ? item : null;
880
+ }
881
+ }
882
+ return null;
883
+ }
884
+ release(item) {
885
+ if (this.buffers.length < this.maxSize) {
886
+ this.buffers.push(item);
887
+ } else {
888
+ this.buffers[this.pointer] = item;
889
+ this.pointer = (this.pointer + 1) % this.maxSize;
890
+ }
891
+ }
892
+ clear() {
893
+ this.buffers = [];
894
+ this.pointer = 0;
895
+ }
896
+ }
897
+ class Pool {
898
+ static CONFIG = {
899
+ uint16: {
900
+ type: 'uint16',
901
+ maxSize: 32,
902
+ maxItemSize: 2048,
903
+ allowOversize: true
904
+ },
905
+ 'number[]': {
906
+ type: 'number[]',
907
+ maxSize: 16,
908
+ maxItemSize: 1024,
909
+ allowOversize: false
910
+ },
911
+ 'string[]': {
912
+ type: 'string[]',
913
+ maxSize: 4,
914
+ maxItemSize: 1024,
915
+ allowOversize: false
916
+ },
917
+ set: { type: 'set', maxSize: 8, maxItemSize: 0, allowOversize: false },
918
+ map: { type: 'map', maxSize: 8, maxItemSize: 0, allowOversize: false }
919
+ };
920
+ static POOLS = {
921
+ uint16: new RingPool(32),
922
+ 'number[]': new RingPool(16),
923
+ 'string[]': new RingPool(4),
924
+ set: new RingPool(8),
925
+ map: new RingPool(8)
926
+ };
927
+ static allocate(type, size) {
928
+ switch (type) {
929
+ case 'uint16':
930
+ return new Uint16Array(size);
931
+ case 'number[]':
932
+ return new Array(size).fill(0);
933
+ case 'string[]':
934
+ return new Array(size);
935
+ case 'set':
936
+ return new Set();
937
+ case 'map':
938
+ return new Map();
939
+ }
940
+ }
941
+ static acquire(type, size) {
942
+ const CONFIG = this.CONFIG[type];
943
+ if (size > CONFIG.maxItemSize) return this.allocate(type, size);
944
+ const item = this.POOLS[type].acquire(size, CONFIG.allowOversize);
945
+ if (item) {
946
+ return type === 'uint16' ? item.buffer.subarray(0, size) : item.buffer;
947
+ }
948
+ return this.allocate(type, size);
949
+ }
950
+ static acquireMany(type, sizes) {
951
+ return sizes.map((size) => this.acquire(type, size));
952
+ }
953
+ static release(type, buffer, size) {
954
+ const CONFIG = this.CONFIG[type];
955
+ if (size <= CONFIG.maxItemSize) {
956
+ this.POOLS[type].release({ buffer, size });
957
+ }
958
+ }
959
+ }
960
+
961
+ class StructuredData {
962
+ static create(data, key) {
963
+ return new StructuredData(data, key);
964
+ }
965
+ data;
966
+ key;
967
+ constructor(data, key) {
968
+ this.data = data;
969
+ this.key = key;
970
+ }
971
+ extractFrom(arr, key) {
972
+ const result = Pool.acquire('string[]', arr.length);
973
+ for (let i = 0; i < arr.length; i++) {
974
+ const val = arr[i][key];
975
+ result[i] = typeof val === 'string' ? val : String(val ?? '');
976
+ }
977
+ return result;
978
+ }
979
+ extract() {
980
+ return this.extractFrom(this.data, this.key);
981
+ }
982
+ isMetricResult(v) {
983
+ return (
984
+ typeof v === 'object' &&
985
+ v !== null &&
986
+ 'a' in v &&
987
+ 'b' in v &&
988
+ 'res' in v
989
+ );
990
+ }
991
+ isCmpStrResult(v) {
992
+ return (
993
+ typeof v === 'object' &&
994
+ v !== null &&
995
+ 'source' in v &&
996
+ 'target' in v &&
997
+ 'match' in v
998
+ );
999
+ }
1000
+ normalizeResults(results) {
1001
+ if (!Array.isArray(results) || results.length === 0) return [];
1002
+ const first = results[0];
1003
+ if (this.isMetricResult(first)) return results;
1004
+ if (this.isCmpStrResult(first))
1005
+ return results.map((r) => ({
1006
+ metric: 'unknown',
1007
+ a: r.source,
1008
+ b: r.target,
1009
+ res: r.match,
1010
+ raw: r.raw
1011
+ }));
1012
+ return [];
1013
+ }
1014
+ rebuild(results, sourceData, extractedStrings, removeZero, objectsOnly) {
1015
+ const output = new Array(results.length);
1016
+ let out = 0;
1017
+ for (let i = 0; i < results.length; i++) {
1018
+ const result = results[i];
1019
+ if (removeZero && result.res === 0) continue;
1020
+ let dataIndex =
1021
+ result.b && extractedStrings.length
1022
+ ? extractedStrings.indexOf(result.b)
1023
+ : i;
1024
+ if (dataIndex < 0 || dataIndex >= sourceData.length) dataIndex = i;
1025
+ const sourceObj = sourceData[dataIndex];
1026
+ if (objectsOnly) output[out++] = sourceObj;
1027
+ else
1028
+ output[out++] = {
1029
+ obj: sourceObj,
1030
+ key: this.key,
1031
+ result: {
1032
+ source: result.a,
1033
+ target: extractedStrings[dataIndex] || result.b,
1034
+ match: result.res
1035
+ },
1036
+ ...(result.raw ? { raw: result.raw } : null)
1037
+ };
1038
+ }
1039
+ output.length = out;
1040
+ return output;
1041
+ }
1042
+ sort(results, sort) {
1043
+ if (!sort || results.length <= 1) return results;
1044
+ const asc = sort === 'asc';
1045
+ return results.sort((a, b) => (asc ? a.res - b.res : b.res - a.res));
1046
+ }
1047
+ performLookup(fn, extractedStrings, opt) {
1048
+ return this.rebuild(
1049
+ this.sort(this.normalizeResults(fn()), opt?.sort),
1050
+ this.data,
1051
+ extractedStrings,
1052
+ opt?.removeZero,
1053
+ opt?.objectsOnly
1054
+ );
1055
+ }
1056
+ async performLookupAsync(fn, extractedStrings, opt) {
1057
+ return this.rebuild(
1058
+ this.sort(this.normalizeResults(await fn()), opt?.sort),
1059
+ this.data,
1060
+ extractedStrings,
1061
+ opt?.removeZero,
1062
+ opt?.objectsOnly
1063
+ );
1064
+ }
1065
+ lookup(fn, query, opt) {
1066
+ const b = this.extract();
1067
+ try {
1068
+ return this.performLookup(() => fn(query, b, opt), b, opt);
1069
+ } finally {
1070
+ Pool.release('string[]', b, b.length);
1071
+ }
1072
+ }
1073
+ lookupPairs(fn, other, otherKey, opt) {
1074
+ const a = this.extract();
1075
+ const b = this.extractFrom(other, otherKey);
1076
+ try {
1077
+ return this.performLookup(() => fn(a, b, opt), a, opt);
1078
+ } finally {
1079
+ Pool.release('string[]', a, a.length);
1080
+ Pool.release('string[]', b, b.length);
1081
+ }
1082
+ }
1083
+ async lookupAsync(fn, query, opt) {
1084
+ const b = this.extract();
1085
+ try {
1086
+ return await this.performLookupAsync(() => fn(query, b, opt), b, opt);
1087
+ } finally {
1088
+ Pool.release('string[]', b, b.length);
1089
+ }
1090
+ }
1091
+ async lookupPairsAsync(fn, other, otherKey, opt) {
1092
+ const a = this.extract();
1093
+ const b = this.extractFrom(other, otherKey);
1094
+ try {
1095
+ return await this.performLookupAsync(() => fn(a, b, opt), a, opt);
1096
+ } finally {
1097
+ Pool.release('string[]', a, a.length);
1098
+ Pool.release('string[]', b, b.length);
1099
+ }
1100
+ }
1101
+ }
1102
+
850
1103
  const registry = Object.create(null);
851
1104
  const factory = Object.create(null);
852
1105
  function Registry(reg, ctor) {
@@ -1076,93 +1329,6 @@
1076
1329
  }
1077
1330
  const MetricRegistry = Registry('metric', Metric);
1078
1331
 
1079
- class RingPool {
1080
- maxSize;
1081
- buffers = [];
1082
- pointer = 0;
1083
- constructor(maxSize) {
1084
- this.maxSize = maxSize;
1085
- }
1086
- acquire(minSize, allowOversize) {
1087
- const len = this.buffers.length;
1088
- for (let i = 0; i < len; i++) {
1089
- const idx = (this.pointer + i) % len;
1090
- const item = this.buffers[idx];
1091
- if (item.size >= minSize) {
1092
- this.pointer = (idx + 1) % len;
1093
- return allowOversize || item.size === minSize ? item : null;
1094
- }
1095
- }
1096
- return null;
1097
- }
1098
- release(item) {
1099
- if (this.buffers.length < this.maxSize) {
1100
- this.buffers.push(item);
1101
- } else {
1102
- this.buffers[this.pointer] = item;
1103
- this.pointer = (this.pointer + 1) % this.maxSize;
1104
- }
1105
- }
1106
- clear() {
1107
- this.buffers = [];
1108
- this.pointer = 0;
1109
- }
1110
- }
1111
- class Pool {
1112
- static CONFIG = {
1113
- uint16: {
1114
- type: 'uint16',
1115
- maxSize: 32,
1116
- maxItemSize: 2048,
1117
- allowOversize: true
1118
- },
1119
- 'number[]': {
1120
- type: 'number[]',
1121
- maxSize: 16,
1122
- maxItemSize: 1024,
1123
- allowOversize: false
1124
- },
1125
- set: { type: 'set', maxSize: 8, maxItemSize: 0, allowOversize: false },
1126
- map: { type: 'map', maxSize: 8, maxItemSize: 0, allowOversize: false }
1127
- };
1128
- static POOLS = {
1129
- uint16: new RingPool(32),
1130
- 'number[]': new RingPool(16),
1131
- set: new RingPool(8),
1132
- map: new RingPool(8)
1133
- };
1134
- static allocate(type, size) {
1135
- switch (type) {
1136
- case 'uint16':
1137
- return new Uint16Array(size);
1138
- case 'number[]':
1139
- return new Array(size).fill(0);
1140
- case 'set':
1141
- return new Set();
1142
- case 'map':
1143
- return new Map();
1144
- }
1145
- }
1146
- static acquire(type, size) {
1147
- const CONFIG = this.CONFIG[type];
1148
- if (size > CONFIG.maxItemSize) return this.allocate(type, size);
1149
- const item = this.POOLS[type].acquire(size, CONFIG.allowOversize);
1150
- if (item) {
1151
- return type === 'uint16' ? item.buffer.subarray(0, size) : item.buffer;
1152
- }
1153
- return this.allocate(type, size);
1154
- }
1155
- static acquireMany(type, sizes) {
1156
- return sizes.map((size) => this.acquire(type, size));
1157
- }
1158
- static release(type, buffer, size) {
1159
- const CONFIG = this.CONFIG[type];
1160
- if (size <= CONFIG.maxItemSize) {
1161
- this.POOLS[type].release({ buffer, size });
1162
- }
1163
- }
1164
- }
1165
-
1166
1332
  class CosineSimilarity extends Metric {
1167
1333
  constructor(a, b, opt = {}) {
1168
1334
  super('cosine', a, b, opt, true);
@@ -2155,6 +2321,9 @@
2155
2321
  ? input.map((s) => phonetic.getIndex(s).join(delimiter))
2156
2322
  : phonetic.getIndex(input).join(delimiter);
2157
2323
  }
2324
+ structured(data, key) {
2325
+ return StructuredData.create(data, key);
2326
+ }
2158
2327
  compute(a, b, opt, mode, raw, skip) {
2159
2328
  const resolved = this.resolveOptions(opt);
2160
2329
  this.assert('metric', resolved.metric);
@@ -2288,6 +2457,42 @@
2288
2457
  const { algo: a, opt: o } = this.options.processors?.phonetic ?? {};
2289
2458
  return this.index(input, { algo: algo ?? a, opt: opt ?? o });
2290
2459
  }
2460
+ structuredLookup(query, data, key, opt) {
2461
+ return this.structured(data, key).lookup(
2462
+ (q, items, options) => this.batchTest(q, items, options),
2463
+ query,
2464
+ opt
2465
+ );
2466
+ }
2467
+ structuredMatch(query, data, key, threshold, opt) {
2468
+ return this.structured(data, key).lookup(
2469
+ (q, items, options) => this.match(q, items, threshold, options),
2470
+ query,
2471
+ { ...opt, sort: 'desc' }
2472
+ );
2473
+ }
2474
+ structuredClosest(query, data, key, n = 1, opt) {
2475
+ return this.structured(data, key).lookup(
2476
+ (q, items, options) => this.closest(q, items, n, options),
2477
+ query,
2478
+ { ...opt, sort: 'desc' }
2479
+ );
2480
+ }
2481
+ structuredFurthest(query, data, key, n = 1, opt) {
2482
+ return this.structured(data, key).lookup(
2483
+ (q, items, options) => this.furthest(q, items, n, options),
2484
+ query,
2485
+ { ...opt, sort: 'asc' }
2486
+ );
2487
+ }
2488
+ structuredPairs(data, key, other, otherKey, opt) {
2489
+ return this.structured(data, key).lookupPairs(
2490
+ (items, otherItems, options) => this.pairs(items, otherItems, options),
2491
+ other,
2492
+ otherKey,
2493
+ opt
2494
+ );
2495
+ }
2291
2496
  }
2292
2497
 
2293
2498
  class CmpStrAsync extends CmpStr {
@@ -2404,12 +2609,60 @@
2404
2609
  const { algo: a, opt: o } = this.options.processors?.phonetic ?? {};
2405
2610
  return this.indexAsync(input, { algo: algo ?? a, opt: opt ?? o });
2406
2611
  }
2612
+ async structuredLookupAsync(query, data, key, opt) {
2613
+ return await this.structured(data, key).lookupAsync(
2614
+ (q, items, options) => this.batchTestAsync(q, items, options),
2615
+ query,
2616
+ opt
2617
+ );
2618
+ }
2619
+ async structuredMatchAsync(query, data, key, threshold, opt) {
2620
+ return await this.structured(data, key).lookupAsync(
2621
+ (q, items, options) => this.matchAsync(q, items, threshold, options),
2622
+ query,
2623
+ { ...opt, sort: 'desc' }
2624
+ );
2625
+ }
2626
+ async structuredClosestAsync(query, data, key, n = 1, opt) {
2627
+ return await this.structured(data, key).lookupAsync(
2628
+ (q, items, options) => this.closestAsync(q, items, n, options),
2629
+ query,
2630
+ { ...opt, sort: 'desc' }
2631
+ );
2632
+ }
2633
+ async structuredFurthestAsync(query, data, key, n = 1, opt) {
2634
+ return await this.structured(data, key).lookupAsync(
2635
+ (q, items, options) => this.furthestAsync(q, items, n, options),
2636
+ query,
2637
+ { ...opt, sort: 'asc' }
2638
+ );
2639
+ }
2640
+ async structuredPairsAsync(data, key, other, otherKey, opt) {
2641
+ return await this.structured(data, key).lookupPairsAsync(
2642
+ (items, otherItems, options) =>
2643
+ this.pairsAsync(items, otherItems, options),
2644
+ other,
2645
+ otherKey,
2646
+ opt
2647
+ );
2648
+ }
2407
2649
  }
2408
2650
 
2409
2651
  exports.CmpStr = CmpStr;
2410
2652
  exports.CmpStrAsync = CmpStrAsync;
2653
+ exports.DeepMerge = DeepMerge;
2411
2654
  exports.DiffChecker = DiffChecker;
2655
+ exports.Filter = Filter;
2656
+ exports.HashTable = HashTable;
2657
+ exports.Metric = Metric;
2658
+ exports.MetricRegistry = MetricRegistry;
2412
2659
  exports.Normalizer = Normalizer;
2660
+ exports.Phonetic = Phonetic;
2661
+ exports.PhoneticMappingRegistry = PhoneticMappingRegistry;
2662
+ exports.PhoneticRegistry = PhoneticRegistry;
2663
+ exports.Pool = Pool;
2664
+ exports.Profiler = Profiler;
2665
+ exports.StructuredData = StructuredData;
2413
2666
  exports.TextAnalyzer = TextAnalyzer;
2414
2667
  });
2415
2668
  //# sourceMappingURL=CmpStr.umd.js.map