instantsearch.js 4.40.2 → 4.40.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.
Files changed (43) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/cjs/connectors/breadcrumb/connectBreadcrumb.js +1 -1
  3. package/cjs/connectors/current-refinements/connectCurrentRefinements.js +13 -1
  4. package/cjs/connectors/hierarchical-menu/connectHierarchicalMenu.js +4 -3
  5. package/cjs/connectors/menu/connectMenu.js +3 -2
  6. package/cjs/connectors/refinement-list/connectRefinementList.js +7 -5
  7. package/cjs/connectors/toggle-refinement/connectToggleRefinement.js +6 -6
  8. package/cjs/lib/routers/history.js +46 -31
  9. package/cjs/lib/utils/escapeFacetValue.js +23 -0
  10. package/cjs/lib/utils/getRefinements.js +10 -14
  11. package/cjs/lib/utils/index.js +7 -9
  12. package/cjs/lib/version.js +1 -1
  13. package/dist/instantsearch.development.d.ts +3 -3
  14. package/dist/instantsearch.development.js +158 -79
  15. package/dist/instantsearch.development.js.map +1 -1
  16. package/dist/instantsearch.production.d.ts +3 -3
  17. package/dist/instantsearch.production.min.d.ts +3 -3
  18. package/dist/instantsearch.production.min.js +2 -2
  19. package/dist/instantsearch.production.min.js.map +1 -1
  20. package/es/connectors/breadcrumb/connectBreadcrumb.js +1 -1
  21. package/es/connectors/current-refinements/connectCurrentRefinements.js +13 -1
  22. package/es/connectors/hierarchical-menu/connectHierarchicalMenu.js +4 -3
  23. package/es/connectors/menu/connectMenu.js +3 -2
  24. package/es/connectors/refinement-list/connectRefinementList.js +7 -5
  25. package/es/connectors/toggle-refinement/connectToggleRefinement.js +7 -7
  26. package/es/lib/routers/history.d.ts +3 -3
  27. package/es/lib/routers/history.js +46 -31
  28. package/es/lib/utils/escapeFacetValue.d.ts +4 -0
  29. package/es/lib/utils/escapeFacetValue.js +14 -0
  30. package/es/lib/utils/getRefinements.d.ts +22 -7
  31. package/es/lib/utils/getRefinements.js +10 -13
  32. package/es/lib/utils/index.d.ts +1 -2
  33. package/es/lib/utils/index.js +1 -2
  34. package/es/lib/version.d.ts +1 -1
  35. package/es/lib/version.js +1 -1
  36. package/es/types/results.d.ts +2 -7
  37. package/package.json +3 -3
  38. package/cjs/lib/utils/escapeRefinement.js +0 -17
  39. package/cjs/lib/utils/unescapeRefinement.js +0 -13
  40. package/es/lib/utils/escapeRefinement.d.ts +0 -3
  41. package/es/lib/utils/escapeRefinement.js +0 -9
  42. package/es/lib/utils/unescapeRefinement.d.ts +0 -2
  43. package/es/lib/utils/unescapeRefinement.js +0 -5
package/CHANGELOG.md CHANGED
@@ -1,3 +1,30 @@
1
+ ## [4.40.5](https://github.com/algolia/instantsearch.js/compare/v4.40.4...v4.40.5) (2022-04-26)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **routing:** prevent writing the same URL twice ([#5045](https://github.com/algolia/instantsearch.js/issues/5045)) ([5d79d92](https://github.com/algolia/instantsearch.js/commit/5d79d92b30e188e5206dcb5fe86fcac058c3f09b))
7
+
8
+
9
+
10
+ ## [4.40.4](https://github.com/algolia/instantsearch.js/compare/v4.40.3...v4.40.4) (2022-04-13)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * **currentRefinements:** correctly show and allow for refining escaped values ([#5041](https://github.com/algolia/instantsearch.js/issues/5041)) ([277f4df](https://github.com/algolia/instantsearch.js/commit/277f4dff21fb7eeaeb41a8c49aaaf707f880ee58))
16
+
17
+
18
+
19
+ ## [4.40.3](https://github.com/algolia/instantsearch.js/compare/v4.40.2...v4.40.3) (2022-04-04)
20
+
21
+
22
+ ### Bug Fixes
23
+
24
+ * **refinements:** escape facet values starting with "-" ([#5039](https://github.com/algolia/instantsearch.js/issues/5039)) ([6b6f4e8](https://github.com/algolia/instantsearch.js/commit/6b6f4e86550a3c9dd02f3a8400d832cef64cb45d))
25
+
26
+
27
+
1
28
  ## [4.40.2](https://github.com/algolia/instantsearch.js/compare/v4.40.1...v4.40.2) (2022-03-29)
2
29
 
3
30
 
@@ -157,7 +157,7 @@ function prepareItems(data) {
157
157
  if (currentItem.isRefined) {
158
158
  result.push({
159
159
  label: currentItem.name,
160
- value: currentItem.path
160
+ value: currentItem.escapedValue
161
161
  });
162
162
 
163
163
  if (Array.isArray(currentItem.data)) {
@@ -195,7 +195,7 @@ function getOperatorSymbol(operator) {
195
195
  }
196
196
 
197
197
  function normalizeRefinement(refinement) {
198
- var value = refinement.type === 'numeric' ? Number(refinement.name) : refinement.name;
198
+ var value = getValue(refinement);
199
199
  var label = refinement.operator ? "".concat(getOperatorSymbol(refinement.operator), " ").concat(refinement.name) : refinement.name;
200
200
  var normalizedRefinement = {
201
201
  attribute: refinement.attribute,
@@ -219,5 +219,17 @@ function normalizeRefinement(refinement) {
219
219
  return normalizedRefinement;
220
220
  }
221
221
 
222
+ function getValue(refinement) {
223
+ if (refinement.type === 'numeric') {
224
+ return Number(refinement.name);
225
+ }
226
+
227
+ if ('escapedValue' in refinement) {
228
+ return refinement.escapedValue;
229
+ }
230
+
231
+ return refinement.name;
232
+ }
233
+
222
234
  var _default = connectCurrentRefinements;
223
235
  exports.default = _default;
@@ -114,13 +114,14 @@ var connectHierarchicalMenu = function connectHierarchicalMenu(renderFn) {
114
114
  function _prepareFacetValues(facetValues) {
115
115
  return facetValues.slice(0, getLimit()).map(function (_ref2) {
116
116
  var label = _ref2.name,
117
- value = _ref2.path,
117
+ value = _ref2.escapedValue,
118
118
  data = _ref2.data,
119
- subValue = _objectWithoutProperties(_ref2, ["name", "path", "data"]);
119
+ path = _ref2.path,
120
+ subValue = _objectWithoutProperties(_ref2, ["name", "escapedValue", "data", "path"]);
120
121
 
121
122
  var item = _objectSpread(_objectSpread({}, subValue), {}, {
122
- label: label,
123
123
  value: value,
124
+ label: label,
124
125
  data: null
125
126
  });
126
127
 
@@ -169,8 +169,9 @@ var connectMenu = function connectMenu(renderFn) {
169
169
  canToggleShowMore = showMore && (isShowingMore || facetItems.length > getLimit());
170
170
  items = transformItems(facetItems.slice(0, getLimit()).map(function (_ref3) {
171
171
  var label = _ref3.name,
172
- value = _ref3.path,
173
- item = _objectWithoutProperties(_ref3, ["name", "path"]);
172
+ value = _ref3.escapedValue,
173
+ path = _ref3.path,
174
+ item = _objectWithoutProperties(_ref3, ["name", "escapedValue", "path"]);
174
175
 
175
176
  return _objectSpread(_objectSpread({}, item), {}, {
176
177
  label: label,
@@ -72,11 +72,12 @@ var connectRefinementList = function connectRefinementList(renderFn) {
72
72
 
73
73
  var formatItems = function formatItems(_ref2) {
74
74
  var label = _ref2.name,
75
- item = _objectWithoutProperties(_ref2, ["name"]);
75
+ value = _ref2.escapedValue,
76
+ item = _objectWithoutProperties(_ref2, ["name", "escapedValue"]);
76
77
 
77
78
  return _objectSpread(_objectSpread({}, item), {}, {
79
+ value: value,
78
80
  label: label,
79
- value: label,
80
81
  highlighted: label
81
82
  });
82
83
  };
@@ -134,11 +135,12 @@ var connectRefinementList = function connectRefinementList(renderFn) {
134
135
  Math.min(getLimit(), 100), tags).then(function (results) {
135
136
  var facetValues = escapeFacetValues ? (0, _index.escapeFacets)(results.facetHits) : results.facetHits;
136
137
  var normalizedFacetValues = transformItems(facetValues.map(function (_ref3) {
137
- var value = _ref3.value,
138
- item = _objectWithoutProperties(_ref3, ["value"]);
138
+ var escapedValue = _ref3.escapedValue,
139
+ value = _ref3.value,
140
+ item = _objectWithoutProperties(_ref3, ["escapedValue", "value"]);
139
141
 
140
142
  return _objectSpread(_objectSpread({}, item), {}, {
141
- value: value,
143
+ value: escapedValue,
142
144
  label: value
143
145
  });
144
146
  }), {
@@ -89,8 +89,8 @@ var connectToggleRefinement = function connectToggleRefinement(renderFn) {
89
89
  }
90
90
 
91
91
  var hasAnOffValue = userOff !== undefined;
92
- var on = (0, _index.toArray)(userOn).map(_index.escapeRefinement);
93
- var off = hasAnOffValue ? (0, _index.toArray)(userOff).map(_index.escapeRefinement) : undefined;
92
+ var on = (0, _index.toArray)(userOn).map(_index.escapeFacetValue);
93
+ var off = hasAnOffValue ? (0, _index.toArray)(userOff).map(_index.escapeFacetValue) : undefined;
94
94
  var sendEvent;
95
95
 
96
96
  var toggleRefinementFactory = function toggleRefinementFactory(helper) {
@@ -203,16 +203,16 @@ var connectToggleRefinement = function connectToggleRefinement(renderFn) {
203
203
  var allFacetValues = results.getFacetValues(attribute, {}) || [];
204
204
  var onData = on.map(function (v) {
205
205
  return (0, _index.find)(allFacetValues, function (_ref7) {
206
- var name = _ref7.name;
207
- return name === (0, _index.unescapeRefinement)(v);
206
+ var escapedValue = _ref7.escapedValue;
207
+ return escapedValue === (0, _index.escapeFacetValue)(String(v));
208
208
  });
209
209
  }).filter(function (v) {
210
210
  return v !== undefined;
211
211
  });
212
212
  var offData = hasAnOffValue ? offValue.map(function (v) {
213
213
  return (0, _index.find)(allFacetValues, function (_ref8) {
214
- var name = _ref8.name;
215
- return name === (0, _index.unescapeRefinement)(v);
214
+ var escapedValue = _ref8.escapedValue;
215
+ return escapedValue === (0, _index.escapeFacetValue)(String(v));
216
216
  });
217
217
  }).filter(function (v) {
218
218
  return v !== undefined;
@@ -56,7 +56,7 @@ var BrowserHistory = /*#__PURE__*/function () {
56
56
 
57
57
  _defineProperty(this, "writeTimer", void 0);
58
58
 
59
- _defineProperty(this, "shouldPushState", true);
59
+ _defineProperty(this, "inPopState", false);
60
60
 
61
61
  _defineProperty(this, "isDisposed", false);
62
62
 
@@ -111,20 +111,14 @@ var BrowserHistory = /*#__PURE__*/function () {
111
111
  }
112
112
 
113
113
  _this2.writeTimer = setTimeout(function () {
114
- setWindowTitle(title); // We do want to `pushState` if:
115
- // - the router is not disposed, IS.js needs to update the URL
116
- // OR
117
- // - the last write was from InstantSearch.js
118
- // (unlike a SPA, where it would have last written)
114
+ setWindowTitle(title);
119
115
 
120
- var lastPushWasByISAfterDispose = !_this2.isDisposed || _this2.latestAcknowledgedHistory === window.history.length;
121
-
122
- if (_this2.shouldPushState && lastPushWasByISAfterDispose) {
116
+ if (_this2.shouldWrite(url)) {
123
117
  window.history.pushState(routeState, title || '', url);
124
118
  _this2.latestAcknowledgedHistory = window.history.length;
125
119
  }
126
120
 
127
- _this2.shouldPushState = true;
121
+ _this2.inPopState = false;
128
122
  _this2.writeTimer = undefined;
129
123
  }, _this2.writeDelay);
130
124
  });
@@ -145,7 +139,7 @@ var BrowserHistory = /*#__PURE__*/function () {
145
139
  _this3.writeTimer = undefined;
146
140
  }
147
141
 
148
- _this3.shouldPushState = false;
142
+ _this3.inPopState = true;
149
143
  var routeState = event.state; // At initial load, the state is read from the URL without update.
150
144
  // Therefore the state object is not available.
151
145
  // In this case, we fallback and read the URL.
@@ -203,18 +197,39 @@ var BrowserHistory = /*#__PURE__*/function () {
203
197
 
204
198
  this.write({});
205
199
  }
200
+ }, {
201
+ key: "shouldWrite",
202
+ value: function shouldWrite(url) {
203
+ var _this5 = this;
204
+
205
+ return (0, _index.safelyRunOnBrowser)(function (_ref6) {
206
+ var window = _ref6.window;
207
+ // We do want to `pushState` if:
208
+ // - the router is not disposed, IS.js needs to update the URL
209
+ // OR
210
+ // - the last write was from InstantSearch.js
211
+ // (unlike a SPA, where it would have last written)
212
+ var lastPushWasByISAfterDispose = !(_this5.isDisposed && _this5.latestAcknowledgedHistory !== window.history.length);
213
+ return (// When the last state change was through popstate, the IS.js state changes,
214
+ // but that should not write the URL.
215
+ !_this5.inPopState && // When the previous pushState after dispose was by IS.js, we want to write the URL.
216
+ lastPushWasByISAfterDispose && // When the URL is the same as the current one, we do not want to write it.
217
+ url !== window.location.href
218
+ );
219
+ });
220
+ }
206
221
  }]);
207
222
 
208
223
  return BrowserHistory;
209
224
  }();
210
225
 
211
226
  function historyRouter() {
212
- var _ref6 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
213
- _ref6$createURL = _ref6.createURL,
214
- createURL = _ref6$createURL === void 0 ? function (_ref7) {
215
- var qsModule = _ref7.qsModule,
216
- routeState = _ref7.routeState,
217
- location = _ref7.location;
227
+ var _ref7 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
228
+ _ref7$createURL = _ref7.createURL,
229
+ createURL = _ref7$createURL === void 0 ? function (_ref8) {
230
+ var qsModule = _ref8.qsModule,
231
+ routeState = _ref8.routeState,
232
+ location = _ref8.location;
218
233
  var protocol = location.protocol,
219
234
  hostname = location.hostname,
220
235
  _location$port = location.port,
@@ -230,11 +245,11 @@ function historyRouter() {
230
245
  }
231
246
 
232
247
  return "".concat(protocol, "//").concat(hostname).concat(portWithPrefix).concat(pathname, "?").concat(queryString).concat(hash);
233
- } : _ref6$createURL,
234
- _ref6$parseURL = _ref6.parseURL,
235
- parseURL = _ref6$parseURL === void 0 ? function (_ref8) {
236
- var qsModule = _ref8.qsModule,
237
- location = _ref8.location;
248
+ } : _ref7$createURL,
249
+ _ref7$parseURL = _ref7.parseURL,
250
+ parseURL = _ref7$parseURL === void 0 ? function (_ref9) {
251
+ var qsModule = _ref9.qsModule,
252
+ location = _ref9.location;
238
253
  // `qs` by default converts arrays with more than 20 items to an object.
239
254
  // We want to avoid this because the data structure manipulated can therefore vary.
240
255
  // Setting the limit to `100` seems a good number because the engine's default is 100
@@ -248,21 +263,21 @@ function historyRouter() {
248
263
  return qsModule.parse(location.search.slice(1), {
249
264
  arrayLimit: 99
250
265
  });
251
- } : _ref6$parseURL,
252
- _ref6$writeDelay = _ref6.writeDelay,
253
- writeDelay = _ref6$writeDelay === void 0 ? 400 : _ref6$writeDelay,
254
- windowTitle = _ref6.windowTitle,
255
- _ref6$getLocation = _ref6.getLocation,
256
- getLocation = _ref6$getLocation === void 0 ? function () {
257
- return (0, _index.safelyRunOnBrowser)(function (_ref9) {
258
- var window = _ref9.window;
266
+ } : _ref7$parseURL,
267
+ _ref7$writeDelay = _ref7.writeDelay,
268
+ writeDelay = _ref7$writeDelay === void 0 ? 400 : _ref7$writeDelay,
269
+ windowTitle = _ref7.windowTitle,
270
+ _ref7$getLocation = _ref7.getLocation,
271
+ getLocation = _ref7$getLocation === void 0 ? function () {
272
+ return (0, _index.safelyRunOnBrowser)(function (_ref10) {
273
+ var window = _ref10.window;
259
274
  return window.location;
260
275
  }, {
261
276
  fallback: function fallback() {
262
277
  throw new Error('You need to provide `getLocation` to the `history` router in environments where `window` does not exist.');
263
278
  }
264
279
  });
265
- } : _ref6$getLocation;
280
+ } : _ref7$getLocation;
266
281
 
267
282
  return new BrowserHistory({
268
283
  createURL: createURL,
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.unescapeFacetValue = unescapeFacetValue;
7
+ exports.escapeFacetValue = escapeFacetValue;
8
+
9
+ function unescapeFacetValue(value) {
10
+ if (typeof value === 'string') {
11
+ return value.replace(/^\\-/, '-');
12
+ }
13
+
14
+ return value;
15
+ }
16
+
17
+ function escapeFacetValue(value) {
18
+ if (typeof value === 'number' && value < 0 || typeof value === 'string') {
19
+ return String(value).replace(/^-/, '\\-');
20
+ }
21
+
22
+ return value;
23
+ }
@@ -3,11 +3,11 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.default = void 0;
6
+ exports.default = getRefinements;
7
7
 
8
8
  var _find = _interopRequireDefault(require("./find.js"));
9
9
 
10
- var _unescapeRefinement = _interopRequireDefault(require("./unescapeRefinement.js"));
10
+ var _escapeFacetValue = require("./escapeFacetValue.js");
11
11
 
12
12
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
13
 
@@ -16,7 +16,8 @@ function getRefinement(state, type, attribute, name) {
16
16
  var res = {
17
17
  type: type,
18
18
  attribute: attribute,
19
- name: name
19
+ name: name,
20
+ escapedValue: (0, _escapeFacetValue.escapeFacetValue)(name)
20
21
  };
21
22
  var facet = (0, _find.default)(resultsFacets, function (resultsFacet) {
22
23
  return resultsFacet.name === attribute;
@@ -50,14 +51,12 @@ function getRefinement(state, type, attribute, name) {
50
51
  count = facet && facet.data && facet.data[res.name];
51
52
  }
52
53
 
53
- var exhaustive = facet && facet.exhaustive;
54
-
55
54
  if (count !== undefined) {
56
55
  res.count = count;
57
56
  }
58
57
 
59
- if (exhaustive !== undefined) {
60
- res.exhaustive = exhaustive;
58
+ if (facet && facet.exhaustive !== undefined) {
59
+ res.exhaustive = facet.exhaustive;
61
60
  }
62
61
 
63
62
  return res;
@@ -98,9 +97,9 @@ function getRefinements(results, state) {
98
97
  Object.keys(disjunctiveFacetsRefinements).forEach(function (attribute) {
99
98
  var refinementNames = disjunctiveFacetsRefinements[attribute];
100
99
  refinementNames.forEach(function (refinementName) {
101
- refinements.push(getRefinement(state, 'disjunctive', attribute, // We unescape any disjunctive refined values with `unescapeRefinement` because
102
- // they can be escaped on negative numeric values with `escapeRefinement`.
103
- (0, _unescapeRefinement.default)(refinementName), results.disjunctiveFacets));
100
+ refinements.push(getRefinement(state, 'disjunctive', attribute, // We unescape any disjunctive refined values with `unescapeFacetValue` because
101
+ // they can be escaped on negative numeric values with `escapeFacetValue`.
102
+ (0, _escapeFacetValue.unescapeFacetValue)(refinementName), results.disjunctiveFacets));
104
103
  });
105
104
  });
106
105
  Object.keys(hierarchicalFacetsRefinements).forEach(function (attribute) {
@@ -144,7 +143,4 @@ function getRefinements(results, state) {
144
143
  }
145
144
 
146
145
  return refinements;
147
- }
148
-
149
- var _default = getRefinements;
150
- exports.default = _default;
146
+ }
@@ -13,8 +13,8 @@ var _exportNames = {
13
13
  renderTemplate: true,
14
14
  getRefinements: true,
15
15
  clearRefinements: true,
16
- escapeRefinement: true,
17
- unescapeRefinement: true,
16
+ escapeFacetValue: true,
17
+ unescapeFacetValue: true,
18
18
  checkRendering: true,
19
19
  checkIndexUiState: true,
20
20
  getPropertyByPath: true,
@@ -112,16 +112,16 @@ Object.defineProperty(exports, "clearRefinements", {
112
112
  return _clearRefinements.default;
113
113
  }
114
114
  });
115
- Object.defineProperty(exports, "escapeRefinement", {
115
+ Object.defineProperty(exports, "escapeFacetValue", {
116
116
  enumerable: true,
117
117
  get: function get() {
118
- return _escapeRefinement.default;
118
+ return _escapeFacetValue.escapeFacetValue;
119
119
  }
120
120
  });
121
- Object.defineProperty(exports, "unescapeRefinement", {
121
+ Object.defineProperty(exports, "unescapeFacetValue", {
122
122
  enumerable: true,
123
123
  get: function get() {
124
- return _unescapeRefinement.default;
124
+ return _escapeFacetValue.unescapeFacetValue;
125
125
  }
126
126
  });
127
127
  Object.defineProperty(exports, "checkRendering", {
@@ -395,9 +395,7 @@ var _getRefinements = _interopRequireDefault(require("./getRefinements.js"));
395
395
 
396
396
  var _clearRefinements = _interopRequireDefault(require("./clearRefinements.js"));
397
397
 
398
- var _escapeRefinement = _interopRequireDefault(require("./escapeRefinement.js"));
399
-
400
- var _unescapeRefinement = _interopRequireDefault(require("./unescapeRefinement.js"));
398
+ var _escapeFacetValue = require("./escapeFacetValue.js");
401
399
 
402
400
  var _checkRendering = _interopRequireDefault(require("./checkRendering.js"));
403
401
 
@@ -4,5 +4,5 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
- var _default = '4.40.2';
7
+ var _default = '4.40.5';
8
8
  exports.default = _default;
@@ -463,10 +463,9 @@ declare class BrowserHistory<TRouteState> implements Router<TRouteState> {
463
463
  private writeTimer?;
464
464
  private _onPopState;
465
465
  /**
466
- * Indicates if history.pushState should be executed.
467
- * It needs to avoid pushing state to history in case of back/forward in browser
466
+ * Indicates if last action was back/forward in the browser.
468
467
  */
469
- private shouldPushState;
468
+ private inPopState;
470
469
  /**
471
470
  * Indicates whether the history router is disposed or not.
472
471
  */
@@ -508,6 +507,7 @@ declare class BrowserHistory<TRouteState> implements Router<TRouteState> {
508
507
  * Removes the event listener and cleans up the URL.
509
508
  */
510
509
  dispose(): void;
510
+ private shouldWrite;
511
511
  }
512
512
 
513
513
  declare type BrowserHistoryArgs<TRouteState> = {