kdu-router 3.0.7 → 3.1.7

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.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * kdu-router v3.0.7
2
+ * kdu-router v3.1.7
3
3
  * (c) 2022 NKDuy
4
4
  * @license MIT
5
5
  */
@@ -21,6 +21,14 @@ function isError (err) {
21
21
  return Object.prototype.toString.call(err).indexOf('Error') > -1
22
22
  }
23
23
 
24
+ function isExtendedError (constructor, err) {
25
+ return (
26
+ err instanceof constructor ||
27
+ // _name is to support IE9 too
28
+ (err && (err.name === constructor.name || err._name === constructor._name))
29
+ )
30
+ }
31
+
24
32
  function extend (a, b) {
25
33
  for (var key in b) {
26
34
  a[key] = b[key];
@@ -58,14 +66,12 @@ var View = {
58
66
  var depth = 0;
59
67
  var inactive = false;
60
68
  while (parent && parent._routerRoot !== parent) {
61
- var knodeData = parent.$knode && parent.$knode.data;
62
- if (knodeData) {
63
- if (knodeData.routerView) {
64
- depth++;
65
- }
66
- if (knodeData.keepAlive && parent._inactive) {
67
- inactive = true;
68
- }
69
+ var knodeData = parent.$knode ? parent.$knode.data : {};
70
+ if (knodeData.routerView) {
71
+ depth++;
72
+ }
73
+ if (knodeData.keepAlive && parent._directInactive && parent._inactive) {
74
+ inactive = true;
69
75
  }
70
76
  parent = parent.$parent;
71
77
  }
@@ -73,17 +79,32 @@ var View = {
73
79
 
74
80
  // render previous view if the tree is inactive and kept-alive
75
81
  if (inactive) {
76
- return h(cache[name], data, children)
82
+ var cachedData = cache[name];
83
+ var cachedComponent = cachedData && cachedData.component;
84
+ if (cachedComponent) {
85
+ // #2301
86
+ // pass props
87
+ if (cachedData.configProps) {
88
+ fillPropsinData(cachedComponent, data, cachedData.route, cachedData.configProps);
89
+ }
90
+ return h(cachedComponent, data, children)
91
+ } else {
92
+ // render previous empty view
93
+ return h()
94
+ }
77
95
  }
78
96
 
79
97
  var matched = route.matched[depth];
80
- // render empty node if no matched route
81
- if (!matched) {
98
+ var component = matched && matched.components[name];
99
+
100
+ // render empty node if no matched route or no config component
101
+ if (!matched || !component) {
82
102
  cache[name] = null;
83
103
  return h()
84
104
  }
85
105
 
86
- var component = cache[name] = matched.components[name];
106
+ // cache component
107
+ cache[name] = { component: component };
87
108
 
88
109
  // attach instance registration hook
89
110
  // this will be called in the instance's injected lifecycle hooks
@@ -115,23 +136,35 @@ var View = {
115
136
  }
116
137
  };
117
138
 
118
- // resolve props
119
- var propsToPass = data.props = resolveProps(route, matched.props && matched.props[name]);
120
- if (propsToPass) {
121
- // clone to prevent mutation
122
- propsToPass = data.props = extend({}, propsToPass);
123
- // pass non-declared props as attrs
124
- var attrs = data.attrs = data.attrs || {};
125
- for (var key in propsToPass) {
126
- if (!component.props || !(key in component.props)) {
127
- attrs[key] = propsToPass[key];
128
- delete propsToPass[key];
129
- }
130
- }
139
+ var configProps = matched.props && matched.props[name];
140
+ // save route and configProps in cachce
141
+ if (configProps) {
142
+ extend(cache[name], {
143
+ route: route,
144
+ configProps: configProps
145
+ });
146
+ fillPropsinData(component, data, route, configProps);
131
147
  }
132
148
 
133
149
  return h(component, data, children)
134
150
  }
151
+ };
152
+
153
+ function fillPropsinData (component, data, route, configProps) {
154
+ // resolve props
155
+ var propsToPass = data.props = resolveProps(route, configProps);
156
+ if (propsToPass) {
157
+ // clone to prevent mutation
158
+ propsToPass = data.props = extend({}, propsToPass);
159
+ // pass non-declared props as attrs
160
+ var attrs = data.attrs = data.attrs || {};
161
+ for (var key in propsToPass) {
162
+ if (!component.props || !(key in component.props)) {
163
+ attrs[key] = propsToPass[key];
164
+ delete propsToPass[key];
165
+ }
166
+ }
167
+ }
135
168
  }
136
169
 
137
170
  function resolveProps (route, config) {
@@ -261,7 +294,7 @@ function createRoute (
261
294
  redirectedFrom,
262
295
  router
263
296
  ) {
264
- var stringifyQuery$$1 = router && router.options.stringifyQuery;
297
+ var stringifyQuery = router && router.options.stringifyQuery;
265
298
 
266
299
  var query = location.query || {};
267
300
  try {
@@ -275,11 +308,11 @@ function createRoute (
275
308
  hash: location.hash || '',
276
309
  query: query,
277
310
  params: location.params || {},
278
- fullPath: getFullPath(location, stringifyQuery$$1),
311
+ fullPath: getFullPath(location, stringifyQuery),
279
312
  matched: record ? formatMatch(record) : []
280
313
  };
281
314
  if (redirectedFrom) {
282
- route.redirectedFrom = getFullPath(redirectedFrom, stringifyQuery$$1);
315
+ route.redirectedFrom = getFullPath(redirectedFrom, stringifyQuery);
283
316
  }
284
317
  return Object.freeze(route)
285
318
  }
@@ -390,200 +423,6 @@ function queryIncludes (current, target) {
390
423
 
391
424
  /* */
392
425
 
393
- // work around weird flow bug
394
- var toTypes = [String, Object];
395
- var eventTypes = [String, Array];
396
-
397
- var Link = {
398
- name: 'RouterLink',
399
- props: {
400
- to: {
401
- type: toTypes,
402
- required: true
403
- },
404
- tag: {
405
- type: String,
406
- default: 'a'
407
- },
408
- exact: Boolean,
409
- append: Boolean,
410
- replace: Boolean,
411
- activeClass: String,
412
- exactActiveClass: String,
413
- event: {
414
- type: eventTypes,
415
- default: 'click'
416
- }
417
- },
418
- render: function render (h) {
419
- var this$1 = this;
420
-
421
- var router = this.$router;
422
- var current = this.$route;
423
- var ref = router.resolve(this.to, current, this.append);
424
- var location = ref.location;
425
- var route = ref.route;
426
- var href = ref.href;
427
-
428
- var classes = {};
429
- var globalActiveClass = router.options.linkActiveClass;
430
- var globalExactActiveClass = router.options.linkExactActiveClass;
431
- // Support global empty active class
432
- var activeClassFallback = globalActiveClass == null
433
- ? 'router-link-active'
434
- : globalActiveClass;
435
- var exactActiveClassFallback = globalExactActiveClass == null
436
- ? 'router-link-exact-active'
437
- : globalExactActiveClass;
438
- var activeClass = this.activeClass == null
439
- ? activeClassFallback
440
- : this.activeClass;
441
- var exactActiveClass = this.exactActiveClass == null
442
- ? exactActiveClassFallback
443
- : this.exactActiveClass;
444
- var compareTarget = location.path
445
- ? createRoute(null, location, null, router)
446
- : route;
447
-
448
- classes[exactActiveClass] = isSameRoute(current, compareTarget);
449
- classes[activeClass] = this.exact
450
- ? classes[exactActiveClass]
451
- : isIncludedRoute(current, compareTarget);
452
-
453
- var handler = function (e) {
454
- if (guardEvent(e)) {
455
- if (this$1.replace) {
456
- router.replace(location);
457
- } else {
458
- router.push(location);
459
- }
460
- }
461
- };
462
-
463
- var on = { click: guardEvent };
464
- if (Array.isArray(this.event)) {
465
- this.event.forEach(function (e) { on[e] = handler; });
466
- } else {
467
- on[this.event] = handler;
468
- }
469
-
470
- var data = {
471
- class: classes
472
- };
473
-
474
- if (this.tag === 'a') {
475
- data.on = on;
476
- data.attrs = { href: href };
477
- } else {
478
- // find the first <a> child and apply listener and href
479
- var a = findAnchor(this.$slots.default);
480
- if (a) {
481
- // in case the <a> is a static node
482
- a.isStatic = false;
483
- var aData = a.data = extend({}, a.data);
484
- aData.on = on;
485
- var aAttrs = a.data.attrs = extend({}, a.data.attrs);
486
- aAttrs.href = href;
487
- } else {
488
- // doesn't have <a> child, apply listener to self
489
- data.on = on;
490
- }
491
- }
492
-
493
- return h(this.tag, data, this.$slots.default)
494
- }
495
- }
496
-
497
- function guardEvent (e) {
498
- // don't redirect with control keys
499
- if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) { return }
500
- // don't redirect when preventDefault called
501
- if (e.defaultPrevented) { return }
502
- // don't redirect on right click
503
- if (e.button !== undefined && e.button !== 0) { return }
504
- // don't redirect if `target="_blank"`
505
- if (e.currentTarget && e.currentTarget.getAttribute) {
506
- var target = e.currentTarget.getAttribute('target');
507
- if (/\b_blank\b/i.test(target)) { return }
508
- }
509
- // this may be a Weex event which doesn't have this method
510
- if (e.preventDefault) {
511
- e.preventDefault();
512
- }
513
- return true
514
- }
515
-
516
- function findAnchor (children) {
517
- if (children) {
518
- var child;
519
- for (var i = 0; i < children.length; i++) {
520
- child = children[i];
521
- if (child.tag === 'a') {
522
- return child
523
- }
524
- if (child.children && (child = findAnchor(child.children))) {
525
- return child
526
- }
527
- }
528
- }
529
- }
530
-
531
- var _Kdu;
532
-
533
- function install (Kdu) {
534
- if (install.installed && _Kdu === Kdu) { return }
535
- install.installed = true;
536
-
537
- _Kdu = Kdu;
538
-
539
- var isDef = function (v) { return v !== undefined; };
540
-
541
- var registerInstance = function (vm, callVal) {
542
- var i = vm.$options._parentKnode;
543
- if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {
544
- i(vm, callVal);
545
- }
546
- };
547
-
548
- Kdu.mixin({
549
- beforeCreate: function beforeCreate () {
550
- if (isDef(this.$options.router)) {
551
- this._routerRoot = this;
552
- this._router = this.$options.router;
553
- this._router.init(this);
554
- Kdu.util.defineReactive(this, '_route', this._router.history.current);
555
- } else {
556
- this._routerRoot = (this.$parent && this.$parent._routerRoot) || this;
557
- }
558
- registerInstance(this, this);
559
- },
560
- destroyed: function destroyed () {
561
- registerInstance(this);
562
- }
563
- });
564
-
565
- Object.defineProperty(Kdu.prototype, '$router', {
566
- get: function get () { return this._routerRoot._router }
567
- });
568
-
569
- Object.defineProperty(Kdu.prototype, '$route', {
570
- get: function get () { return this._routerRoot._route }
571
- });
572
-
573
- Kdu.component('RouterView', View);
574
- Kdu.component('RouterLink', Link);
575
-
576
- var strats = Kdu.config.optionMergeStrategies;
577
- // use the same hook merging strategy for route hooks
578
- strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created;
579
- }
580
-
581
- /* */
582
-
583
- var inBrowser = typeof window !== 'undefined';
584
-
585
- /* */
586
-
587
426
  function resolvePath (
588
427
  relative,
589
428
  base,
@@ -1069,53 +908,361 @@ function pathToRegexp (path, keys, options) {
1069
908
  keys = [];
1070
909
  }
1071
910
 
1072
- options = options || {};
911
+ options = options || {};
912
+
913
+ if (path instanceof RegExp) {
914
+ return regexpToRegexp(path, /** @type {!Array} */ (keys))
915
+ }
916
+
917
+ if (isarray(path)) {
918
+ return arrayToRegexp(/** @type {!Array} */ (path), /** @type {!Array} */ (keys), options)
919
+ }
920
+
921
+ return stringToRegexp(/** @type {string} */ (path), /** @type {!Array} */ (keys), options)
922
+ }
923
+ pathToRegexp_1.parse = parse_1;
924
+ pathToRegexp_1.compile = compile_1;
925
+ pathToRegexp_1.tokensToFunction = tokensToFunction_1;
926
+ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
927
+
928
+ /* */
929
+
930
+ // $flow-disable-line
931
+ var regexpCompileCache = Object.create(null);
932
+
933
+ function fillParams (
934
+ path,
935
+ params,
936
+ routeMsg
937
+ ) {
938
+ params = params || {};
939
+ try {
940
+ var filler =
941
+ regexpCompileCache[path] ||
942
+ (regexpCompileCache[path] = pathToRegexp_1.compile(path));
943
+
944
+ // Fix #2505 resolving asterisk routes { name: 'not-found', params: { pathMatch: '/not-found' }}
945
+ // and fix #3106 so that you can work with location descriptor object having params.pathMatch equal to empty string
946
+ if (typeof params.pathMatch === 'string') { params[0] = params.pathMatch; }
947
+
948
+ return filler(params, { pretty: true })
949
+ } catch (e) {
950
+ if (process.env.NODE_ENV !== 'production') {
951
+ // Fix #3072 no warn if `pathMatch` is string
952
+ warn(typeof params.pathMatch === 'string', ("missing param for " + routeMsg + ": " + (e.message)));
953
+ }
954
+ return ''
955
+ } finally {
956
+ // delete the 0 if it was added
957
+ delete params[0];
958
+ }
959
+ }
960
+
961
+ /* */
962
+
963
+ function normalizeLocation (
964
+ raw,
965
+ current,
966
+ append,
967
+ router
968
+ ) {
969
+ var next = typeof raw === 'string' ? { path: raw } : raw;
970
+ // named target
971
+ if (next._normalized) {
972
+ return next
973
+ } else if (next.name) {
974
+ next = extend({}, raw);
975
+ var params = next.params;
976
+ if (params && typeof params === 'object') {
977
+ next.params = extend({}, params);
978
+ }
979
+ return next
980
+ }
981
+
982
+ // relative params
983
+ if (!next.path && next.params && current) {
984
+ next = extend({}, next);
985
+ next._normalized = true;
986
+ var params$1 = extend(extend({}, current.params), next.params);
987
+ if (current.name) {
988
+ next.name = current.name;
989
+ next.params = params$1;
990
+ } else if (current.matched.length) {
991
+ var rawPath = current.matched[current.matched.length - 1].path;
992
+ next.path = fillParams(rawPath, params$1, ("path " + (current.path)));
993
+ } else if (process.env.NODE_ENV !== 'production') {
994
+ warn(false, "relative params navigation requires a current route.");
995
+ }
996
+ return next
997
+ }
998
+
999
+ var parsedPath = parsePath(next.path || '');
1000
+ var basePath = (current && current.path) || '/';
1001
+ var path = parsedPath.path
1002
+ ? resolvePath(parsedPath.path, basePath, append || next.append)
1003
+ : basePath;
1004
+
1005
+ var query = resolveQuery(
1006
+ parsedPath.query,
1007
+ next.query,
1008
+ router && router.options.parseQuery
1009
+ );
1010
+
1011
+ var hash = next.hash || parsedPath.hash;
1012
+ if (hash && hash.charAt(0) !== '#') {
1013
+ hash = "#" + hash;
1014
+ }
1015
+
1016
+ return {
1017
+ _normalized: true,
1018
+ path: path,
1019
+ query: query,
1020
+ hash: hash
1021
+ }
1022
+ }
1023
+
1024
+ /* */
1025
+
1026
+ // work around weird flow bug
1027
+ var toTypes = [String, Object];
1028
+ var eventTypes = [String, Array];
1029
+
1030
+ var noop = function () {};
1031
+
1032
+ var Link = {
1033
+ name: 'RouterLink',
1034
+ props: {
1035
+ to: {
1036
+ type: toTypes,
1037
+ required: true
1038
+ },
1039
+ tag: {
1040
+ type: String,
1041
+ default: 'a'
1042
+ },
1043
+ exact: Boolean,
1044
+ append: Boolean,
1045
+ replace: Boolean,
1046
+ activeClass: String,
1047
+ exactActiveClass: String,
1048
+ event: {
1049
+ type: eventTypes,
1050
+ default: 'click'
1051
+ }
1052
+ },
1053
+ render: function render (h) {
1054
+ var this$1 = this;
1055
+
1056
+ var router = this.$router;
1057
+ var current = this.$route;
1058
+ var ref = router.resolve(
1059
+ this.to,
1060
+ current,
1061
+ this.append
1062
+ );
1063
+ var location = ref.location;
1064
+ var route = ref.route;
1065
+ var href = ref.href;
1066
+
1067
+ var classes = {};
1068
+ var globalActiveClass = router.options.linkActiveClass;
1069
+ var globalExactActiveClass = router.options.linkExactActiveClass;
1070
+ // Support global empty active class
1071
+ var activeClassFallback =
1072
+ globalActiveClass == null ? 'router-link-active' : globalActiveClass;
1073
+ var exactActiveClassFallback =
1074
+ globalExactActiveClass == null
1075
+ ? 'router-link-exact-active'
1076
+ : globalExactActiveClass;
1077
+ var activeClass =
1078
+ this.activeClass == null ? activeClassFallback : this.activeClass;
1079
+ var exactActiveClass =
1080
+ this.exactActiveClass == null
1081
+ ? exactActiveClassFallback
1082
+ : this.exactActiveClass;
1083
+
1084
+ var compareTarget = route.redirectedFrom
1085
+ ? createRoute(null, normalizeLocation(route.redirectedFrom), null, router)
1086
+ : route;
1087
+
1088
+ classes[exactActiveClass] = isSameRoute(current, compareTarget);
1089
+ classes[activeClass] = this.exact
1090
+ ? classes[exactActiveClass]
1091
+ : isIncludedRoute(current, compareTarget);
1092
+
1093
+ var handler = function (e) {
1094
+ if (guardEvent(e)) {
1095
+ if (this$1.replace) {
1096
+ router.replace(location, noop);
1097
+ } else {
1098
+ router.push(location, noop);
1099
+ }
1100
+ }
1101
+ };
1102
+
1103
+ var on = { click: guardEvent };
1104
+ if (Array.isArray(this.event)) {
1105
+ this.event.forEach(function (e) {
1106
+ on[e] = handler;
1107
+ });
1108
+ } else {
1109
+ on[this.event] = handler;
1110
+ }
1111
+
1112
+ var data = { class: classes };
1113
+
1114
+ var scopedSlot =
1115
+ !this.$scopedSlots.$hasNormal &&
1116
+ this.$scopedSlots.default &&
1117
+ this.$scopedSlots.default({
1118
+ href: href,
1119
+ route: route,
1120
+ navigate: handler,
1121
+ isActive: classes[activeClass],
1122
+ isExactActive: classes[exactActiveClass]
1123
+ });
1124
+
1125
+ if (scopedSlot) {
1126
+ if (scopedSlot.length === 1) {
1127
+ return scopedSlot[0]
1128
+ } else if (scopedSlot.length > 1 || !scopedSlot.length) {
1129
+ if (process.env.NODE_ENV !== 'production') {
1130
+ warn(
1131
+ false,
1132
+ ("RouterLink with to=\"" + (this.to) + "\" is trying to use a scoped slot but it didn't provide exactly one child. Wrapping the content with a span element.")
1133
+ );
1134
+ }
1135
+ return scopedSlot.length === 0 ? h() : h('span', {}, scopedSlot)
1136
+ }
1137
+ }
1138
+
1139
+ if (this.tag === 'a') {
1140
+ data.on = on;
1141
+ data.attrs = { href: href };
1142
+ } else {
1143
+ // find the first <a> child and apply listener and href
1144
+ var a = findAnchor(this.$slots.default);
1145
+ if (a) {
1146
+ // in case the <a> is a static node
1147
+ a.isStatic = false;
1148
+ var aData = (a.data = extend({}, a.data));
1149
+ aData.on = aData.on || {};
1150
+ // transform existing events in both objects into arrays so we can push later
1151
+ for (var event in aData.on) {
1152
+ var handler$1 = aData.on[event];
1153
+ if (event in on) {
1154
+ aData.on[event] = Array.isArray(handler$1) ? handler$1 : [handler$1];
1155
+ }
1156
+ }
1157
+ // append new listeners for router-link
1158
+ for (var event$1 in on) {
1159
+ if (event$1 in aData.on) {
1160
+ // on[event] is always a function
1161
+ aData.on[event$1].push(on[event$1]);
1162
+ } else {
1163
+ aData.on[event$1] = handler;
1164
+ }
1165
+ }
1166
+
1167
+ var aAttrs = (a.data.attrs = extend({}, a.data.attrs));
1168
+ aAttrs.href = href;
1169
+ } else {
1170
+ // doesn't have <a> child, apply listener to self
1171
+ data.on = on;
1172
+ }
1173
+ }
1174
+
1175
+ return h(this.tag, data, this.$slots.default)
1176
+ }
1177
+ };
1178
+
1179
+ function guardEvent (e) {
1180
+ // don't redirect with control keys
1181
+ if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) { return }
1182
+ // don't redirect when preventDefault called
1183
+ if (e.defaultPrevented) { return }
1184
+ // don't redirect on right click
1185
+ if (e.button !== undefined && e.button !== 0) { return }
1186
+ // don't redirect if `target="_blank"`
1187
+ if (e.currentTarget && e.currentTarget.getAttribute) {
1188
+ var target = e.currentTarget.getAttribute('target');
1189
+ if (/\b_blank\b/i.test(target)) { return }
1190
+ }
1191
+ // this may be a Weex event which doesn't have this method
1192
+ if (e.preventDefault) {
1193
+ e.preventDefault();
1194
+ }
1195
+ return true
1196
+ }
1197
+
1198
+ function findAnchor (children) {
1199
+ if (children) {
1200
+ var child;
1201
+ for (var i = 0; i < children.length; i++) {
1202
+ child = children[i];
1203
+ if (child.tag === 'a') {
1204
+ return child
1205
+ }
1206
+ if (child.children && (child = findAnchor(child.children))) {
1207
+ return child
1208
+ }
1209
+ }
1210
+ }
1211
+ }
1212
+
1213
+ var _Kdu;
1214
+
1215
+ function install (Kdu) {
1216
+ if (install.installed && _Kdu === Kdu) { return }
1217
+ install.installed = true;
1218
+
1219
+ _Kdu = Kdu;
1220
+
1221
+ var isDef = function (v) { return v !== undefined; };
1222
+
1223
+ var registerInstance = function (vm, callVal) {
1224
+ var i = vm.$options._parentKnode;
1225
+ if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {
1226
+ i(vm, callVal);
1227
+ }
1228
+ };
1229
+
1230
+ Kdu.mixin({
1231
+ beforeCreate: function beforeCreate () {
1232
+ if (isDef(this.$options.router)) {
1233
+ this._routerRoot = this;
1234
+ this._router = this.$options.router;
1235
+ this._router.init(this);
1236
+ Kdu.util.defineReactive(this, '_route', this._router.history.current);
1237
+ } else {
1238
+ this._routerRoot = (this.$parent && this.$parent._routerRoot) || this;
1239
+ }
1240
+ registerInstance(this, this);
1241
+ },
1242
+ destroyed: function destroyed () {
1243
+ registerInstance(this);
1244
+ }
1245
+ });
1246
+
1247
+ Object.defineProperty(Kdu.prototype, '$router', {
1248
+ get: function get () { return this._routerRoot._router }
1249
+ });
1073
1250
 
1074
- if (path instanceof RegExp) {
1075
- return regexpToRegexp(path, /** @type {!Array} */ (keys))
1076
- }
1251
+ Object.defineProperty(Kdu.prototype, '$route', {
1252
+ get: function get () { return this._routerRoot._route }
1253
+ });
1077
1254
 
1078
- if (isarray(path)) {
1079
- return arrayToRegexp(/** @type {!Array} */ (path), /** @type {!Array} */ (keys), options)
1080
- }
1255
+ Kdu.component('RouterView', View);
1256
+ Kdu.component('RouterLink', Link);
1081
1257
 
1082
- return stringToRegexp(/** @type {string} */ (path), /** @type {!Array} */ (keys), options)
1258
+ var strats = Kdu.config.optionMergeStrategies;
1259
+ // use the same hook merging strategy for route hooks
1260
+ strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created;
1083
1261
  }
1084
- pathToRegexp_1.parse = parse_1;
1085
- pathToRegexp_1.compile = compile_1;
1086
- pathToRegexp_1.tokensToFunction = tokensToFunction_1;
1087
- pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
1088
1262
 
1089
1263
  /* */
1090
1264
 
1091
- // $flow-disable-line
1092
- var regexpCompileCache = Object.create(null);
1093
-
1094
- function fillParams (
1095
- path,
1096
- params,
1097
- routeMsg
1098
- ) {
1099
- params = params || {};
1100
- try {
1101
- var filler =
1102
- regexpCompileCache[path] ||
1103
- (regexpCompileCache[path] = pathToRegexp_1.compile(path));
1104
-
1105
- // Fix #2505 resolving asterisk routes { name: 'not-found', params: { pathMatch: '/not-found' }}
1106
- if (params.pathMatch) { params[0] = params.pathMatch; }
1107
-
1108
- return filler(params, { pretty: true })
1109
- } catch (e) {
1110
- if (process.env.NODE_ENV !== 'production') {
1111
- warn(false, ("missing param for " + routeMsg + ": " + (e.message)));
1112
- }
1113
- return ''
1114
- } finally {
1115
- // delete the 0 if it was added
1116
- delete params[0];
1117
- }
1118
- }
1265
+ var inBrowser = typeof window !== 'undefined';
1119
1266
 
1120
1267
  /* */
1121
1268
 
@@ -1145,6 +1292,18 @@ function createRouteMap (
1145
1292
  }
1146
1293
  }
1147
1294
 
1295
+ if (process.env.NODE_ENV === 'development') {
1296
+ // warn if routes do not include leading slashes
1297
+ var found = pathList
1298
+ // check for missing leading slash
1299
+ .filter(function (path) { return path && path.charAt(0) !== '*' && path.charAt(0) !== '/'; });
1300
+
1301
+ if (found.length > 0) {
1302
+ var pathNames = found.map(function (path) { return ("- " + path); }).join('\n');
1303
+ warn(false, ("Non-nested routes must include a leading slash character. Fix the following routes: \n" + pathNames));
1304
+ }
1305
+ }
1306
+
1148
1307
  return {
1149
1308
  pathList: pathList,
1150
1309
  pathMap: pathMap,
@@ -1166,17 +1325,15 @@ function addRouteRecord (
1166
1325
  assert(path != null, "\"path\" is required in a route configuration.");
1167
1326
  assert(
1168
1327
  typeof route.component !== 'string',
1169
- "route config \"component\" for path: " + (String(path || name)) + " cannot be a " +
1170
- "string id. Use an actual component instead."
1328
+ "route config \"component\" for path: " + (String(
1329
+ path || name
1330
+ )) + " cannot be a " + "string id. Use an actual component instead."
1171
1331
  );
1172
1332
  }
1173
1333
 
1174
- var pathToRegexpOptions = route.pathToRegexpOptions || {};
1175
- var normalizedPath = normalizePath(
1176
- path,
1177
- parent,
1178
- pathToRegexpOptions.strict
1179
- );
1334
+ var pathToRegexpOptions =
1335
+ route.pathToRegexpOptions || {};
1336
+ var normalizedPath = normalizePath(path, parent, pathToRegexpOptions.strict);
1180
1337
 
1181
1338
  if (typeof route.caseSensitive === 'boolean') {
1182
1339
  pathToRegexpOptions.sensitive = route.caseSensitive;
@@ -1193,11 +1350,12 @@ function addRouteRecord (
1193
1350
  redirect: route.redirect,
1194
1351
  beforeEnter: route.beforeEnter,
1195
1352
  meta: route.meta || {},
1196
- props: route.props == null
1197
- ? {}
1198
- : route.components
1199
- ? route.props
1200
- : { default: route.props }
1353
+ props:
1354
+ route.props == null
1355
+ ? {}
1356
+ : route.components
1357
+ ? route.props
1358
+ : { default: route.props }
1201
1359
  };
1202
1360
 
1203
1361
  if (route.children) {
@@ -1205,14 +1363,18 @@ function addRouteRecord (
1205
1363
  // If users navigate to this route by name, the default child will
1206
1364
  // not be rendered (GH Issue #629)
1207
1365
  if (process.env.NODE_ENV !== 'production') {
1208
- if (route.name && !route.redirect && route.children.some(function (child) { return /^\/?$/.test(child.path); })) {
1366
+ if (
1367
+ route.name &&
1368
+ !route.redirect &&
1369
+ route.children.some(function (child) { return /^\/?$/.test(child.path); })
1370
+ ) {
1209
1371
  warn(
1210
1372
  false,
1211
1373
  "Named Route '" + (route.name) + "' has a default child route. " +
1212
- "When navigating to this named route (:to=\"{name: '" + (route.name) + "'\"), " +
1213
- "the default child route will not be rendered. Remove the name from " +
1214
- "this route and use the name of the default child route for named " +
1215
- "links instead."
1374
+ "When navigating to this named route (:to=\"{name: '" + (route.name) + "'\"), " +
1375
+ "the default child route will not be rendered. Remove the name from " +
1376
+ "this route and use the name of the default child route for named " +
1377
+ "links instead."
1216
1378
  );
1217
1379
  }
1218
1380
  }
@@ -1224,12 +1386,24 @@ function addRouteRecord (
1224
1386
  });
1225
1387
  }
1226
1388
 
1389
+ if (!pathMap[record.path]) {
1390
+ pathList.push(record.path);
1391
+ pathMap[record.path] = record;
1392
+ }
1393
+
1227
1394
  if (route.alias !== undefined) {
1228
- var aliases = Array.isArray(route.alias)
1229
- ? route.alias
1230
- : [route.alias];
1395
+ var aliases = Array.isArray(route.alias) ? route.alias : [route.alias];
1396
+ for (var i = 0; i < aliases.length; ++i) {
1397
+ var alias = aliases[i];
1398
+ if (process.env.NODE_ENV !== 'production' && alias === path) {
1399
+ warn(
1400
+ false,
1401
+ ("Found an alias with the same value as the path: \"" + path + "\". You have to remove that alias. It will be ignored in development.")
1402
+ );
1403
+ // skip in dev to make it work
1404
+ continue
1405
+ }
1231
1406
 
1232
- aliases.forEach(function (alias) {
1233
1407
  var aliasRoute = {
1234
1408
  path: alias,
1235
1409
  children: route.children
@@ -1242,12 +1416,7 @@ function addRouteRecord (
1242
1416
  parent,
1243
1417
  record.path || '/' // matchAs
1244
1418
  );
1245
- });
1246
- }
1247
-
1248
- if (!pathMap[record.path]) {
1249
- pathList.push(record.path);
1250
- pathMap[record.path] = record;
1419
+ }
1251
1420
  }
1252
1421
 
1253
1422
  if (name) {
@@ -1257,25 +1426,35 @@ function addRouteRecord (
1257
1426
  warn(
1258
1427
  false,
1259
1428
  "Duplicate named routes definition: " +
1260
- "{ name: \"" + name + "\", path: \"" + (record.path) + "\" }"
1429
+ "{ name: \"" + name + "\", path: \"" + (record.path) + "\" }"
1261
1430
  );
1262
1431
  }
1263
1432
  }
1264
1433
  }
1265
1434
 
1266
- function compileRouteRegex (path, pathToRegexpOptions) {
1435
+ function compileRouteRegex (
1436
+ path,
1437
+ pathToRegexpOptions
1438
+ ) {
1267
1439
  var regex = pathToRegexp_1(path, [], pathToRegexpOptions);
1268
1440
  if (process.env.NODE_ENV !== 'production') {
1269
1441
  var keys = Object.create(null);
1270
1442
  regex.keys.forEach(function (key) {
1271
- warn(!keys[key.name], ("Duplicate param keys in route with path: \"" + path + "\""));
1443
+ warn(
1444
+ !keys[key.name],
1445
+ ("Duplicate param keys in route with path: \"" + path + "\"")
1446
+ );
1272
1447
  keys[key.name] = true;
1273
1448
  });
1274
1449
  }
1275
1450
  return regex
1276
1451
  }
1277
1452
 
1278
- function normalizePath (path, parent, strict) {
1453
+ function normalizePath (
1454
+ path,
1455
+ parent,
1456
+ strict
1457
+ ) {
1279
1458
  if (!strict) { path = path.replace(/\/$/, ''); }
1280
1459
  if (path[0] === '/') { return path }
1281
1460
  if (parent == null) { return path }
@@ -1284,64 +1463,6 @@ function normalizePath (path, parent, strict) {
1284
1463
 
1285
1464
  /* */
1286
1465
 
1287
- function normalizeLocation (
1288
- raw,
1289
- current,
1290
- append,
1291
- router
1292
- ) {
1293
- var next = typeof raw === 'string' ? { path: raw } : raw;
1294
- // named target
1295
- if (next._normalized) {
1296
- return next
1297
- } else if (next.name) {
1298
- return extend({}, raw)
1299
- }
1300
-
1301
- // relative params
1302
- if (!next.path && next.params && current) {
1303
- next = extend({}, next);
1304
- next._normalized = true;
1305
- var params = extend(extend({}, current.params), next.params);
1306
- if (current.name) {
1307
- next.name = current.name;
1308
- next.params = params;
1309
- } else if (current.matched.length) {
1310
- var rawPath = current.matched[current.matched.length - 1].path;
1311
- next.path = fillParams(rawPath, params, ("path " + (current.path)));
1312
- } else if (process.env.NODE_ENV !== 'production') {
1313
- warn(false, "relative params navigation requires a current route.");
1314
- }
1315
- return next
1316
- }
1317
-
1318
- var parsedPath = parsePath(next.path || '');
1319
- var basePath = (current && current.path) || '/';
1320
- var path = parsedPath.path
1321
- ? resolvePath(parsedPath.path, basePath, append || next.append)
1322
- : basePath;
1323
-
1324
- var query = resolveQuery(
1325
- parsedPath.query,
1326
- next.query,
1327
- router && router.options.parseQuery
1328
- );
1329
-
1330
- var hash = next.hash || parsedPath.hash;
1331
- if (hash && hash.charAt(0) !== '#') {
1332
- hash = "#" + hash;
1333
- }
1334
-
1335
- return {
1336
- _normalized: true,
1337
- path: path,
1338
- query: query,
1339
- hash: hash
1340
- }
1341
- }
1342
-
1343
- /* */
1344
-
1345
1466
 
1346
1467
 
1347
1468
  function createMatcher (
@@ -1538,6 +1659,28 @@ function resolveRecordPath (path, record) {
1538
1659
 
1539
1660
  /* */
1540
1661
 
1662
+ // use User Timing api (if present) for more accurate key precision
1663
+ var Time =
1664
+ inBrowser && window.performance && window.performance.now
1665
+ ? window.performance
1666
+ : Date;
1667
+
1668
+ function genStateKey () {
1669
+ return Time.now().toFixed(3)
1670
+ }
1671
+
1672
+ var _key = genStateKey();
1673
+
1674
+ function getStateKey () {
1675
+ return _key
1676
+ }
1677
+
1678
+ function setStateKey (key) {
1679
+ return (_key = key)
1680
+ }
1681
+
1682
+ /* */
1683
+
1541
1684
  var positionStore = Object.create(null);
1542
1685
 
1543
1686
  function setupScroll () {
@@ -1548,7 +1691,10 @@ function setupScroll () {
1548
1691
  // location.host contains the port and location.hostname doesn't
1549
1692
  var protocolAndPath = window.location.protocol + '//' + window.location.host;
1550
1693
  var absolutePath = window.location.href.replace(protocolAndPath, '');
1551
- window.history.replaceState({ key: getStateKey() }, '', absolutePath);
1694
+ // preserve existing history state as it could be overriden by the user
1695
+ var stateCopy = extend({}, window.history.state);
1696
+ stateCopy.key = getStateKey();
1697
+ window.history.replaceState(stateCopy, '', absolutePath);
1552
1698
  window.addEventListener('popstate', function (e) {
1553
1699
  saveScrollPosition();
1554
1700
  if (e.state && e.state.key) {
@@ -1579,20 +1725,27 @@ function handleScroll (
1579
1725
  // wait until re-render finishes before scrolling
1580
1726
  router.app.$nextTick(function () {
1581
1727
  var position = getScrollPosition();
1582
- var shouldScroll = behavior.call(router, to, from, isPop ? position : null);
1728
+ var shouldScroll = behavior.call(
1729
+ router,
1730
+ to,
1731
+ from,
1732
+ isPop ? position : null
1733
+ );
1583
1734
 
1584
1735
  if (!shouldScroll) {
1585
1736
  return
1586
1737
  }
1587
1738
 
1588
1739
  if (typeof shouldScroll.then === 'function') {
1589
- shouldScroll.then(function (shouldScroll) {
1590
- scrollToPosition((shouldScroll), position);
1591
- }).catch(function (err) {
1592
- if (process.env.NODE_ENV !== 'production') {
1593
- assert(false, err.toString());
1594
- }
1595
- });
1740
+ shouldScroll
1741
+ .then(function (shouldScroll) {
1742
+ scrollToPosition((shouldScroll), position);
1743
+ })
1744
+ .catch(function (err) {
1745
+ if (process.env.NODE_ENV !== 'production') {
1746
+ assert(false, err.toString());
1747
+ }
1748
+ });
1596
1749
  } else {
1597
1750
  scrollToPosition(shouldScroll, position);
1598
1751
  }
@@ -1648,12 +1801,22 @@ function isNumber (v) {
1648
1801
  return typeof v === 'number'
1649
1802
  }
1650
1803
 
1804
+ var hashStartsWithNumberRE = /^#\d/;
1805
+
1651
1806
  function scrollToPosition (shouldScroll, position) {
1652
1807
  var isObject = typeof shouldScroll === 'object';
1653
1808
  if (isObject && typeof shouldScroll.selector === 'string') {
1654
- var el = document.querySelector(shouldScroll.selector);
1809
+ // getElementById would still fail if the selector contains a more complicated query like #main[data-attr]
1810
+ // but at the same time, it doesn't make much sense to select an element with an id and an extra selector
1811
+ var el = hashStartsWithNumberRE.test(shouldScroll.selector) // $flow-disable-line
1812
+ ? document.getElementById(shouldScroll.selector.slice(1)) // $flow-disable-line
1813
+ : document.querySelector(shouldScroll.selector);
1814
+
1655
1815
  if (el) {
1656
- var offset = shouldScroll.offset && typeof shouldScroll.offset === 'object' ? shouldScroll.offset : {};
1816
+ var offset =
1817
+ shouldScroll.offset && typeof shouldScroll.offset === 'object'
1818
+ ? shouldScroll.offset
1819
+ : {};
1657
1820
  offset = normalizeOffset(offset);
1658
1821
  position = getElementPosition(el, offset);
1659
1822
  } else if (isValidPosition(shouldScroll)) {
@@ -1670,39 +1833,22 @@ function scrollToPosition (shouldScroll, position) {
1670
1833
 
1671
1834
  /* */
1672
1835
 
1673
- var supportsPushState = inBrowser && (function () {
1674
- var ua = window.navigator.userAgent;
1675
-
1676
- if (
1677
- (ua.indexOf('Android 2.') !== -1 || ua.indexOf('Android 4.0') !== -1) &&
1678
- ua.indexOf('Mobile Safari') !== -1 &&
1679
- ua.indexOf('Chrome') === -1 &&
1680
- ua.indexOf('Windows Phone') === -1
1681
- ) {
1682
- return false
1683
- }
1684
-
1685
- return window.history && 'pushState' in window.history
1686
- })();
1687
-
1688
- // use User Timing api (if present) for more accurate key precision
1689
- var Time = inBrowser && window.performance && window.performance.now
1690
- ? window.performance
1691
- : Date;
1692
-
1693
- var _key = genKey();
1694
-
1695
- function genKey () {
1696
- return Time.now().toFixed(3)
1697
- }
1698
-
1699
- function getStateKey () {
1700
- return _key
1701
- }
1836
+ var supportsPushState =
1837
+ inBrowser &&
1838
+ (function () {
1839
+ var ua = window.navigator.userAgent;
1840
+
1841
+ if (
1842
+ (ua.indexOf('Android 2.') !== -1 || ua.indexOf('Android 4.0') !== -1) &&
1843
+ ua.indexOf('Mobile Safari') !== -1 &&
1844
+ ua.indexOf('Chrome') === -1 &&
1845
+ ua.indexOf('Windows Phone') === -1
1846
+ ) {
1847
+ return false
1848
+ }
1702
1849
 
1703
- function setStateKey (key) {
1704
- _key = key;
1705
- }
1850
+ return window.history && 'pushState' in window.history
1851
+ })();
1706
1852
 
1707
1853
  function pushState (url, replace) {
1708
1854
  saveScrollPosition();
@@ -1711,10 +1857,12 @@ function pushState (url, replace) {
1711
1857
  var history = window.history;
1712
1858
  try {
1713
1859
  if (replace) {
1714
- history.replaceState({ key: _key }, '', url);
1860
+ // preserve existing history state as it could be overriden by the user
1861
+ var stateCopy = extend({}, history.state);
1862
+ stateCopy.key = getStateKey();
1863
+ history.replaceState(stateCopy, '', url);
1715
1864
  } else {
1716
- _key = genKey();
1717
- history.pushState({ key: _key }, '', url);
1865
+ history.pushState({ key: setStateKey(genStateKey()) }, '', url);
1718
1866
  }
1719
1867
  } catch (e) {
1720
1868
  window.location[replace ? 'replace' : 'assign'](url);
@@ -1853,6 +2001,33 @@ function once (fn) {
1853
2001
  }
1854
2002
  }
1855
2003
 
2004
+ var NavigationDuplicated = /*@__PURE__*/(function (Error) {
2005
+ function NavigationDuplicated (normalizedLocation) {
2006
+ Error.call(this);
2007
+ this.name = this._name = 'NavigationDuplicated';
2008
+ // passing the message to super() doesn't seem to work in the transpiled version
2009
+ this.message = "Navigating to current location (\"" + (normalizedLocation.fullPath) + "\") is not allowed";
2010
+ // add a stack property so services like Sentry can correctly display it
2011
+ Object.defineProperty(this, 'stack', {
2012
+ value: new Error().stack,
2013
+ writable: true,
2014
+ configurable: true
2015
+ });
2016
+ // we could also have used
2017
+ // Error.captureStackTrace(this, this.constructor)
2018
+ // but it only exists on node and chrome
2019
+ }
2020
+
2021
+ if ( Error ) NavigationDuplicated.__proto__ = Error;
2022
+ NavigationDuplicated.prototype = Object.create( Error && Error.prototype );
2023
+ NavigationDuplicated.prototype.constructor = NavigationDuplicated;
2024
+
2025
+ return NavigationDuplicated;
2026
+ }(Error));
2027
+
2028
+ // support IE9
2029
+ NavigationDuplicated._name = 'NavigationDuplicated';
2030
+
1856
2031
  /* */
1857
2032
 
1858
2033
  var History = function History (router, base) {
@@ -1886,29 +2061,41 @@ History.prototype.onError = function onError (errorCb) {
1886
2061
  this.errorCbs.push(errorCb);
1887
2062
  };
1888
2063
 
1889
- History.prototype.transitionTo = function transitionTo (location, onComplete, onAbort) {
2064
+ History.prototype.transitionTo = function transitionTo (
2065
+ location,
2066
+ onComplete,
2067
+ onAbort
2068
+ ) {
1890
2069
  var this$1 = this;
1891
2070
 
1892
2071
  var route = this.router.match(location, this.current);
1893
- this.confirmTransition(route, function () {
1894
- this$1.updateRoute(route);
1895
- onComplete && onComplete(route);
1896
- this$1.ensureURL();
2072
+ this.confirmTransition(
2073
+ route,
2074
+ function () {
2075
+ this$1.updateRoute(route);
2076
+ onComplete && onComplete(route);
2077
+ this$1.ensureURL();
1897
2078
 
1898
- // fire ready cbs once
1899
- if (!this$1.ready) {
1900
- this$1.ready = true;
1901
- this$1.readyCbs.forEach(function (cb) { cb(route); });
1902
- }
1903
- }, function (err) {
1904
- if (onAbort) {
1905
- onAbort(err);
1906
- }
1907
- if (err && !this$1.ready) {
1908
- this$1.ready = true;
1909
- this$1.readyErrorCbs.forEach(function (cb) { cb(err); });
2079
+ // fire ready cbs once
2080
+ if (!this$1.ready) {
2081
+ this$1.ready = true;
2082
+ this$1.readyCbs.forEach(function (cb) {
2083
+ cb(route);
2084
+ });
2085
+ }
2086
+ },
2087
+ function (err) {
2088
+ if (onAbort) {
2089
+ onAbort(err);
2090
+ }
2091
+ if (err && !this$1.ready) {
2092
+ this$1.ready = true;
2093
+ this$1.readyErrorCbs.forEach(function (cb) {
2094
+ cb(err);
2095
+ });
2096
+ }
1910
2097
  }
1911
- });
2098
+ );
1912
2099
  };
1913
2100
 
1914
2101
  History.prototype.confirmTransition = function confirmTransition (route, onComplete, onAbort) {
@@ -1916,9 +2103,14 @@ History.prototype.confirmTransition = function confirmTransition (route, onCompl
1916
2103
 
1917
2104
  var current = this.current;
1918
2105
  var abort = function (err) {
1919
- if (isError(err)) {
2106
+ // When the user navigates through history through back/forward buttons
2107
+ // we do not want to throw the error. We only throw it if directly calling
2108
+ // push/replace. That's why it's not included in isError
2109
+ if (!isExtendedError(NavigationDuplicated, err) && isError(err)) {
1920
2110
  if (this$1.errorCbs.length) {
1921
- this$1.errorCbs.forEach(function (cb) { cb(err); });
2111
+ this$1.errorCbs.forEach(function (cb) {
2112
+ cb(err);
2113
+ });
1922
2114
  } else {
1923
2115
  warn(false, 'uncaught error during route navigation:');
1924
2116
  console.error(err);
@@ -1932,10 +2124,13 @@ History.prototype.confirmTransition = function confirmTransition (route, onCompl
1932
2124
  route.matched.length === current.matched.length
1933
2125
  ) {
1934
2126
  this.ensureURL();
1935
- return abort()
2127
+ return abort(new NavigationDuplicated(route))
1936
2128
  }
1937
2129
 
1938
- var ref = resolveQueue(this.current.matched, route.matched);
2130
+ var ref = resolveQueue(
2131
+ this.current.matched,
2132
+ route.matched
2133
+ );
1939
2134
  var updated = ref.updated;
1940
2135
  var deactivated = ref.deactivated;
1941
2136
  var activated = ref.activated;
@@ -1966,10 +2161,8 @@ History.prototype.confirmTransition = function confirmTransition (route, onCompl
1966
2161
  abort(to);
1967
2162
  } else if (
1968
2163
  typeof to === 'string' ||
1969
- (typeof to === 'object' && (
1970
- typeof to.path === 'string' ||
1971
- typeof to.name === 'string'
1972
- ))
2164
+ (typeof to === 'object' &&
2165
+ (typeof to.path === 'string' || typeof to.name === 'string'))
1973
2166
  ) {
1974
2167
  // next('/') or next({ path: '/' }) -> redirect
1975
2168
  abort();
@@ -2003,7 +2196,9 @@ History.prototype.confirmTransition = function confirmTransition (route, onCompl
2003
2196
  onComplete(route);
2004
2197
  if (this$1.router.app) {
2005
2198
  this$1.router.app.$nextTick(function () {
2006
- postEnterCbs.forEach(function (cb) { cb(); });
2199
+ postEnterCbs.forEach(function (cb) {
2200
+ cb();
2201
+ });
2007
2202
  });
2008
2203
  }
2009
2204
  });
@@ -2106,9 +2301,13 @@ function extractEnterGuards (
2106
2301
  cbs,
2107
2302
  isValid
2108
2303
  ) {
2109
- return extractGuards(activated, 'beforeRouteEnter', function (guard, _, match, key) {
2110
- return bindEnterGuard(guard, match, key, cbs, isValid)
2111
- })
2304
+ return extractGuards(
2305
+ activated,
2306
+ 'beforeRouteEnter',
2307
+ function (guard, _, match, key) {
2308
+ return bindEnterGuard(guard, match, key, cbs, isValid)
2309
+ }
2310
+ )
2112
2311
  }
2113
2312
 
2114
2313
  function bindEnterGuard (
@@ -2155,11 +2354,11 @@ function poll (
2155
2354
 
2156
2355
  /* */
2157
2356
 
2158
- var HTML5History = /*@__PURE__*/(function (History$$1) {
2357
+ var HTML5History = /*@__PURE__*/(function (History) {
2159
2358
  function HTML5History (router, base) {
2160
2359
  var this$1 = this;
2161
2360
 
2162
- History$$1.call(this, router, base);
2361
+ History.call(this, router, base);
2163
2362
 
2164
2363
  var expectScroll = router.options.scrollBehavior;
2165
2364
  var supportsScroll = supportsPushState && expectScroll;
@@ -2187,8 +2386,8 @@ var HTML5History = /*@__PURE__*/(function (History$$1) {
2187
2386
  });
2188
2387
  }
2189
2388
 
2190
- if ( History$$1 ) HTML5History.__proto__ = History$$1;
2191
- HTML5History.prototype = Object.create( History$$1 && History$$1.prototype );
2389
+ if ( History ) HTML5History.__proto__ = History;
2390
+ HTML5History.prototype = Object.create( History && History.prototype );
2192
2391
  HTML5History.prototype.constructor = HTML5History;
2193
2392
 
2194
2393
  HTML5History.prototype.go = function go (n) {
@@ -2243,9 +2442,9 @@ function getLocation (base) {
2243
2442
 
2244
2443
  /* */
2245
2444
 
2246
- var HashHistory = /*@__PURE__*/(function (History$$1) {
2445
+ var HashHistory = /*@__PURE__*/(function (History) {
2247
2446
  function HashHistory (router, base, fallback) {
2248
- History$$1.call(this, router, base);
2447
+ History.call(this, router, base);
2249
2448
  // check history fallback deeplinking
2250
2449
  if (fallback && checkFallback(this.base)) {
2251
2450
  return
@@ -2253,8 +2452,8 @@ var HashHistory = /*@__PURE__*/(function (History$$1) {
2253
2452
  ensureSlash();
2254
2453
  }
2255
2454
 
2256
- if ( History$$1 ) HashHistory.__proto__ = History$$1;
2257
- HashHistory.prototype = Object.create( History$$1 && History$$1.prototype );
2455
+ if ( History ) HashHistory.__proto__ = History;
2456
+ HashHistory.prototype = Object.create( History && History.prototype );
2258
2457
  HashHistory.prototype.constructor = HashHistory;
2259
2458
 
2260
2459
  // this is delayed until the app mounts
@@ -2270,20 +2469,23 @@ var HashHistory = /*@__PURE__*/(function (History$$1) {
2270
2469
  setupScroll();
2271
2470
  }
2272
2471
 
2273
- window.addEventListener(supportsPushState ? 'popstate' : 'hashchange', function () {
2274
- var current = this$1.current;
2275
- if (!ensureSlash()) {
2276
- return
2277
- }
2278
- this$1.transitionTo(getHash(), function (route) {
2279
- if (supportsScroll) {
2280
- handleScroll(this$1.router, route, current, true);
2281
- }
2282
- if (!supportsPushState) {
2283
- replaceHash(route.fullPath);
2472
+ window.addEventListener(
2473
+ supportsPushState ? 'popstate' : 'hashchange',
2474
+ function () {
2475
+ var current = this$1.current;
2476
+ if (!ensureSlash()) {
2477
+ return
2284
2478
  }
2285
- });
2286
- });
2479
+ this$1.transitionTo(getHash(), function (route) {
2480
+ if (supportsScroll) {
2481
+ handleScroll(this$1.router, route, current, true);
2482
+ }
2483
+ if (!supportsPushState) {
2484
+ replaceHash(route.fullPath);
2485
+ }
2486
+ });
2487
+ }
2488
+ );
2287
2489
  };
2288
2490
 
2289
2491
  HashHistory.prototype.push = function push (location, onComplete, onAbort) {
@@ -2291,11 +2493,15 @@ var HashHistory = /*@__PURE__*/(function (History$$1) {
2291
2493
 
2292
2494
  var ref = this;
2293
2495
  var fromRoute = ref.current;
2294
- this.transitionTo(location, function (route) {
2295
- pushHash(route.fullPath);
2296
- handleScroll(this$1.router, route, fromRoute, false);
2297
- onComplete && onComplete(route);
2298
- }, onAbort);
2496
+ this.transitionTo(
2497
+ location,
2498
+ function (route) {
2499
+ pushHash(route.fullPath);
2500
+ handleScroll(this$1.router, route, fromRoute, false);
2501
+ onComplete && onComplete(route);
2502
+ },
2503
+ onAbort
2504
+ );
2299
2505
  };
2300
2506
 
2301
2507
  HashHistory.prototype.replace = function replace (location, onComplete, onAbort) {
@@ -2303,11 +2509,15 @@ var HashHistory = /*@__PURE__*/(function (History$$1) {
2303
2509
 
2304
2510
  var ref = this;
2305
2511
  var fromRoute = ref.current;
2306
- this.transitionTo(location, function (route) {
2307
- replaceHash(route.fullPath);
2308
- handleScroll(this$1.router, route, fromRoute, false);
2309
- onComplete && onComplete(route);
2310
- }, onAbort);
2512
+ this.transitionTo(
2513
+ location,
2514
+ function (route) {
2515
+ replaceHash(route.fullPath);
2516
+ handleScroll(this$1.router, route, fromRoute, false);
2517
+ onComplete && onComplete(route);
2518
+ },
2519
+ onAbort
2520
+ );
2311
2521
  };
2312
2522
 
2313
2523
  HashHistory.prototype.go = function go (n) {
@@ -2331,9 +2541,7 @@ var HashHistory = /*@__PURE__*/(function (History$$1) {
2331
2541
  function checkFallback (base) {
2332
2542
  var location = getLocation(base);
2333
2543
  if (!/^\/#/.test(location)) {
2334
- window.location.replace(
2335
- cleanPath(base + '/#' + location)
2336
- );
2544
+ window.location.replace(cleanPath(base + '/#' + location));
2337
2545
  return true
2338
2546
  }
2339
2547
  }
@@ -2361,10 +2569,11 @@ function getHash () {
2361
2569
  var searchIndex = href.indexOf('?');
2362
2570
  if (searchIndex < 0) {
2363
2571
  var hashIndex = href.indexOf('#');
2364
- if (hashIndex > -1) { href = decodeURI(href.slice(0, hashIndex)) + href.slice(hashIndex); }
2365
- else { href = decodeURI(href); }
2572
+ if (hashIndex > -1) {
2573
+ href = decodeURI(href.slice(0, hashIndex)) + href.slice(hashIndex);
2574
+ } else { href = decodeURI(href); }
2366
2575
  } else {
2367
- if (searchIndex > -1) { href = decodeURI(href.slice(0, searchIndex)) + href.slice(searchIndex); }
2576
+ href = decodeURI(href.slice(0, searchIndex)) + href.slice(searchIndex);
2368
2577
  }
2369
2578
 
2370
2579
  return href
@@ -2395,34 +2604,42 @@ function replaceHash (path) {
2395
2604
 
2396
2605
  /* */
2397
2606
 
2398
- var AbstractHistory = /*@__PURE__*/(function (History$$1) {
2607
+ var AbstractHistory = /*@__PURE__*/(function (History) {
2399
2608
  function AbstractHistory (router, base) {
2400
- History$$1.call(this, router, base);
2609
+ History.call(this, router, base);
2401
2610
  this.stack = [];
2402
2611
  this.index = -1;
2403
2612
  }
2404
2613
 
2405
- if ( History$$1 ) AbstractHistory.__proto__ = History$$1;
2406
- AbstractHistory.prototype = Object.create( History$$1 && History$$1.prototype );
2614
+ if ( History ) AbstractHistory.__proto__ = History;
2615
+ AbstractHistory.prototype = Object.create( History && History.prototype );
2407
2616
  AbstractHistory.prototype.constructor = AbstractHistory;
2408
2617
 
2409
2618
  AbstractHistory.prototype.push = function push (location, onComplete, onAbort) {
2410
2619
  var this$1 = this;
2411
2620
 
2412
- this.transitionTo(location, function (route) {
2413
- this$1.stack = this$1.stack.slice(0, this$1.index + 1).concat(route);
2414
- this$1.index++;
2415
- onComplete && onComplete(route);
2416
- }, onAbort);
2621
+ this.transitionTo(
2622
+ location,
2623
+ function (route) {
2624
+ this$1.stack = this$1.stack.slice(0, this$1.index + 1).concat(route);
2625
+ this$1.index++;
2626
+ onComplete && onComplete(route);
2627
+ },
2628
+ onAbort
2629
+ );
2417
2630
  };
2418
2631
 
2419
2632
  AbstractHistory.prototype.replace = function replace (location, onComplete, onAbort) {
2420
2633
  var this$1 = this;
2421
2634
 
2422
- this.transitionTo(location, function (route) {
2423
- this$1.stack = this$1.stack.slice(0, this$1.index).concat(route);
2424
- onComplete && onComplete(route);
2425
- }, onAbort);
2635
+ this.transitionTo(
2636
+ location,
2637
+ function (route) {
2638
+ this$1.stack = this$1.stack.slice(0, this$1.index).concat(route);
2639
+ onComplete && onComplete(route);
2640
+ },
2641
+ onAbort
2642
+ );
2426
2643
  };
2427
2644
 
2428
2645
  AbstractHistory.prototype.go = function go (n) {
@@ -2433,10 +2650,18 @@ var AbstractHistory = /*@__PURE__*/(function (History$$1) {
2433
2650
  return
2434
2651
  }
2435
2652
  var route = this.stack[targetIndex];
2436
- this.confirmTransition(route, function () {
2437
- this$1.index = targetIndex;
2438
- this$1.updateRoute(route);
2439
- });
2653
+ this.confirmTransition(
2654
+ route,
2655
+ function () {
2656
+ this$1.index = targetIndex;
2657
+ this$1.updateRoute(route);
2658
+ },
2659
+ function (err) {
2660
+ if (isExtendedError(NavigationDuplicated, err)) {
2661
+ this$1.index = targetIndex;
2662
+ }
2663
+ }
2664
+ );
2440
2665
  };
2441
2666
 
2442
2667
  AbstractHistory.prototype.getCurrentLocation = function getCurrentLocation () {
@@ -2579,11 +2804,29 @@ KduRouter.prototype.onError = function onError (errorCb) {
2579
2804
  };
2580
2805
 
2581
2806
  KduRouter.prototype.push = function push (location, onComplete, onAbort) {
2582
- this.history.push(location, onComplete, onAbort);
2807
+ var this$1 = this;
2808
+
2809
+ // $flow-disable-line
2810
+ if (!onComplete && !onAbort && typeof Promise !== 'undefined') {
2811
+ return new Promise(function (resolve, reject) {
2812
+ this$1.history.push(location, resolve, reject);
2813
+ })
2814
+ } else {
2815
+ this.history.push(location, onComplete, onAbort);
2816
+ }
2583
2817
  };
2584
2818
 
2585
2819
  KduRouter.prototype.replace = function replace (location, onComplete, onAbort) {
2586
- this.history.replace(location, onComplete, onAbort);
2820
+ var this$1 = this;
2821
+
2822
+ // $flow-disable-line
2823
+ if (!onComplete && !onAbort && typeof Promise !== 'undefined') {
2824
+ return new Promise(function (resolve, reject) {
2825
+ this$1.history.replace(location, resolve, reject);
2826
+ })
2827
+ } else {
2828
+ this.history.replace(location, onComplete, onAbort);
2829
+ }
2587
2830
  };
2588
2831
 
2589
2832
  KduRouter.prototype.go = function go (n) {
@@ -2663,7 +2906,7 @@ function createHref (base, fullPath, mode) {
2663
2906
  }
2664
2907
 
2665
2908
  KduRouter.install = install;
2666
- KduRouter.version = '3.0.7';
2909
+ KduRouter.version = '3.1.7';
2667
2910
 
2668
2911
  if (inBrowser && window.Kdu) {
2669
2912
  window.Kdu.use(KduRouter);