kdu-router 2.7.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2022 NKDuy
3
+ Copyright (c) 2021-present NKDuy
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,10 +1,8 @@
1
1
  # kdu-router
2
2
 
3
- > This is kdu-router 2.0 which works only with Kdu 2.0..
4
-
5
3
  ### Introduction
6
4
 
7
- `kdu-router` is the official router for Kdu.js. It deeply integrates with Kdu.js core to make building Single Page Applications with Kdu.js a breeze. Features include:
5
+ `kdu-router` is the official router for [Kdu.js](http://kdu-js.web.app). It deeply integrates with Kdu.js core to make building Single Page Applications with Kdu.js a breeze. Features include:
8
6
 
9
7
  - Nested route/view mapping
10
8
  - Modular, component-based router configuration
@@ -15,31 +13,10 @@
15
13
  - HTML5 history mode or hash mode, with auto-fallback in IE9
16
14
  - Customizable Scroll Behavior
17
15
 
18
- Get started with the [documentation](http://khanhduy1407.github.io/kdu-router), or play with the [examples](https://github.com/khanhduy1407/kdu-router/tree/dev/examples) (see how to run them below).
19
-
20
- ### Development Setup
21
-
22
- ``` bash
23
- # install deps
24
- npm install
25
-
26
- # build dist files
27
- npm run build
28
-
29
- # serve examples at localhost:8080
30
- npm run dev
31
-
32
- # lint & run all tests
33
- npm test
34
-
35
- # serve docs at localhost:4000 (requires global gitbook-cli)
36
- npm run docs
37
- ```
38
-
39
16
  ## License
40
17
 
41
18
  [MIT](http://opensource.org/licenses/MIT)
42
19
 
43
- Copyright (c) 2022 NKDuy
20
+ Copyright (c) 2021-present NKDuy
44
21
 
45
22
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * kdu-router v2.7.0
2
+ * kdu-router v3.0.0
3
3
  * (c) 2022 NKDuy
4
4
  * @license MIT
5
5
  */
@@ -52,7 +52,7 @@ var View = {
52
52
  var depth = 0;
53
53
  var inactive = false;
54
54
  while (parent && parent._routerRoot !== parent) {
55
- if (parent.$vnode && parent.$vnode.data.routerView) {
55
+ if (parent.$knode && parent.$knode.data.routerView) {
56
56
  depth++;
57
57
  }
58
58
  if (parent._inactive) {
@@ -89,14 +89,22 @@ var View = {
89
89
  }
90
90
  }
91
91
 
92
- // also regiseter instance in prepatch hook
92
+ // also register instance in prepatch hook
93
93
  // in case the same component instance is reused across different routes
94
- ;(data.hook || (data.hook = {})).prepatch = function (_, vnode) {
95
- matched.instances[name] = vnode.componentInstance;
94
+ ;(data.hook || (data.hook = {})).prepatch = function (_, knode) {
95
+ matched.instances[name] = knode.componentInstance;
96
96
  };
97
97
 
98
98
  // resolve props
99
99
  data.props = resolveProps(route, matched.props && matched.props[name]);
100
+ data.attrs = {};
101
+
102
+ for (var key in data.props) {
103
+ if (!('props' in component) || !(key in component.props)) {
104
+ data.attrs[key] = data.props[key];
105
+ delete data.props[key];
106
+ }
107
+ }
100
108
 
101
109
  return h(component, data, children)
102
110
  }
@@ -154,8 +162,7 @@ function resolveQuery (
154
162
  parsedQuery = {};
155
163
  }
156
164
  for (var key in extraQuery) {
157
- var val = extraQuery[key];
158
- parsedQuery[key] = Array.isArray(val) ? val.slice() : val;
165
+ parsedQuery[key] = extraQuery[key];
159
166
  }
160
167
  return parsedQuery
161
168
  }
@@ -232,12 +239,18 @@ function createRoute (
232
239
  router
233
240
  ) {
234
241
  var stringifyQuery$$1 = router && router.options.stringifyQuery;
242
+
243
+ var query = location.query || {};
244
+ try {
245
+ query = clone(query);
246
+ } catch (e) {}
247
+
235
248
  var route = {
236
249
  name: location.name || (record && record.name),
237
250
  meta: (record && record.meta) || {},
238
251
  path: location.path || '/',
239
252
  hash: location.hash || '',
240
- query: location.query || {},
253
+ query: query,
241
254
  params: location.params || {},
242
255
  fullPath: getFullPath(location, stringifyQuery$$1),
243
256
  matched: record ? formatMatch(record) : []
@@ -248,6 +261,20 @@ function createRoute (
248
261
  return Object.freeze(route)
249
262
  }
250
263
 
264
+ function clone (value) {
265
+ if (Array.isArray(value)) {
266
+ return value.map(clone)
267
+ } else if (value && typeof value === 'object') {
268
+ var res = {};
269
+ for (var key in value) {
270
+ res[key] = clone(value[key]);
271
+ }
272
+ return res
273
+ } else {
274
+ return value
275
+ }
276
+ }
277
+
251
278
  // the starting route that represents the initial state
252
279
  var START = createRoute(null, {
253
280
  path: '/'
@@ -301,6 +328,8 @@ function isObjectEqual (a, b) {
301
328
  if ( a === void 0 ) a = {};
302
329
  if ( b === void 0 ) b = {};
303
330
 
331
+ // handle null value #1566
332
+ if (!a || !b) { return a === b }
304
333
  var aKeys = Object.keys(a);
305
334
  var bKeys = Object.keys(b);
306
335
  if (aKeys.length !== bKeys.length) {
@@ -480,7 +509,7 @@ function findAnchor (children) {
480
509
  var _Kdu;
481
510
 
482
511
  function install (Kdu) {
483
- if (install.installed) { return }
512
+ if (install.installed && _Kdu === Kdu) { return }
484
513
  install.installed = true;
485
514
 
486
515
  _Kdu = Kdu;
@@ -488,7 +517,7 @@ function install (Kdu) {
488
517
  var isDef = function (v) { return v !== undefined; };
489
518
 
490
519
  var registerInstance = function (vm, callVal) {
491
- var i = vm.$options._parentVnode;
520
+ var i = vm.$options._parentKnode;
492
521
  if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {
493
522
  i(vm, callVal);
494
523
  }
@@ -602,14 +631,14 @@ function cleanPath (path) {
602
631
  return path.replace(/\/\//g, '/')
603
632
  }
604
633
 
605
- var index$1 = Array.isArray || function (arr) {
634
+ var isarray = Array.isArray || function (arr) {
606
635
  return Object.prototype.toString.call(arr) == '[object Array]';
607
636
  };
608
637
 
609
638
  /**
610
639
  * Expose `pathToRegexp`.
611
640
  */
612
- var index = pathToRegexp;
641
+ var pathToRegexp_1 = pathToRegexp;
613
642
  var parse_1 = parse;
614
643
  var compile_1 = compile;
615
644
  var tokensToFunction_1 = tokensToFunction;
@@ -714,7 +743,7 @@ function parse (str, options) {
714
743
  * @return {!function(Object=, Object=)}
715
744
  */
716
745
  function compile (str, options) {
717
- return tokensToFunction(parse(str, options))
746
+ return tokensToFunction(parse(str, options), options)
718
747
  }
719
748
 
720
749
  /**
@@ -744,14 +773,14 @@ function encodeAsterisk (str) {
744
773
  /**
745
774
  * Expose a method for transforming tokens into the path function.
746
775
  */
747
- function tokensToFunction (tokens) {
776
+ function tokensToFunction (tokens, options) {
748
777
  // Compile all the tokens into regexps.
749
778
  var matches = new Array(tokens.length);
750
779
 
751
780
  // Compile all the patterns before compilation.
752
781
  for (var i = 0; i < tokens.length; i++) {
753
782
  if (typeof tokens[i] === 'object') {
754
- matches[i] = new RegExp('^(?:' + tokens[i].pattern + ')$');
783
+ matches[i] = new RegExp('^(?:' + tokens[i].pattern + ')$', flags(options));
755
784
  }
756
785
  }
757
786
 
@@ -786,7 +815,7 @@ function tokensToFunction (tokens) {
786
815
  }
787
816
  }
788
817
 
789
- if (index$1(value)) {
818
+ if (isarray(value)) {
790
819
  if (!token.repeat) {
791
820
  throw new TypeError('Expected "' + token.name + '" to not repeat, but received `' + JSON.stringify(value) + '`')
792
821
  }
@@ -864,7 +893,7 @@ function attachKeys (re, keys) {
864
893
  * @return {string}
865
894
  */
866
895
  function flags (options) {
867
- return options.sensitive ? '' : 'i'
896
+ return options && options.sensitive ? '' : 'i'
868
897
  }
869
898
 
870
899
  /**
@@ -937,7 +966,7 @@ function stringToRegexp (path, keys, options) {
937
966
  * @return {!RegExp}
938
967
  */
939
968
  function tokensToRegExp (tokens, keys, options) {
940
- if (!index$1(keys)) {
969
+ if (!isarray(keys)) {
941
970
  options = /** @type {!Object} */ (keys || options);
942
971
  keys = [];
943
972
  }
@@ -1013,7 +1042,7 @@ function tokensToRegExp (tokens, keys, options) {
1013
1042
  * @return {!RegExp}
1014
1043
  */
1015
1044
  function pathToRegexp (path, keys, options) {
1016
- if (!index$1(keys)) {
1045
+ if (!isarray(keys)) {
1017
1046
  options = /** @type {!Object} */ (keys || options);
1018
1047
  keys = [];
1019
1048
  }
@@ -1024,20 +1053,21 @@ function pathToRegexp (path, keys, options) {
1024
1053
  return regexpToRegexp(path, /** @type {!Array} */ (keys))
1025
1054
  }
1026
1055
 
1027
- if (index$1(path)) {
1056
+ if (isarray(path)) {
1028
1057
  return arrayToRegexp(/** @type {!Array} */ (path), /** @type {!Array} */ (keys), options)
1029
1058
  }
1030
1059
 
1031
1060
  return stringToRegexp(/** @type {string} */ (path), /** @type {!Array} */ (keys), options)
1032
1061
  }
1033
1062
 
1034
- index.parse = parse_1;
1035
- index.compile = compile_1;
1036
- index.tokensToFunction = tokensToFunction_1;
1037
- index.tokensToRegExp = tokensToRegExp_1;
1063
+ pathToRegexp_1.parse = parse_1;
1064
+ pathToRegexp_1.compile = compile_1;
1065
+ pathToRegexp_1.tokensToFunction = tokensToFunction_1;
1066
+ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
1038
1067
 
1039
1068
  /* */
1040
1069
 
1070
+ // $flow-disable-line
1041
1071
  var regexpCompileCache = Object.create(null);
1042
1072
 
1043
1073
  function fillParams (
@@ -1048,7 +1078,7 @@ function fillParams (
1048
1078
  try {
1049
1079
  var filler =
1050
1080
  regexpCompileCache[path] ||
1051
- (regexpCompileCache[path] = index.compile(path));
1081
+ (regexpCompileCache[path] = pathToRegexp_1.compile(path));
1052
1082
  return filler(params || {}, { pretty: true })
1053
1083
  } catch (e) {
1054
1084
  if (process.env.NODE_ENV !== 'production') {
@@ -1068,7 +1098,9 @@ function createRouteMap (
1068
1098
  ) {
1069
1099
  // the path list is used to control path matching priority
1070
1100
  var pathList = oldPathList || [];
1101
+ // $flow-disable-line
1071
1102
  var pathMap = oldPathMap || Object.create(null);
1103
+ // $flow-disable-line
1072
1104
  var nameMap = oldNameMap || Object.create(null);
1073
1105
 
1074
1106
  routes.forEach(function (route) {
@@ -1110,8 +1142,12 @@ function addRouteRecord (
1110
1142
  );
1111
1143
  }
1112
1144
 
1113
- var normalizedPath = normalizePath(path, parent);
1114
1145
  var pathToRegexpOptions = route.pathToRegexpOptions || {};
1146
+ var normalizedPath = normalizePath(
1147
+ path,
1148
+ parent,
1149
+ pathToRegexpOptions.strict
1150
+ );
1115
1151
 
1116
1152
  if (typeof route.caseSensitive === 'boolean') {
1117
1153
  pathToRegexpOptions.sensitive = route.caseSensitive;
@@ -1199,9 +1235,9 @@ function addRouteRecord (
1199
1235
  }
1200
1236
 
1201
1237
  function compileRouteRegex (path, pathToRegexpOptions) {
1202
- var regex = index(path, [], pathToRegexpOptions);
1238
+ var regex = pathToRegexp_1(path, [], pathToRegexpOptions);
1203
1239
  if (process.env.NODE_ENV !== 'production') {
1204
- var keys = {};
1240
+ var keys = Object.create(null);
1205
1241
  regex.keys.forEach(function (key) {
1206
1242
  warn(!keys[key.name], ("Duplicate param keys in route with path: \"" + path + "\""));
1207
1243
  keys[key.name] = true;
@@ -1210,8 +1246,8 @@ function compileRouteRegex (path, pathToRegexpOptions) {
1210
1246
  return regex
1211
1247
  }
1212
1248
 
1213
- function normalizePath (path, parent) {
1214
- path = path.replace(/\/$/, '');
1249
+ function normalizePath (path, parent, strict) {
1250
+ if (!strict) { path = path.replace(/\/$/, ''); }
1215
1251
  if (path[0] === '/') { return path }
1216
1252
  if (parent == null) { return path }
1217
1253
  return cleanPath(((parent.path) + "/" + path))
@@ -1483,6 +1519,8 @@ function resolveRecordPath (path, record) {
1483
1519
  var positionStore = Object.create(null);
1484
1520
 
1485
1521
  function setupScroll () {
1522
+ // Fix for #1585 for Firefox
1523
+ window.history.replaceState({ key: getStateKey() }, '');
1486
1524
  window.addEventListener('popstate', function (e) {
1487
1525
  saveScrollPosition();
1488
1526
  if (e.state && e.state.key) {
@@ -1514,25 +1552,21 @@ function handleScroll (
1514
1552
  router.app.$nextTick(function () {
1515
1553
  var position = getScrollPosition();
1516
1554
  var shouldScroll = behavior(to, from, isPop ? position : null);
1555
+
1517
1556
  if (!shouldScroll) {
1518
1557
  return
1519
1558
  }
1520
- var isObject = typeof shouldScroll === 'object';
1521
- if (isObject && typeof shouldScroll.selector === 'string') {
1522
- var el = document.querySelector(shouldScroll.selector);
1523
- if (el) {
1524
- var offset = shouldScroll.offset && typeof shouldScroll.offset === 'object' ? shouldScroll.offset : {};
1525
- offset = normalizeOffset(offset);
1526
- position = getElementPosition(el, offset);
1527
- } else if (isValidPosition(shouldScroll)) {
1528
- position = normalizePosition(shouldScroll);
1529
- }
1530
- } else if (isObject && isValidPosition(shouldScroll)) {
1531
- position = normalizePosition(shouldScroll);
1532
- }
1533
1559
 
1534
- if (position) {
1535
- window.scrollTo(position.x, position.y);
1560
+ if (typeof shouldScroll.then === 'function') {
1561
+ shouldScroll.then(function (shouldScroll) {
1562
+ scrollToPosition((shouldScroll), position);
1563
+ }).catch(function (err) {
1564
+ if (process.env.NODE_ENV !== 'production') {
1565
+ assert(false, err.toString());
1566
+ }
1567
+ });
1568
+ } else {
1569
+ scrollToPosition(shouldScroll, position);
1536
1570
  }
1537
1571
  });
1538
1572
  }
@@ -1586,6 +1620,26 @@ function isNumber (v) {
1586
1620
  return typeof v === 'number'
1587
1621
  }
1588
1622
 
1623
+ function scrollToPosition (shouldScroll, position) {
1624
+ var isObject = typeof shouldScroll === 'object';
1625
+ if (isObject && typeof shouldScroll.selector === 'string') {
1626
+ var el = document.querySelector(shouldScroll.selector);
1627
+ if (el) {
1628
+ var offset = shouldScroll.offset && typeof shouldScroll.offset === 'object' ? shouldScroll.offset : {};
1629
+ offset = normalizeOffset(offset);
1630
+ position = getElementPosition(el, offset);
1631
+ } else if (isValidPosition(shouldScroll)) {
1632
+ position = normalizePosition(shouldScroll);
1633
+ }
1634
+ } else if (isObject && isValidPosition(shouldScroll)) {
1635
+ position = normalizePosition(shouldScroll);
1636
+ }
1637
+
1638
+ if (position) {
1639
+ window.scrollTo(position.x, position.y);
1640
+ }
1641
+ }
1642
+
1589
1643
  /* */
1590
1644
 
1591
1645
  var supportsPushState = inBrowser && (function () {
@@ -1681,7 +1735,7 @@ function resolveAsyncComponents (matched) {
1681
1735
  pending++;
1682
1736
 
1683
1737
  var resolve = once(function (resolvedDef) {
1684
- if (resolvedDef.__esModule && resolvedDef.default) {
1738
+ if (isESModule(resolvedDef)) {
1685
1739
  resolvedDef = resolvedDef.default;
1686
1740
  }
1687
1741
  // save resolved on async factory in case it's used elsewhere
@@ -1716,7 +1770,7 @@ function resolveAsyncComponents (matched) {
1716
1770
  if (typeof res.then === 'function') {
1717
1771
  res.then(resolve, reject);
1718
1772
  } else {
1719
- // new syntax in Kdu
1773
+ // new syntax in Kdu 2.3
1720
1774
  var comp = res.component;
1721
1775
  if (comp && typeof comp.then === 'function') {
1722
1776
  comp.then(resolve, reject);
@@ -1747,6 +1801,14 @@ function flatten (arr) {
1747
1801
  return Array.prototype.concat.apply([], arr)
1748
1802
  }
1749
1803
 
1804
+ var hasSymbol =
1805
+ typeof Symbol === 'function' &&
1806
+ typeof Symbol.toStringTag === 'symbol';
1807
+
1808
+ function isESModule (obj) {
1809
+ return obj.__esModule || (hasSymbol && obj[Symbol.toStringTag] === 'Module')
1810
+ }
1811
+
1750
1812
  // in Webpack 2, require.ensure now also returns a Promise
1751
1813
  // so the resolve/reject functions may get called an extra time
1752
1814
  // if the user uses an arrow function shorthand that happens to
@@ -2075,9 +2137,18 @@ var HTML5History = (function (History$$1) {
2075
2137
  setupScroll();
2076
2138
  }
2077
2139
 
2140
+ var initLocation = getLocation(this.base);
2078
2141
  window.addEventListener('popstate', function (e) {
2079
2142
  var current = this$1.current;
2080
- this$1.transitionTo(getLocation(this$1.base), function (route) {
2143
+
2144
+ // Avoiding first `popstate` event dispatched in some browsers but first
2145
+ // history route not updated since async guard at the same time.
2146
+ var location = getLocation(this$1.base);
2147
+ if (this$1.current === START && location === initLocation) {
2148
+ return
2149
+ }
2150
+
2151
+ this$1.transitionTo(location, function (route) {
2081
2152
  if (expectScroll) {
2082
2153
  handleScroll(router, route, current, true);
2083
2154
  }
@@ -2161,26 +2232,50 @@ var HashHistory = (function (History$$1) {
2161
2232
  HashHistory.prototype.setupListeners = function setupListeners () {
2162
2233
  var this$1 = this;
2163
2234
 
2164
- window.addEventListener('hashchange', function () {
2235
+ var router = this.router;
2236
+ var expectScroll = router.options.scrollBehavior;
2237
+ var supportsScroll = supportsPushState && expectScroll;
2238
+
2239
+ if (supportsScroll) {
2240
+ setupScroll();
2241
+ }
2242
+
2243
+ window.addEventListener(supportsPushState ? 'popstate' : 'hashchange', function () {
2244
+ var current = this$1.current;
2165
2245
  if (!ensureSlash()) {
2166
2246
  return
2167
2247
  }
2168
2248
  this$1.transitionTo(getHash(), function (route) {
2169
- replaceHash(route.fullPath);
2249
+ if (supportsScroll) {
2250
+ handleScroll(this$1.router, route, current, true);
2251
+ }
2252
+ if (!supportsPushState) {
2253
+ replaceHash(route.fullPath);
2254
+ }
2170
2255
  });
2171
2256
  });
2172
2257
  };
2173
2258
 
2174
2259
  HashHistory.prototype.push = function push (location, onComplete, onAbort) {
2260
+ var this$1 = this;
2261
+
2262
+ var ref = this;
2263
+ var fromRoute = ref.current;
2175
2264
  this.transitionTo(location, function (route) {
2176
2265
  pushHash(route.fullPath);
2266
+ handleScroll(this$1.router, route, fromRoute, false);
2177
2267
  onComplete && onComplete(route);
2178
2268
  }, onAbort);
2179
2269
  };
2180
2270
 
2181
2271
  HashHistory.prototype.replace = function replace (location, onComplete, onAbort) {
2272
+ var this$1 = this;
2273
+
2274
+ var ref = this;
2275
+ var fromRoute = ref.current;
2182
2276
  this.transitionTo(location, function (route) {
2183
2277
  replaceHash(route.fullPath);
2278
+ handleScroll(this$1.router, route, fromRoute, false);
2184
2279
  onComplete && onComplete(route);
2185
2280
  }, onAbort);
2186
2281
  };
@@ -2230,15 +2325,27 @@ function getHash () {
2230
2325
  return index === -1 ? '' : href.slice(index + 1)
2231
2326
  }
2232
2327
 
2328
+ function getUrl (path) {
2329
+ var href = window.location.href;
2330
+ var i = href.indexOf('#');
2331
+ var base = i >= 0 ? href.slice(0, i) : href;
2332
+ return (base + "#" + path)
2333
+ }
2334
+
2233
2335
  function pushHash (path) {
2234
- window.location.hash = path;
2336
+ if (supportsPushState) {
2337
+ pushState(getUrl(path));
2338
+ } else {
2339
+ window.location.hash = path;
2340
+ }
2235
2341
  }
2236
2342
 
2237
2343
  function replaceHash (path) {
2238
- var href = window.location.href;
2239
- var i = href.indexOf('#');
2240
- var base = i >= 0 ? href.slice(0, i) : href;
2241
- window.location.replace((base + "#" + path));
2344
+ if (supportsPushState) {
2345
+ replaceState(getUrl(path));
2346
+ } else {
2347
+ window.location.replace(getUrl(path));
2348
+ }
2242
2349
  }
2243
2350
 
2244
2351
  /* */
@@ -2340,7 +2447,7 @@ var KduRouter = function KduRouter (options) {
2340
2447
  }
2341
2448
  };
2342
2449
 
2343
- var prototypeAccessors = { currentRoute: {} };
2450
+ var prototypeAccessors = { currentRoute: { configurable: true } };
2344
2451
 
2345
2452
  KduRouter.prototype.match = function match (
2346
2453
  raw,
@@ -2498,7 +2605,7 @@ function createHref (base, fullPath, mode) {
2498
2605
  }
2499
2606
 
2500
2607
  KduRouter.install = install;
2501
- KduRouter.version = '2.7.0';
2608
+ KduRouter.version = '3.0.0';
2502
2609
 
2503
2610
  if (inBrowser && window.Kdu) {
2504
2611
  window.Kdu.use(KduRouter);