@usereactify/search 5.60.0-beta.1 → 5.60.0-beta.2

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/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ## [5.60.0-beta.2](///compare/beta-v5.60.0-beta.1...beta-v5.60.0-beta.2) (2026-01-15)
6
+
7
+
8
+ ### Features
9
+
10
+ * add term-level tracking and formatting for weight breakdown 949e7e9
11
+
5
12
  ## [5.60.0-beta.1](///compare/beta-v5.59.0-beta.8...beta-v5.60.0-beta.1) (2026-01-15)
6
13
 
7
14
 
package/dist/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@usereactify/search",
3
3
  "description": "React UI library for Reactify Search",
4
- "version": "5.60.0-beta.1",
4
+ "version": "5.60.0-beta.2",
5
5
  "license": "MIT",
6
6
  "main": "dist/src/index.js",
7
7
  "types": "dist/src/index.d.ts",
@@ -35,6 +35,8 @@ const ExampleProductCardWeight = ({ document }) => {
35
35
  const weight = (0, react_1.useMemo)(() => (explanation ? (0, utility_1.getWeight)(explanation) : document._score), [explanation, document._score]);
36
36
  // Parse the weight breakdown if available
37
37
  const weightBreakdown = (0, react_1.useMemo)(() => (explanation ? (0, utility_1.explainWeight)(explanation) : []), [explanation]);
38
+ // Memoized formatted breakdown for performance
39
+ const formattedBreakdown = (0, react_1.useMemo)(() => (0, utility_1.formatWeightBreakdown)(weightBreakdown), [weightBreakdown]);
38
40
  const toggleWeightBreakdown = () => setShowWeightBreakdown(!showWeightBreakdown);
39
41
  if (!options.devMode)
40
42
  return null;
@@ -65,13 +67,7 @@ const ExampleProductCardWeight = ({ document }) => {
65
67
  overflowY: "auto",
66
68
  padding: "8px",
67
69
  } },
68
- react_1.default.createElement("strong", { style: { display: "block", marginBottom: "4px" } }, "Breakdown:"),
69
- weightBreakdown.map((item, index) => (react_1.default.createElement("div", { key: index, style: { marginBottom: "2px" } },
70
- react_1.default.createElement("strong", null,
71
- item.field,
72
- ":"),
73
- " ",
74
- item.weight.toFixed(2))))))));
70
+ react_1.default.createElement("div", { style: { whiteSpace: "pre-line", fontFamily: "monospace" } }, formattedBreakdown)))));
75
71
  };
76
72
  exports.ExampleProductCardWeight = ExampleProductCardWeight;
77
73
  //# sourceMappingURL=ExampleProductCardWeight.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ExampleProductCardWeight.js","sourceRoot":"","sources":["../../../../src/components/Example/ExampleProductCardWeight.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+CAAiD;AAEjD,uCAAuD;AACvD,2CAAkG;AAO3F,MAAM,wBAAwB,GAAG,CAAC,EAAE,QAAQ,EAAiC,EAAE,EAAE;IACtF,MAAM,EAAE,OAAO,EAAE,GAAG,IAAA,gCAAwB,GAAE,CAAC;IAC/C,MAAM,CAAC,mBAAmB,EAAE,sBAAsB,CAAC,GAAG,IAAA,gBAAQ,EAAC,KAAK,CAAC,CAAC;IAEtE,8CAA8C;IAC9C,MAAM,WAAW,GAAG,QAAQ,CAAC,YAAY,CAAC;IAC1C,MAAM,MAAM,GAAG,IAAA,eAAO,EACpB,GAAG,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAA,mBAAS,EAAC,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAC9D,CAAC,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,CAC/B,CAAC;IAEF,0CAA0C;IAC1C,MAAM,eAAe,GAA0B,IAAA,eAAO,EACpD,GAAG,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAA,uBAAa,EAAC,WAAiC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAC3E,CAAC,WAAW,CAAC,CACd,CAAC;IAEF,MAAM,qBAAqB,GAAG,GAAG,EAAE,CAAC,sBAAsB,CAAC,CAAC,mBAAmB,CAAC,CAAC;IAEjF,IAAI,CAAC,OAAO,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAElC,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,OAAO,CACL,uCACE,SAAS,EAAC,iCAAiC,EAC3C,OAAO,EAAE,qBAAqB,EAC9B,KAAK,EAAE;YACL,UAAU,EAAE,oBAAoB;YAChC,YAAY,EAAE,KAAK;YACnB,KAAK,EAAE,OAAO;YACd,MAAM,EAAE,SAAS;YACjB,UAAU,EAAE,WAAW;YACvB,QAAQ,EAAE,MAAM;YAChB,UAAU,EAAE,MAAM;YAClB,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,SAAS;SACnB;QAED;;YAAc,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAO;QAErC,mBAAmB,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,IAAI,CACpD,uCACE,KAAK,EAAE;gBACL,eAAe,EAAE,2BAA2B;gBAC5C,MAAM,EAAE,gBAAgB;gBACxB,YAAY,EAAE,KAAK;gBACnB,KAAK,EAAE,OAAO;gBACd,QAAQ,EAAE,MAAM;gBAChB,SAAS,EAAE,KAAK;gBAChB,SAAS,EAAE,OAAO;gBAClB,SAAS,EAAE,MAAM;gBACjB,OAAO,EAAE,KAAK;aACf;YAED,0CAAQ,KAAK,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,iBAAqB;YAC5E,eAAe,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CACpC,uCAAK,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE;gBAC7C;oBAAS,IAAI,CAAC,KAAK;wBAAW;;gBAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAClD,CACP,CAAC,CACE,CACP,CACG,CACP,CAAC;AACJ,CAAC,CAAC;AAjEW,QAAA,wBAAwB,4BAiEnC","sourcesContent":["import React, { useState, useMemo } from \"react\";\n\nimport { useReactifySearchContext } from \"../../hooks\";\nimport { explainWeight, getWeight, ExplainScoreDetail, ExplainParsedWeight } from \"../../utility\";\nimport { ElasticProduct } from \"../../types\";\n\nexport interface ExampleProductCardWeightProps {\n document: ElasticProduct;\n}\n\nexport const ExampleProductCardWeight = ({ document }: ExampleProductCardWeightProps) => {\n const { options } = useReactifySearchContext();\n const [showWeightBreakdown, setShowWeightBreakdown] = useState(false);\n\n // Extract score and explanation from document\n const explanation = document._explanation;\n const weight = useMemo(\n () => (explanation ? getWeight(explanation) : document._score),\n [explanation, document._score]\n );\n\n // Parse the weight breakdown if available\n const weightBreakdown: ExplainParsedWeight[] = useMemo(\n () => (explanation ? explainWeight(explanation as ExplainScoreDetail) : []),\n [explanation]\n );\n\n const toggleWeightBreakdown = () => setShowWeightBreakdown(!showWeightBreakdown);\n\n if (!options.devMode) return null;\n\n if (!weight) return null;\n\n return (\n <div\n className=\"rs__result-card-product__weight\"\n onClick={toggleWeightBreakdown}\n style={{\n background: \"rgba(0, 0, 0, 0.8)\",\n borderRadius: \"4px\",\n color: \"white\",\n cursor: \"pointer\",\n fontFamily: \"monospace\",\n fontSize: \"11px\",\n fontWeight: \"bold\",\n maxWidth: \"100%\",\n padding: \"4px 8px\",\n }}\n >\n <div>Weight: {weight.toFixed(2)}</div>\n\n {showWeightBreakdown && weightBreakdown.length > 0 && (\n <div\n style={{\n backgroundColor: \"rgba(255, 255, 255, 0.95)\",\n border: \"1px solid #ccc\",\n borderRadius: \"4px\",\n color: \"black\",\n fontSize: \"10px\",\n marginTop: \"8px\",\n maxHeight: \"150px\",\n overflowY: \"auto\",\n padding: \"8px\",\n }}\n >\n <strong style={{ display: \"block\", marginBottom: \"4px\" }}>Breakdown:</strong>\n {weightBreakdown.map((item, index) => (\n <div key={index} style={{ marginBottom: \"2px\" }}>\n <strong>{item.field}:</strong> {item.weight.toFixed(2)}\n </div>\n ))}\n </div>\n )}\n </div>\n );\n};\n"]}
1
+ {"version":3,"file":"ExampleProductCardWeight.js","sourceRoot":"","sources":["../../../../src/components/Example/ExampleProductCardWeight.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+CAAiD;AAEjD,uCAAuD;AACvD,2CAMuB;AAOhB,MAAM,wBAAwB,GAAG,CAAC,EAAE,QAAQ,EAAiC,EAAE,EAAE;IACtF,MAAM,EAAE,OAAO,EAAE,GAAG,IAAA,gCAAwB,GAAE,CAAC;IAC/C,MAAM,CAAC,mBAAmB,EAAE,sBAAsB,CAAC,GAAG,IAAA,gBAAQ,EAAC,KAAK,CAAC,CAAC;IAEtE,8CAA8C;IAC9C,MAAM,WAAW,GAAG,QAAQ,CAAC,YAAY,CAAC;IAC1C,MAAM,MAAM,GAAG,IAAA,eAAO,EACpB,GAAG,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAA,mBAAS,EAAC,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAC9D,CAAC,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,CAC/B,CAAC;IAEF,0CAA0C;IAC1C,MAAM,eAAe,GAA0B,IAAA,eAAO,EACpD,GAAG,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAA,uBAAa,EAAC,WAAiC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAC3E,CAAC,WAAW,CAAC,CACd,CAAC;IAEF,+CAA+C;IAC/C,MAAM,kBAAkB,GAAG,IAAA,eAAO,EAAC,GAAG,EAAE,CAAC,IAAA,+BAAqB,EAAC,eAAe,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC;IAEpG,MAAM,qBAAqB,GAAG,GAAG,EAAE,CAAC,sBAAsB,CAAC,CAAC,mBAAmB,CAAC,CAAC;IAEjF,IAAI,CAAC,OAAO,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAElC,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,OAAO,CACL,uCACE,SAAS,EAAC,iCAAiC,EAC3C,OAAO,EAAE,qBAAqB,EAC9B,KAAK,EAAE;YACL,UAAU,EAAE,oBAAoB;YAChC,YAAY,EAAE,KAAK;YACnB,KAAK,EAAE,OAAO;YACd,MAAM,EAAE,SAAS;YACjB,UAAU,EAAE,WAAW;YACvB,QAAQ,EAAE,MAAM;YAChB,UAAU,EAAE,MAAM;YAClB,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,SAAS;SACnB;QAED;;YAAc,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAO;QAErC,mBAAmB,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,IAAI,CACpD,uCACE,KAAK,EAAE;gBACL,eAAe,EAAE,2BAA2B;gBAC5C,MAAM,EAAE,gBAAgB;gBACxB,YAAY,EAAE,KAAK;gBACnB,KAAK,EAAE,OAAO;gBACd,QAAQ,EAAE,MAAM;gBAChB,SAAS,EAAE,KAAK;gBAChB,SAAS,EAAE,OAAO;gBAClB,SAAS,EAAE,MAAM;gBACjB,OAAO,EAAE,KAAK;aACf;YAED,uCAAK,KAAK,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,IAAG,kBAAkB,CAAO,CACvF,CACP,CACG,CACP,CAAC;AACJ,CAAC,CAAC;AA/DW,QAAA,wBAAwB,4BA+DnC","sourcesContent":["import React, { useState, useMemo } from \"react\";\n\nimport { useReactifySearchContext } from \"../../hooks\";\nimport {\n explainWeight,\n getWeight,\n ExplainScoreDetail,\n ExplainParsedWeight,\n formatWeightBreakdown,\n} from \"../../utility\";\nimport { ElasticProduct } from \"../../types\";\n\nexport interface ExampleProductCardWeightProps {\n document: ElasticProduct;\n}\n\nexport const ExampleProductCardWeight = ({ document }: ExampleProductCardWeightProps) => {\n const { options } = useReactifySearchContext();\n const [showWeightBreakdown, setShowWeightBreakdown] = useState(false);\n\n // Extract score and explanation from document\n const explanation = document._explanation;\n const weight = useMemo(\n () => (explanation ? getWeight(explanation) : document._score),\n [explanation, document._score],\n );\n\n // Parse the weight breakdown if available\n const weightBreakdown: ExplainParsedWeight[] = useMemo(\n () => (explanation ? explainWeight(explanation as ExplainScoreDetail) : []),\n [explanation],\n );\n\n // Memoized formatted breakdown for performance\n const formattedBreakdown = useMemo(() => formatWeightBreakdown(weightBreakdown), [weightBreakdown]);\n\n const toggleWeightBreakdown = () => setShowWeightBreakdown(!showWeightBreakdown);\n\n if (!options.devMode) return null;\n\n if (!weight) return null;\n\n return (\n <div\n className=\"rs__result-card-product__weight\"\n onClick={toggleWeightBreakdown}\n style={{\n background: \"rgba(0, 0, 0, 0.8)\",\n borderRadius: \"4px\",\n color: \"white\",\n cursor: \"pointer\",\n fontFamily: \"monospace\",\n fontSize: \"11px\",\n fontWeight: \"bold\",\n maxWidth: \"100%\",\n padding: \"4px 8px\",\n }}\n >\n <div>Weight: {weight.toFixed(2)}</div>\n\n {showWeightBreakdown && weightBreakdown.length > 0 && (\n <div\n style={{\n backgroundColor: \"rgba(255, 255, 255, 0.95)\",\n border: \"1px solid #ccc\",\n borderRadius: \"4px\",\n color: \"black\",\n fontSize: \"10px\",\n marginTop: \"8px\",\n maxHeight: \"150px\",\n overflowY: \"auto\",\n padding: \"8px\",\n }}\n >\n <div style={{ whiteSpace: \"pre-line\", fontFamily: \"monospace\" }}>{formattedBreakdown}</div>\n </div>\n )}\n </div>\n );\n};\n"]}
@@ -3,9 +3,16 @@ export type ExplainScoreDetail = {
3
3
  description: string;
4
4
  details?: ExplainScoreDetail[];
5
5
  };
6
+ export type ExplainParsedTerm = {
7
+ term: string;
8
+ weight: number;
9
+ isSynonym: boolean;
10
+ };
6
11
  export type ExplainParsedWeight = {
7
12
  field: string;
8
13
  weight: number;
14
+ terms: ExplainParsedTerm[];
9
15
  };
10
16
  export declare function getWeight(explanation: ExplainScoreDetail): number;
11
17
  export declare function explainWeight(explanation: ExplainScoreDetail): ExplainParsedWeight[];
18
+ export declare function formatWeightBreakdown(weights: ExplainParsedWeight[]): string;
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getWeight = getWeight;
4
4
  exports.explainWeight = explainWeight;
5
+ exports.formatWeightBreakdown = formatWeightBreakdown;
5
6
  function getWeight(explanation) {
6
7
  var _a;
7
8
  const detail = (_a = explanation.details) === null || _a === void 0 ? void 0 : _a.find((detail) => detail.description === "min of:");
@@ -19,20 +20,41 @@ function parseWeights(detail) {
19
20
  if (detail.description.includes("min of:")) {
20
21
  if (detail.details) {
21
22
  for (const subDetail of detail.details) {
22
- if (subDetail.description.includes("function score") && subDetail.description.includes("product of:")) {
23
+ if (subDetail.description.includes("function score") &&
24
+ subDetail.description.includes("product of:")) {
23
25
  const parentWeight = subDetail.value;
24
26
  if (subDetail.details) {
25
27
  for (const functionDetail of subDetail.details) {
26
28
  if (functionDetail.description.includes("match filter:")) {
27
- const field = extractFieldFromMatchFilter(functionDetail.description);
28
- if (field) {
29
- parsedWeights.push({ field, weight: parentWeight });
29
+ const fieldTermData = extractFieldWithTerm(functionDetail.description);
30
+ if (fieldTermData) {
31
+ parsedWeights.push({
32
+ field: fieldTermData.field,
33
+ weight: 0, // Will be calculated in mergeWeights
34
+ terms: [
35
+ {
36
+ term: fieldTermData.term,
37
+ weight: parentWeight,
38
+ isSynonym: fieldTermData.isSynonym,
39
+ },
40
+ ],
41
+ });
30
42
  }
31
43
  }
32
44
  if (functionDetail.description.includes("weight")) {
33
45
  const field = extractFieldNameFromDetails(functionDetail);
34
46
  if (field && field !== "unknown") {
35
- parsedWeights.push({ field, weight: parentWeight });
47
+ parsedWeights.push({
48
+ field,
49
+ weight: 0, // Will be calculated in mergeWeights
50
+ terms: [
51
+ {
52
+ term: "unknown",
53
+ weight: parentWeight,
54
+ isSynonym: false,
55
+ },
56
+ ],
57
+ });
36
58
  }
37
59
  }
38
60
  }
@@ -43,20 +65,37 @@ function parseWeights(detail) {
43
65
  }
44
66
  // Fallback to original parsing if min_of is not found
45
67
  if (parsedWeights.length === 0) {
46
- if (detail.description.includes("function score") && detail.description.includes("product of:")) {
68
+ if (detail.description.includes("function score") &&
69
+ detail.description.includes("product of:")) {
47
70
  const parentWeight = detail.value;
48
71
  if (detail.details) {
49
72
  for (const subDetail of detail.details) {
50
73
  if (subDetail.description.includes("match filter:")) {
51
- const field = extractFieldFromMatchFilter(subDetail.description);
52
- if (field) {
53
- parsedWeights.push({ field, weight: parentWeight });
74
+ const fieldTermData = extractFieldWithTerm(subDetail.description);
75
+ if (fieldTermData) {
76
+ parsedWeights.push({
77
+ field: fieldTermData.field,
78
+ weight: 0, // Will be calculated in mergeWeights
79
+ terms: [
80
+ {
81
+ term: fieldTermData.term,
82
+ weight: parentWeight,
83
+ isSynonym: fieldTermData.isSynonym,
84
+ },
85
+ ],
86
+ });
54
87
  }
55
88
  }
56
89
  if (subDetail.description.includes("weight")) {
57
90
  const field = extractFieldNameFromDetails(subDetail);
58
91
  if (field && field !== "unknown") {
59
- parsedWeights.push({ field, weight: parentWeight });
92
+ parsedWeights.push({
93
+ field,
94
+ weight: 0, // Will be calculated in mergeWeights
95
+ terms: [
96
+ { term: "unknown", weight: parentWeight, isSynonym: false },
97
+ ],
98
+ });
60
99
  }
61
100
  }
62
101
  }
@@ -83,7 +122,9 @@ function extractFieldFromMatchFilter(description) {
83
122
  const synonymMatch = description.match(/\+Synonym\(([^:]+):/);
84
123
  if (synonymMatch) {
85
124
  const field = synonymMatch[1];
86
- if (field.includes("freq") || field.includes("*") || field.includes("_all")) {
125
+ if (field.includes("freq") ||
126
+ field.includes("*") ||
127
+ field.includes("_all")) {
87
128
  return null;
88
129
  }
89
130
  return field;
@@ -92,7 +133,9 @@ function extractFieldFromMatchFilter(description) {
92
133
  const simpleMatch = description.match(/match filter: ([a-zA-Z_]+):/);
93
134
  if (simpleMatch) {
94
135
  const field = simpleMatch[1];
95
- if (field.includes("freq") || field.includes("*") || field.includes("_all")) {
136
+ if (field.includes("freq") ||
137
+ field.includes("*") ||
138
+ field.includes("_all")) {
96
139
  return null;
97
140
  }
98
141
  return field;
@@ -101,7 +144,9 @@ function extractFieldFromMatchFilter(description) {
101
144
  const parenthesizedMatch = description.match(/match filter: \(([^:]+):/);
102
145
  if (parenthesizedMatch) {
103
146
  const field = parenthesizedMatch[1];
104
- if (field.includes("freq") || field.includes("*") || field.includes("_all")) {
147
+ if (field.includes("freq") ||
148
+ field.includes("*") ||
149
+ field.includes("_all")) {
105
150
  return null;
106
151
  }
107
152
  return field;
@@ -110,13 +155,58 @@ function extractFieldFromMatchFilter(description) {
110
155
  const complexMatch = description.match(/match filter: ([a-zA-Z_]+):[^(]+/);
111
156
  if (complexMatch) {
112
157
  const field = complexMatch[1];
113
- if (field.includes("freq") || field.includes("*") || field.includes("_all")) {
158
+ if (field.includes("freq") ||
159
+ field.includes("*") ||
160
+ field.includes("_all")) {
114
161
  return null;
115
162
  }
116
163
  return field;
117
164
  }
118
165
  return null;
119
166
  }
167
+ function extractTermFromFilter(description) {
168
+ // Extract from excluded terms in synonym queries: -field:term
169
+ const excludedMatch = description.match(/-([a-zA-Z_]+):([^)\s]+)/);
170
+ if (excludedMatch) {
171
+ const term = excludedMatch[2];
172
+ if (term.includes("freq") || term.includes("*") || term.includes("_all")) {
173
+ return null;
174
+ }
175
+ return { term, isSynonym: true };
176
+ }
177
+ // Extract from direct matches: field:term (but not parenthesized synonyms)
178
+ const directMatch = description.match(/match filter: ([a-zA-Z_]+):([^(\s]+)/);
179
+ if (directMatch) {
180
+ const term = directMatch[2];
181
+ if (term.includes("freq") || term.includes("*") || term.includes("_all")) {
182
+ return null;
183
+ }
184
+ return { term, isSynonym: false };
185
+ }
186
+ // Extract from parenthesized direct matches: (field:term)
187
+ const parenthesizedMatch = description.match(/match filter: \(([a-zA-Z_]+):([^)\s]+)/);
188
+ if (parenthesizedMatch) {
189
+ const term = parenthesizedMatch[2];
190
+ if (term.includes("freq") || term.includes("*") || term.includes("_all")) {
191
+ return null;
192
+ }
193
+ return { term, isSynonym: false };
194
+ }
195
+ return null;
196
+ }
197
+ function extractFieldWithTerm(description) {
198
+ const termData = extractTermFromFilter(description);
199
+ if (!termData)
200
+ return null;
201
+ const fieldData = extractFieldFromMatchFilter(description);
202
+ if (!fieldData)
203
+ return null;
204
+ return {
205
+ field: fieldData,
206
+ term: termData.term,
207
+ isSynonym: termData.isSynonym,
208
+ };
209
+ }
120
210
  function extractFieldNameFromDetails(detail) {
121
211
  const description = detail.description.toLowerCase();
122
212
  // Filter out undesired values
@@ -130,7 +220,9 @@ function extractFieldNameFromDetails(detail) {
130
220
  if (match) {
131
221
  const field = match[1];
132
222
  // Additional filtering for common unwanted patterns
133
- if (field.includes("freq") || field.includes("*") || field.includes("_all")) {
223
+ if (field.includes("freq") ||
224
+ field.includes("*") ||
225
+ field.includes("_all")) {
134
226
  return "unknown";
135
227
  }
136
228
  return field;
@@ -139,7 +231,9 @@ function extractFieldNameFromDetails(detail) {
139
231
  if (fallbackMatch) {
140
232
  const field = fallbackMatch[1];
141
233
  // Additional filtering for common unwanted patterns
142
- if (field.includes("freq") || field.includes("*") || field.includes("_all")) {
234
+ if (field.includes("freq") ||
235
+ field.includes("*") ||
236
+ field.includes("_all")) {
143
237
  return "unknown";
144
238
  }
145
239
  return field;
@@ -148,14 +242,44 @@ function extractFieldNameFromDetails(detail) {
148
242
  }
149
243
  function mergeWeights(weights) {
150
244
  const mergedWeights = {};
245
+ // Merge by field, then by term
151
246
  for (const weight of weights) {
152
- if (mergedWeights[weight.field]) {
153
- mergedWeights[weight.field].weight += weight.weight;
154
- }
155
- else {
156
- mergedWeights[weight.field] = Object.assign({}, weight);
247
+ for (const term of weight.terms) {
248
+ if (!mergedWeights[weight.field]) {
249
+ mergedWeights[weight.field] = {};
250
+ }
251
+ if (mergedWeights[weight.field][term.term]) {
252
+ mergedWeights[weight.field][term.term].weight += term.weight;
253
+ }
254
+ else {
255
+ mergedWeights[weight.field][term.term] = Object.assign({}, term);
256
+ }
157
257
  }
158
258
  }
159
- return Object.values(mergedWeights);
259
+ // Convert back to array format and sort terms by weight
260
+ const result = [];
261
+ for (const [field, terms] of Object.entries(mergedWeights)) {
262
+ const termArray = Object.values(terms).sort((a, b) => b.weight - a.weight);
263
+ const totalWeight = termArray.reduce((sum, term) => sum + term.weight, 0);
264
+ result.push({
265
+ field,
266
+ weight: totalWeight,
267
+ terms: termArray,
268
+ });
269
+ }
270
+ return result;
271
+ }
272
+ function formatWeightBreakdown(weights) {
273
+ const totalWeight = weights.reduce((sum, weight) => sum + weight.weight, 0);
274
+ const breakdown = weights
275
+ .sort((a, b) => b.weight - a.weight)
276
+ .map((weight) => {
277
+ const termBreakdown = weight.terms
278
+ .map((term) => `${term.term}: ${term.weight.toFixed(2)}${term.isSynonym ? " [synonym]" : ""}`)
279
+ .join(", ");
280
+ return `${weight.field}: ${weight.weight.toFixed(2)} (${termBreakdown})`;
281
+ })
282
+ .join("\n");
283
+ return `Weight: ${totalWeight.toFixed(2)}\nBreakdown:\n${breakdown}`;
160
284
  }
161
285
  //# sourceMappingURL=weight.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"weight.js","sourceRoot":"","sources":["../../../src/utility/weight.ts"],"names":[],"mappings":"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","sourcesContent":["export type ExplainScoreDetail = {\n value: number;\n description: string;\n details?: ExplainScoreDetail[];\n};\n\nexport type ExplainParsedWeight = {\n field: string;\n weight: number;\n};\n\nexport function getWeight(explanation: ExplainScoreDetail): number {\n const detail = explanation.details?.find((detail) => detail.description === \"min of:\");\n return detail ? detail.value : explanation.value;\n}\n\nexport function explainWeight(explanation: ExplainScoreDetail): ExplainParsedWeight[] {\n const fieldWeights = parseWeights(explanation);\n const mergedWeights = mergeWeights(fieldWeights);\n const sortedWeights = mergedWeights.sort((a, b) => b.weight - a.weight);\n\n return sortedWeights;\n}\n\nfunction parseWeights(detail: ExplainScoreDetail): ExplainParsedWeight[] {\n const parsedWeights: ExplainParsedWeight[] = [];\n\n // Look for min_of score which contains the clean field weights\n if (detail.description.includes(\"min of:\")) {\n if (detail.details) {\n for (const subDetail of detail.details) {\n if (subDetail.description.includes(\"function score\") && subDetail.description.includes(\"product of:\")) {\n const parentWeight = subDetail.value;\n\n if (subDetail.details) {\n for (const functionDetail of subDetail.details) {\n if (functionDetail.description.includes(\"match filter:\")) {\n const field = extractFieldFromMatchFilter(functionDetail.description);\n if (field) {\n parsedWeights.push({ field, weight: parentWeight });\n }\n }\n\n if (functionDetail.description.includes(\"weight\")) {\n const field = extractFieldNameFromDetails(functionDetail);\n if (field && field !== \"unknown\") {\n parsedWeights.push({ field, weight: parentWeight });\n }\n }\n }\n }\n }\n }\n }\n }\n\n // Fallback to original parsing if min_of is not found\n if (parsedWeights.length === 0) {\n if (detail.description.includes(\"function score\") && detail.description.includes(\"product of:\")) {\n const parentWeight = detail.value;\n\n if (detail.details) {\n for (const subDetail of detail.details) {\n if (subDetail.description.includes(\"match filter:\")) {\n const field = extractFieldFromMatchFilter(subDetail.description);\n if (field) {\n parsedWeights.push({ field, weight: parentWeight });\n }\n }\n\n if (subDetail.description.includes(\"weight\")) {\n const field = extractFieldNameFromDetails(subDetail);\n if (field && field !== \"unknown\") {\n parsedWeights.push({ field, weight: parentWeight });\n }\n }\n }\n }\n }\n }\n\n if (detail.details) {\n for (const subDetail of detail.details) {\n parsedWeights.push(...parseWeights(subDetail));\n }\n }\n\n return parsedWeights;\n}\n\nfunction extractFieldFromMatchFilter(description: string): string | null {\n const lowerDescription = description.toLowerCase();\n\n // Filter out undesired values early\n if (\n lowerDescription.includes(\"freq\") ||\n lowerDescription.includes(\"perfieldsimilarity\") ||\n lowerDescription.includes(\"*:*\") ||\n lowerDescription.includes(\"_all\")\n ) {\n return null;\n }\n\n // Handle synonym queries: +Synonym(tags_colour:atlantic tags_colour:emerald ...) -tags_colour:green\n const synonymMatch = description.match(/\\+Synonym\\(([^:]+):/);\n if (synonymMatch) {\n const field = synonymMatch[1];\n if (field.includes(\"freq\") || field.includes(\"*\") || field.includes(\"_all\")) {\n return null;\n }\n return field;\n }\n\n // Handle simple match filters: match filter: title:shirt\n const simpleMatch = description.match(/match filter: ([a-zA-Z_]+):/);\n if (simpleMatch) {\n const field = simpleMatch[1];\n if (field.includes(\"freq\") || field.includes(\"*\") || field.includes(\"_all\")) {\n return null;\n }\n return field;\n }\n\n // Handle parenthesized match filters: match filter: (product_type:shirts)\n const parenthesizedMatch = description.match(/match filter: \\(([^:]+):/);\n if (parenthesizedMatch) {\n const field = parenthesizedMatch[1];\n if (field.includes(\"freq\") || field.includes(\"*\") || field.includes(\"_all\")) {\n return null;\n }\n return field;\n }\n\n // Handle complex queries with boosts: title:shirt (title:short)^0.8\n const complexMatch = description.match(/match filter: ([a-zA-Z_]+):[^(]+/);\n if (complexMatch) {\n const field = complexMatch[1];\n if (field.includes(\"freq\") || field.includes(\"*\") || field.includes(\"_all\")) {\n return null;\n }\n return field;\n }\n\n return null;\n}\n\nfunction extractFieldNameFromDetails(detail: ExplainScoreDetail): string {\n const description = detail.description.toLowerCase();\n\n // Filter out undesired values\n if (\n description.includes(\"freq\") ||\n description.includes(\"perfieldsimilarity\") ||\n description.includes(\"*:*\") ||\n description.includes(\"_all\")\n ) {\n return \"unknown\";\n }\n\n const match = description.match(/\\(([^:]+):/);\n if (match) {\n const field = match[1];\n // Additional filtering for common unwanted patterns\n if (field.includes(\"freq\") || field.includes(\"*\") || field.includes(\"_all\")) {\n return \"unknown\";\n }\n return field;\n }\n\n const fallbackMatch = description.match(/([a-zA-Z_]+):/);\n if (fallbackMatch) {\n const field = fallbackMatch[1];\n // Additional filtering for common unwanted patterns\n if (field.includes(\"freq\") || field.includes(\"*\") || field.includes(\"_all\")) {\n return \"unknown\";\n }\n return field;\n }\n\n return \"unknown\";\n}\n\nfunction mergeWeights(weights: ExplainParsedWeight[]): ExplainParsedWeight[] {\n const mergedWeights: Record<string, ExplainParsedWeight> = {};\n\n for (const weight of weights) {\n if (mergedWeights[weight.field]) {\n mergedWeights[weight.field].weight += weight.weight;\n } else {\n mergedWeights[weight.field] = { ...weight };\n }\n }\n\n return Object.values(mergedWeights);\n}\n"]}
1
+ {"version":3,"file":"weight.js","sourceRoot":"","sources":["../../../src/utility/weight.ts"],"names":[],"mappings":"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","sourcesContent":["export type ExplainScoreDetail = {\n\tvalue: number;\n\tdescription: string;\n\tdetails?: ExplainScoreDetail[];\n};\n\nexport type ExplainParsedTerm = {\n\tterm: string;\n\tweight: number;\n\tisSynonym: boolean;\n};\n\nexport type ExplainParsedWeight = {\n\tfield: string;\n\tweight: number;\n\tterms: ExplainParsedTerm[];\n};\n\nexport function getWeight(explanation: ExplainScoreDetail): number {\n\tconst detail = explanation.details?.find(\n\t\t(detail) => detail.description === \"min of:\",\n\t);\n\treturn detail ? detail.value : explanation.value;\n}\n\nexport function explainWeight(\n\texplanation: ExplainScoreDetail,\n): ExplainParsedWeight[] {\n\tconst fieldWeights = parseWeights(explanation);\n\tconst mergedWeights = mergeWeights(fieldWeights);\n\tconst sortedWeights = mergedWeights.sort((a, b) => b.weight - a.weight);\n\n\treturn sortedWeights;\n}\n\nfunction parseWeights(detail: ExplainScoreDetail): ExplainParsedWeight[] {\n\tconst parsedWeights: ExplainParsedWeight[] = [];\n\n\t// Look for min_of score which contains the clean field weights\n\tif (detail.description.includes(\"min of:\")) {\n\t\tif (detail.details) {\n\t\t\tfor (const subDetail of detail.details) {\n\t\t\t\tif (\n\t\t\t\t\tsubDetail.description.includes(\"function score\") &&\n\t\t\t\t\tsubDetail.description.includes(\"product of:\")\n\t\t\t\t) {\n\t\t\t\t\tconst parentWeight = subDetail.value;\n\n\t\t\t\t\tif (subDetail.details) {\n\t\t\t\t\t\tfor (const functionDetail of subDetail.details) {\n\t\t\t\t\t\t\tif (functionDetail.description.includes(\"match filter:\")) {\n\t\t\t\t\t\t\t\tconst fieldTermData = extractFieldWithTerm(\n\t\t\t\t\t\t\t\t\tfunctionDetail.description,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tif (fieldTermData) {\n\t\t\t\t\t\t\t\t\tparsedWeights.push({\n\t\t\t\t\t\t\t\t\t\tfield: fieldTermData.field,\n\t\t\t\t\t\t\t\t\t\tweight: 0, // Will be calculated in mergeWeights\n\t\t\t\t\t\t\t\t\t\tterms: [\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tterm: fieldTermData.term,\n\t\t\t\t\t\t\t\t\t\t\t\tweight: parentWeight,\n\t\t\t\t\t\t\t\t\t\t\t\tisSynonym: fieldTermData.isSynonym,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (functionDetail.description.includes(\"weight\")) {\n\t\t\t\t\t\t\t\tconst field = extractFieldNameFromDetails(functionDetail);\n\t\t\t\t\t\t\t\tif (field && field !== \"unknown\") {\n\t\t\t\t\t\t\t\t\tparsedWeights.push({\n\t\t\t\t\t\t\t\t\t\tfield,\n\t\t\t\t\t\t\t\t\t\tweight: 0, // Will be calculated in mergeWeights\n\t\t\t\t\t\t\t\t\t\tterms: [\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tterm: \"unknown\",\n\t\t\t\t\t\t\t\t\t\t\t\tweight: parentWeight,\n\t\t\t\t\t\t\t\t\t\t\t\tisSynonym: false,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Fallback to original parsing if min_of is not found\n\tif (parsedWeights.length === 0) {\n\t\tif (\n\t\t\tdetail.description.includes(\"function score\") &&\n\t\t\tdetail.description.includes(\"product of:\")\n\t\t) {\n\t\t\tconst parentWeight = detail.value;\n\n\t\t\tif (detail.details) {\n\t\t\t\tfor (const subDetail of detail.details) {\n\t\t\t\t\tif (subDetail.description.includes(\"match filter:\")) {\n\t\t\t\t\t\tconst fieldTermData = extractFieldWithTerm(subDetail.description);\n\t\t\t\t\t\tif (fieldTermData) {\n\t\t\t\t\t\t\tparsedWeights.push({\n\t\t\t\t\t\t\t\tfield: fieldTermData.field,\n\t\t\t\t\t\t\t\tweight: 0, // Will be calculated in mergeWeights\n\t\t\t\t\t\t\t\tterms: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tterm: fieldTermData.term,\n\t\t\t\t\t\t\t\t\t\tweight: parentWeight,\n\t\t\t\t\t\t\t\t\t\tisSynonym: fieldTermData.isSynonym,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (subDetail.description.includes(\"weight\")) {\n\t\t\t\t\t\tconst field = extractFieldNameFromDetails(subDetail);\n\t\t\t\t\t\tif (field && field !== \"unknown\") {\n\t\t\t\t\t\t\tparsedWeights.push({\n\t\t\t\t\t\t\t\tfield,\n\t\t\t\t\t\t\t\tweight: 0, // Will be calculated in mergeWeights\n\t\t\t\t\t\t\t\tterms: [\n\t\t\t\t\t\t\t\t\t{ term: \"unknown\", weight: parentWeight, isSynonym: false },\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (detail.details) {\n\t\tfor (const subDetail of detail.details) {\n\t\t\tparsedWeights.push(...parseWeights(subDetail));\n\t\t}\n\t}\n\n\treturn parsedWeights;\n}\n\nfunction extractFieldFromMatchFilter(description: string): string | null {\n\tconst lowerDescription = description.toLowerCase();\n\n\t// Filter out undesired values early\n\tif (\n\t\tlowerDescription.includes(\"freq\") ||\n\t\tlowerDescription.includes(\"perfieldsimilarity\") ||\n\t\tlowerDescription.includes(\"*:*\") ||\n\t\tlowerDescription.includes(\"_all\")\n\t) {\n\t\treturn null;\n\t}\n\n\t// Handle synonym queries: +Synonym(tags_colour:atlantic tags_colour:emerald ...) -tags_colour:green\n\tconst synonymMatch = description.match(/\\+Synonym\\(([^:]+):/);\n\tif (synonymMatch) {\n\t\tconst field = synonymMatch[1];\n\t\tif (\n\t\t\tfield.includes(\"freq\") ||\n\t\t\tfield.includes(\"*\") ||\n\t\t\tfield.includes(\"_all\")\n\t\t) {\n\t\t\treturn null;\n\t\t}\n\t\treturn field;\n\t}\n\n\t// Handle simple match filters: match filter: title:shirt\n\tconst simpleMatch = description.match(/match filter: ([a-zA-Z_]+):/);\n\tif (simpleMatch) {\n\t\tconst field = simpleMatch[1];\n\t\tif (\n\t\t\tfield.includes(\"freq\") ||\n\t\t\tfield.includes(\"*\") ||\n\t\t\tfield.includes(\"_all\")\n\t\t) {\n\t\t\treturn null;\n\t\t}\n\t\treturn field;\n\t}\n\n\t// Handle parenthesized match filters: match filter: (product_type:shirts)\n\tconst parenthesizedMatch = description.match(/match filter: \\(([^:]+):/);\n\tif (parenthesizedMatch) {\n\t\tconst field = parenthesizedMatch[1];\n\t\tif (\n\t\t\tfield.includes(\"freq\") ||\n\t\t\tfield.includes(\"*\") ||\n\t\t\tfield.includes(\"_all\")\n\t\t) {\n\t\t\treturn null;\n\t\t}\n\t\treturn field;\n\t}\n\n\t// Handle complex queries with boosts: title:shirt (title:short)^0.8\n\tconst complexMatch = description.match(/match filter: ([a-zA-Z_]+):[^(]+/);\n\tif (complexMatch) {\n\t\tconst field = complexMatch[1];\n\t\tif (\n\t\t\tfield.includes(\"freq\") ||\n\t\t\tfield.includes(\"*\") ||\n\t\t\tfield.includes(\"_all\")\n\t\t) {\n\t\t\treturn null;\n\t\t}\n\t\treturn field;\n\t}\n\n\treturn null;\n}\n\nfunction extractTermFromFilter(\n\tdescription: string,\n): { term: string; isSynonym: boolean } | null {\n\t// Extract from excluded terms in synonym queries: -field:term\n\tconst excludedMatch = description.match(/-([a-zA-Z_]+):([^)\\s]+)/);\n\tif (excludedMatch) {\n\t\tconst term = excludedMatch[2];\n\t\tif (term.includes(\"freq\") || term.includes(\"*\") || term.includes(\"_all\")) {\n\t\t\treturn null;\n\t\t}\n\t\treturn { term, isSynonym: true };\n\t}\n\n\t// Extract from direct matches: field:term (but not parenthesized synonyms)\n\tconst directMatch = description.match(/match filter: ([a-zA-Z_]+):([^(\\s]+)/);\n\tif (directMatch) {\n\t\tconst term = directMatch[2];\n\t\tif (term.includes(\"freq\") || term.includes(\"*\") || term.includes(\"_all\")) {\n\t\t\treturn null;\n\t\t}\n\t\treturn { term, isSynonym: false };\n\t}\n\n\t// Extract from parenthesized direct matches: (field:term)\n\tconst parenthesizedMatch = description.match(\n\t\t/match filter: \\(([a-zA-Z_]+):([^)\\s]+)/,\n\t);\n\tif (parenthesizedMatch) {\n\t\tconst term = parenthesizedMatch[2];\n\t\tif (term.includes(\"freq\") || term.includes(\"*\") || term.includes(\"_all\")) {\n\t\t\treturn null;\n\t\t}\n\t\treturn { term, isSynonym: false };\n\t}\n\n\treturn null;\n}\n\nfunction extractFieldWithTerm(\n\tdescription: string,\n): { field: string; term: string; isSynonym: boolean } | null {\n\tconst termData = extractTermFromFilter(description);\n\tif (!termData) return null;\n\n\tconst fieldData = extractFieldFromMatchFilter(description);\n\tif (!fieldData) return null;\n\n\treturn {\n\t\tfield: fieldData,\n\t\tterm: termData.term,\n\t\tisSynonym: termData.isSynonym,\n\t};\n}\n\nfunction extractFieldNameFromDetails(detail: ExplainScoreDetail): string {\n\tconst description = detail.description.toLowerCase();\n\n\t// Filter out undesired values\n\tif (\n\t\tdescription.includes(\"freq\") ||\n\t\tdescription.includes(\"perfieldsimilarity\") ||\n\t\tdescription.includes(\"*:*\") ||\n\t\tdescription.includes(\"_all\")\n\t) {\n\t\treturn \"unknown\";\n\t}\n\n\tconst match = description.match(/\\(([^:]+):/);\n\tif (match) {\n\t\tconst field = match[1];\n\t\t// Additional filtering for common unwanted patterns\n\t\tif (\n\t\t\tfield.includes(\"freq\") ||\n\t\t\tfield.includes(\"*\") ||\n\t\t\tfield.includes(\"_all\")\n\t\t) {\n\t\t\treturn \"unknown\";\n\t\t}\n\t\treturn field;\n\t}\n\n\tconst fallbackMatch = description.match(/([a-zA-Z_]+):/);\n\tif (fallbackMatch) {\n\t\tconst field = fallbackMatch[1];\n\t\t// Additional filtering for common unwanted patterns\n\t\tif (\n\t\t\tfield.includes(\"freq\") ||\n\t\t\tfield.includes(\"*\") ||\n\t\t\tfield.includes(\"_all\")\n\t\t) {\n\t\t\treturn \"unknown\";\n\t\t}\n\t\treturn field;\n\t}\n\n\treturn \"unknown\";\n}\n\nfunction mergeWeights(weights: ExplainParsedWeight[]): ExplainParsedWeight[] {\n\tconst mergedWeights: Record<string, Record<string, ExplainParsedTerm>> = {};\n\n\t// Merge by field, then by term\n\tfor (const weight of weights) {\n\t\tfor (const term of weight.terms) {\n\t\t\tif (!mergedWeights[weight.field]) {\n\t\t\t\tmergedWeights[weight.field] = {};\n\t\t\t}\n\n\t\t\tif (mergedWeights[weight.field][term.term]) {\n\t\t\t\tmergedWeights[weight.field][term.term].weight += term.weight;\n\t\t\t} else {\n\t\t\t\tmergedWeights[weight.field][term.term] = { ...term };\n\t\t\t}\n\t\t}\n\t}\n\n\t// Convert back to array format and sort terms by weight\n\tconst result: ExplainParsedWeight[] = [];\n\tfor (const [field, terms] of Object.entries(mergedWeights)) {\n\t\tconst termArray = Object.values(terms).sort((a, b) => b.weight - a.weight);\n\t\tconst totalWeight = termArray.reduce((sum, term) => sum + term.weight, 0);\n\n\t\tresult.push({\n\t\t\tfield,\n\t\t\tweight: totalWeight,\n\t\t\tterms: termArray,\n\t\t});\n\t}\n\n\treturn result;\n}\n\nexport function formatWeightBreakdown(weights: ExplainParsedWeight[]): string {\n\tconst totalWeight = weights.reduce((sum, weight) => sum + weight.weight, 0);\n\tconst breakdown = weights\n\t\t.sort((a, b) => b.weight - a.weight)\n\t\t.map((weight) => {\n\t\t\tconst termBreakdown = weight.terms\n\t\t\t\t.map(\n\t\t\t\t\t(term) =>\n\t\t\t\t\t\t`${term.term}: ${term.weight.toFixed(2)}${term.isSynonym ? \" [synonym]\" : \"\"}`,\n\t\t\t\t)\n\t\t\t\t.join(\", \");\n\t\t\treturn `${weight.field}: ${weight.weight.toFixed(2)} (${termBreakdown})`;\n\t\t})\n\t\t.join(\"\\n\");\n\n\treturn `Weight: ${totalWeight.toFixed(2)}\\nBreakdown:\\n${breakdown}`;\n}\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@usereactify/search",
3
3
  "description": "React UI library for Reactify Search",
4
- "version": "5.60.0-beta.1",
4
+ "version": "5.60.0-beta.2",
5
5
  "license": "MIT",
6
6
  "main": "dist/src/index.js",
7
7
  "types": "dist/src/index.d.ts",