kdu-router 2.7.0 → 4.0.16-rc.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.
@@ -1,2507 +0,0 @@
1
- /**
2
- * kdu-router v2.7.0
3
- * (c) 2022 NKDuy
4
- * @license MIT
5
- */
6
- 'use strict';
7
-
8
- /* */
9
-
10
- function assert (condition, message) {
11
- if (!condition) {
12
- throw new Error(("[kdu-router] " + message))
13
- }
14
- }
15
-
16
- function warn (condition, message) {
17
- if (process.env.NODE_ENV !== 'production' && !condition) {
18
- typeof console !== 'undefined' && console.warn(("[kdu-router] " + message));
19
- }
20
- }
21
-
22
- function isError (err) {
23
- return Object.prototype.toString.call(err).indexOf('Error') > -1
24
- }
25
-
26
- var View = {
27
- name: 'router-view',
28
- functional: true,
29
- props: {
30
- name: {
31
- type: String,
32
- default: 'default'
33
- }
34
- },
35
- render: function render (_, ref) {
36
- var props = ref.props;
37
- var children = ref.children;
38
- var parent = ref.parent;
39
- var data = ref.data;
40
-
41
- data.routerView = true;
42
-
43
- // directly use parent context's createElement() function
44
- // so that components rendered by router-view can resolve named slots
45
- var h = parent.$createElement;
46
- var name = props.name;
47
- var route = parent.$route;
48
- var cache = parent._routerViewCache || (parent._routerViewCache = {});
49
-
50
- // determine current view depth, also check to see if the tree
51
- // has been toggled inactive but kept-alive.
52
- var depth = 0;
53
- var inactive = false;
54
- while (parent && parent._routerRoot !== parent) {
55
- if (parent.$vnode && parent.$vnode.data.routerView) {
56
- depth++;
57
- }
58
- if (parent._inactive) {
59
- inactive = true;
60
- }
61
- parent = parent.$parent;
62
- }
63
- data.routerViewDepth = depth;
64
-
65
- // render previous view if the tree is inactive and kept-alive
66
- if (inactive) {
67
- return h(cache[name], data, children)
68
- }
69
-
70
- var matched = route.matched[depth];
71
- // render empty node if no matched route
72
- if (!matched) {
73
- cache[name] = null;
74
- return h()
75
- }
76
-
77
- var component = cache[name] = matched.components[name];
78
-
79
- // attach instance registration hook
80
- // this will be called in the instance's injected lifecycle hooks
81
- data.registerRouteInstance = function (vm, val) {
82
- // val could be undefined for unregistration
83
- var current = matched.instances[name];
84
- if (
85
- (val && current !== vm) ||
86
- (!val && current === vm)
87
- ) {
88
- matched.instances[name] = val;
89
- }
90
- }
91
-
92
- // also regiseter instance in prepatch hook
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;
96
- };
97
-
98
- // resolve props
99
- data.props = resolveProps(route, matched.props && matched.props[name]);
100
-
101
- return h(component, data, children)
102
- }
103
- };
104
-
105
- function resolveProps (route, config) {
106
- switch (typeof config) {
107
- case 'undefined':
108
- return
109
- case 'object':
110
- return config
111
- case 'function':
112
- return config(route)
113
- case 'boolean':
114
- return config ? route.params : undefined
115
- default:
116
- if (process.env.NODE_ENV !== 'production') {
117
- warn(
118
- false,
119
- "props in \"" + (route.path) + "\" is a " + (typeof config) + ", " +
120
- "expecting an object, function or boolean."
121
- );
122
- }
123
- }
124
- }
125
-
126
- /* */
127
-
128
- var encodeReserveRE = /[!'()*]/g;
129
- var encodeReserveReplacer = function (c) { return '%' + c.charCodeAt(0).toString(16); };
130
- var commaRE = /%2C/g;
131
-
132
- // fixed encodeURIComponent which is more conformant to RFC3986:
133
- // - escapes [!'()*]
134
- // - preserve commas
135
- var encode = function (str) { return encodeURIComponent(str)
136
- .replace(encodeReserveRE, encodeReserveReplacer)
137
- .replace(commaRE, ','); };
138
-
139
- var decode = decodeURIComponent;
140
-
141
- function resolveQuery (
142
- query,
143
- extraQuery,
144
- _parseQuery
145
- ) {
146
- if ( extraQuery === void 0 ) extraQuery = {};
147
-
148
- var parse = _parseQuery || parseQuery;
149
- var parsedQuery;
150
- try {
151
- parsedQuery = parse(query || '');
152
- } catch (e) {
153
- process.env.NODE_ENV !== 'production' && warn(false, e.message);
154
- parsedQuery = {};
155
- }
156
- for (var key in extraQuery) {
157
- var val = extraQuery[key];
158
- parsedQuery[key] = Array.isArray(val) ? val.slice() : val;
159
- }
160
- return parsedQuery
161
- }
162
-
163
- function parseQuery (query) {
164
- var res = {};
165
-
166
- query = query.trim().replace(/^(\?|#|&)/, '');
167
-
168
- if (!query) {
169
- return res
170
- }
171
-
172
- query.split('&').forEach(function (param) {
173
- var parts = param.replace(/\+/g, ' ').split('=');
174
- var key = decode(parts.shift());
175
- var val = parts.length > 0
176
- ? decode(parts.join('='))
177
- : null;
178
-
179
- if (res[key] === undefined) {
180
- res[key] = val;
181
- } else if (Array.isArray(res[key])) {
182
- res[key].push(val);
183
- } else {
184
- res[key] = [res[key], val];
185
- }
186
- });
187
-
188
- return res
189
- }
190
-
191
- function stringifyQuery (obj) {
192
- var res = obj ? Object.keys(obj).map(function (key) {
193
- var val = obj[key];
194
-
195
- if (val === undefined) {
196
- return ''
197
- }
198
-
199
- if (val === null) {
200
- return encode(key)
201
- }
202
-
203
- if (Array.isArray(val)) {
204
- var result = [];
205
- val.forEach(function (val2) {
206
- if (val2 === undefined) {
207
- return
208
- }
209
- if (val2 === null) {
210
- result.push(encode(key));
211
- } else {
212
- result.push(encode(key) + '=' + encode(val2));
213
- }
214
- });
215
- return result.join('&')
216
- }
217
-
218
- return encode(key) + '=' + encode(val)
219
- }).filter(function (x) { return x.length > 0; }).join('&') : null;
220
- return res ? ("?" + res) : ''
221
- }
222
-
223
- /* */
224
-
225
-
226
- var trailingSlashRE = /\/?$/;
227
-
228
- function createRoute (
229
- record,
230
- location,
231
- redirectedFrom,
232
- router
233
- ) {
234
- var stringifyQuery$$1 = router && router.options.stringifyQuery;
235
- var route = {
236
- name: location.name || (record && record.name),
237
- meta: (record && record.meta) || {},
238
- path: location.path || '/',
239
- hash: location.hash || '',
240
- query: location.query || {},
241
- params: location.params || {},
242
- fullPath: getFullPath(location, stringifyQuery$$1),
243
- matched: record ? formatMatch(record) : []
244
- };
245
- if (redirectedFrom) {
246
- route.redirectedFrom = getFullPath(redirectedFrom, stringifyQuery$$1);
247
- }
248
- return Object.freeze(route)
249
- }
250
-
251
- // the starting route that represents the initial state
252
- var START = createRoute(null, {
253
- path: '/'
254
- });
255
-
256
- function formatMatch (record) {
257
- var res = [];
258
- while (record) {
259
- res.unshift(record);
260
- record = record.parent;
261
- }
262
- return res
263
- }
264
-
265
- function getFullPath (
266
- ref,
267
- _stringifyQuery
268
- ) {
269
- var path = ref.path;
270
- var query = ref.query; if ( query === void 0 ) query = {};
271
- var hash = ref.hash; if ( hash === void 0 ) hash = '';
272
-
273
- var stringify = _stringifyQuery || stringifyQuery;
274
- return (path || '/') + stringify(query) + hash
275
- }
276
-
277
- function isSameRoute (a, b) {
278
- if (b === START) {
279
- return a === b
280
- } else if (!b) {
281
- return false
282
- } else if (a.path && b.path) {
283
- return (
284
- a.path.replace(trailingSlashRE, '') === b.path.replace(trailingSlashRE, '') &&
285
- a.hash === b.hash &&
286
- isObjectEqual(a.query, b.query)
287
- )
288
- } else if (a.name && b.name) {
289
- return (
290
- a.name === b.name &&
291
- a.hash === b.hash &&
292
- isObjectEqual(a.query, b.query) &&
293
- isObjectEqual(a.params, b.params)
294
- )
295
- } else {
296
- return false
297
- }
298
- }
299
-
300
- function isObjectEqual (a, b) {
301
- if ( a === void 0 ) a = {};
302
- if ( b === void 0 ) b = {};
303
-
304
- var aKeys = Object.keys(a);
305
- var bKeys = Object.keys(b);
306
- if (aKeys.length !== bKeys.length) {
307
- return false
308
- }
309
- return aKeys.every(function (key) {
310
- var aVal = a[key];
311
- var bVal = b[key];
312
- // check nested equality
313
- if (typeof aVal === 'object' && typeof bVal === 'object') {
314
- return isObjectEqual(aVal, bVal)
315
- }
316
- return String(aVal) === String(bVal)
317
- })
318
- }
319
-
320
- function isIncludedRoute (current, target) {
321
- return (
322
- current.path.replace(trailingSlashRE, '/').indexOf(
323
- target.path.replace(trailingSlashRE, '/')
324
- ) === 0 &&
325
- (!target.hash || current.hash === target.hash) &&
326
- queryIncludes(current.query, target.query)
327
- )
328
- }
329
-
330
- function queryIncludes (current, target) {
331
- for (var key in target) {
332
- if (!(key in current)) {
333
- return false
334
- }
335
- }
336
- return true
337
- }
338
-
339
- /* */
340
-
341
- // work around weird flow bug
342
- var toTypes = [String, Object];
343
- var eventTypes = [String, Array];
344
-
345
- var Link = {
346
- name: 'router-link',
347
- props: {
348
- to: {
349
- type: toTypes,
350
- required: true
351
- },
352
- tag: {
353
- type: String,
354
- default: 'a'
355
- },
356
- exact: Boolean,
357
- append: Boolean,
358
- replace: Boolean,
359
- activeClass: String,
360
- exactActiveClass: String,
361
- event: {
362
- type: eventTypes,
363
- default: 'click'
364
- }
365
- },
366
- render: function render (h) {
367
- var this$1 = this;
368
-
369
- var router = this.$router;
370
- var current = this.$route;
371
- var ref = router.resolve(this.to, current, this.append);
372
- var location = ref.location;
373
- var route = ref.route;
374
- var href = ref.href;
375
-
376
- var classes = {};
377
- var globalActiveClass = router.options.linkActiveClass;
378
- var globalExactActiveClass = router.options.linkExactActiveClass;
379
- // Support global empty active class
380
- var activeClassFallback = globalActiveClass == null
381
- ? 'router-link-active'
382
- : globalActiveClass;
383
- var exactActiveClassFallback = globalExactActiveClass == null
384
- ? 'router-link-exact-active'
385
- : globalExactActiveClass;
386
- var activeClass = this.activeClass == null
387
- ? activeClassFallback
388
- : this.activeClass;
389
- var exactActiveClass = this.exactActiveClass == null
390
- ? exactActiveClassFallback
391
- : this.exactActiveClass;
392
- var compareTarget = location.path
393
- ? createRoute(null, location, null, router)
394
- : route;
395
-
396
- classes[exactActiveClass] = isSameRoute(current, compareTarget);
397
- classes[activeClass] = this.exact
398
- ? classes[exactActiveClass]
399
- : isIncludedRoute(current, compareTarget);
400
-
401
- var handler = function (e) {
402
- if (guardEvent(e)) {
403
- if (this$1.replace) {
404
- router.replace(location);
405
- } else {
406
- router.push(location);
407
- }
408
- }
409
- };
410
-
411
- var on = { click: guardEvent };
412
- if (Array.isArray(this.event)) {
413
- this.event.forEach(function (e) { on[e] = handler; });
414
- } else {
415
- on[this.event] = handler;
416
- }
417
-
418
- var data = {
419
- class: classes
420
- };
421
-
422
- if (this.tag === 'a') {
423
- data.on = on;
424
- data.attrs = { href: href };
425
- } else {
426
- // find the first <a> child and apply listener and href
427
- var a = findAnchor(this.$slots.default);
428
- if (a) {
429
- // in case the <a> is a static node
430
- a.isStatic = false;
431
- var extend = _Kdu.util.extend;
432
- var aData = a.data = extend({}, a.data);
433
- aData.on = on;
434
- var aAttrs = a.data.attrs = extend({}, a.data.attrs);
435
- aAttrs.href = href;
436
- } else {
437
- // doesn't have <a> child, apply listener to self
438
- data.on = on;
439
- }
440
- }
441
-
442
- return h(this.tag, data, this.$slots.default)
443
- }
444
- };
445
-
446
- function guardEvent (e) {
447
- // don't redirect with control keys
448
- if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) { return }
449
- // don't redirect when preventDefault called
450
- if (e.defaultPrevented) { return }
451
- // don't redirect on right click
452
- if (e.button !== undefined && e.button !== 0) { return }
453
- // don't redirect if `target="_blank"`
454
- if (e.currentTarget && e.currentTarget.getAttribute) {
455
- var target = e.currentTarget.getAttribute('target');
456
- if (/\b_blank\b/i.test(target)) { return }
457
- }
458
- // this may be a Weex event which doesn't have this method
459
- if (e.preventDefault) {
460
- e.preventDefault();
461
- }
462
- return true
463
- }
464
-
465
- function findAnchor (children) {
466
- if (children) {
467
- var child;
468
- for (var i = 0; i < children.length; i++) {
469
- child = children[i];
470
- if (child.tag === 'a') {
471
- return child
472
- }
473
- if (child.children && (child = findAnchor(child.children))) {
474
- return child
475
- }
476
- }
477
- }
478
- }
479
-
480
- var _Kdu;
481
-
482
- function install (Kdu) {
483
- if (install.installed) { return }
484
- install.installed = true;
485
-
486
- _Kdu = Kdu;
487
-
488
- var isDef = function (v) { return v !== undefined; };
489
-
490
- var registerInstance = function (vm, callVal) {
491
- var i = vm.$options._parentVnode;
492
- if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {
493
- i(vm, callVal);
494
- }
495
- };
496
-
497
- Kdu.mixin({
498
- beforeCreate: function beforeCreate () {
499
- if (isDef(this.$options.router)) {
500
- this._routerRoot = this;
501
- this._router = this.$options.router;
502
- this._router.init(this);
503
- Kdu.util.defineReactive(this, '_route', this._router.history.current);
504
- } else {
505
- this._routerRoot = (this.$parent && this.$parent._routerRoot) || this;
506
- }
507
- registerInstance(this, this);
508
- },
509
- destroyed: function destroyed () {
510
- registerInstance(this);
511
- }
512
- });
513
-
514
- Object.defineProperty(Kdu.prototype, '$router', {
515
- get: function get () { return this._routerRoot._router }
516
- });
517
-
518
- Object.defineProperty(Kdu.prototype, '$route', {
519
- get: function get () { return this._routerRoot._route }
520
- });
521
-
522
- Kdu.component('router-view', View);
523
- Kdu.component('router-link', Link);
524
-
525
- var strats = Kdu.config.optionMergeStrategies;
526
- // use the same hook merging strategy for route hooks
527
- strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created;
528
- }
529
-
530
- /* */
531
-
532
- var inBrowser = typeof window !== 'undefined';
533
-
534
- /* */
535
-
536
- function resolvePath (
537
- relative,
538
- base,
539
- append
540
- ) {
541
- var firstChar = relative.charAt(0);
542
- if (firstChar === '/') {
543
- return relative
544
- }
545
-
546
- if (firstChar === '?' || firstChar === '#') {
547
- return base + relative
548
- }
549
-
550
- var stack = base.split('/');
551
-
552
- // remove trailing segment if:
553
- // - not appending
554
- // - appending to trailing slash (last segment is empty)
555
- if (!append || !stack[stack.length - 1]) {
556
- stack.pop();
557
- }
558
-
559
- // resolve relative path
560
- var segments = relative.replace(/^\//, '').split('/');
561
- for (var i = 0; i < segments.length; i++) {
562
- var segment = segments[i];
563
- if (segment === '..') {
564
- stack.pop();
565
- } else if (segment !== '.') {
566
- stack.push(segment);
567
- }
568
- }
569
-
570
- // ensure leading slash
571
- if (stack[0] !== '') {
572
- stack.unshift('');
573
- }
574
-
575
- return stack.join('/')
576
- }
577
-
578
- function parsePath (path) {
579
- var hash = '';
580
- var query = '';
581
-
582
- var hashIndex = path.indexOf('#');
583
- if (hashIndex >= 0) {
584
- hash = path.slice(hashIndex);
585
- path = path.slice(0, hashIndex);
586
- }
587
-
588
- var queryIndex = path.indexOf('?');
589
- if (queryIndex >= 0) {
590
- query = path.slice(queryIndex + 1);
591
- path = path.slice(0, queryIndex);
592
- }
593
-
594
- return {
595
- path: path,
596
- query: query,
597
- hash: hash
598
- }
599
- }
600
-
601
- function cleanPath (path) {
602
- return path.replace(/\/\//g, '/')
603
- }
604
-
605
- var index$1 = Array.isArray || function (arr) {
606
- return Object.prototype.toString.call(arr) == '[object Array]';
607
- };
608
-
609
- /**
610
- * Expose `pathToRegexp`.
611
- */
612
- var index = pathToRegexp;
613
- var parse_1 = parse;
614
- var compile_1 = compile;
615
- var tokensToFunction_1 = tokensToFunction;
616
- var tokensToRegExp_1 = tokensToRegExp;
617
-
618
- /**
619
- * The main path matching regexp utility.
620
- *
621
- * @type {RegExp}
622
- */
623
- var PATH_REGEXP = new RegExp([
624
- // Match escaped characters that would otherwise appear in future matches.
625
- // This allows the user to escape special characters that won't transform.
626
- '(\\\\.)',
627
- // Match Express-style parameters and un-named parameters with a prefix
628
- // and optional suffixes. Matches appear as:
629
- //
630
- // "/:test(\\d+)?" => ["/", "test", "\d+", undefined, "?", undefined]
631
- // "/route(\\d+)" => [undefined, undefined, undefined, "\d+", undefined, undefined]
632
- // "/*" => ["/", undefined, undefined, undefined, undefined, "*"]
633
- '([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))'
634
- ].join('|'), 'g');
635
-
636
- /**
637
- * Parse a string for the raw tokens.
638
- *
639
- * @param {string} str
640
- * @param {Object=} options
641
- * @return {!Array}
642
- */
643
- function parse (str, options) {
644
- var tokens = [];
645
- var key = 0;
646
- var index = 0;
647
- var path = '';
648
- var defaultDelimiter = options && options.delimiter || '/';
649
- var res;
650
-
651
- while ((res = PATH_REGEXP.exec(str)) != null) {
652
- var m = res[0];
653
- var escaped = res[1];
654
- var offset = res.index;
655
- path += str.slice(index, offset);
656
- index = offset + m.length;
657
-
658
- // Ignore already escaped sequences.
659
- if (escaped) {
660
- path += escaped[1];
661
- continue
662
- }
663
-
664
- var next = str[index];
665
- var prefix = res[2];
666
- var name = res[3];
667
- var capture = res[4];
668
- var group = res[5];
669
- var modifier = res[6];
670
- var asterisk = res[7];
671
-
672
- // Push the current path onto the tokens.
673
- if (path) {
674
- tokens.push(path);
675
- path = '';
676
- }
677
-
678
- var partial = prefix != null && next != null && next !== prefix;
679
- var repeat = modifier === '+' || modifier === '*';
680
- var optional = modifier === '?' || modifier === '*';
681
- var delimiter = res[2] || defaultDelimiter;
682
- var pattern = capture || group;
683
-
684
- tokens.push({
685
- name: name || key++,
686
- prefix: prefix || '',
687
- delimiter: delimiter,
688
- optional: optional,
689
- repeat: repeat,
690
- partial: partial,
691
- asterisk: !!asterisk,
692
- pattern: pattern ? escapeGroup(pattern) : (asterisk ? '.*' : '[^' + escapeString(delimiter) + ']+?')
693
- });
694
- }
695
-
696
- // Match any characters still remaining.
697
- if (index < str.length) {
698
- path += str.substr(index);
699
- }
700
-
701
- // If the path exists, push it onto the end.
702
- if (path) {
703
- tokens.push(path);
704
- }
705
-
706
- return tokens
707
- }
708
-
709
- /**
710
- * Compile a string to a template function for the path.
711
- *
712
- * @param {string} str
713
- * @param {Object=} options
714
- * @return {!function(Object=, Object=)}
715
- */
716
- function compile (str, options) {
717
- return tokensToFunction(parse(str, options))
718
- }
719
-
720
- /**
721
- * Prettier encoding of URI path segments.
722
- *
723
- * @param {string}
724
- * @return {string}
725
- */
726
- function encodeURIComponentPretty (str) {
727
- return encodeURI(str).replace(/[\/?#]/g, function (c) {
728
- return '%' + c.charCodeAt(0).toString(16).toUpperCase()
729
- })
730
- }
731
-
732
- /**
733
- * Encode the asterisk parameter. Similar to `pretty`, but allows slashes.
734
- *
735
- * @param {string}
736
- * @return {string}
737
- */
738
- function encodeAsterisk (str) {
739
- return encodeURI(str).replace(/[?#]/g, function (c) {
740
- return '%' + c.charCodeAt(0).toString(16).toUpperCase()
741
- })
742
- }
743
-
744
- /**
745
- * Expose a method for transforming tokens into the path function.
746
- */
747
- function tokensToFunction (tokens) {
748
- // Compile all the tokens into regexps.
749
- var matches = new Array(tokens.length);
750
-
751
- // Compile all the patterns before compilation.
752
- for (var i = 0; i < tokens.length; i++) {
753
- if (typeof tokens[i] === 'object') {
754
- matches[i] = new RegExp('^(?:' + tokens[i].pattern + ')$');
755
- }
756
- }
757
-
758
- return function (obj, opts) {
759
- var path = '';
760
- var data = obj || {};
761
- var options = opts || {};
762
- var encode = options.pretty ? encodeURIComponentPretty : encodeURIComponent;
763
-
764
- for (var i = 0; i < tokens.length; i++) {
765
- var token = tokens[i];
766
-
767
- if (typeof token === 'string') {
768
- path += token;
769
-
770
- continue
771
- }
772
-
773
- var value = data[token.name];
774
- var segment;
775
-
776
- if (value == null) {
777
- if (token.optional) {
778
- // Prepend partial segment prefixes.
779
- if (token.partial) {
780
- path += token.prefix;
781
- }
782
-
783
- continue
784
- } else {
785
- throw new TypeError('Expected "' + token.name + '" to be defined')
786
- }
787
- }
788
-
789
- if (index$1(value)) {
790
- if (!token.repeat) {
791
- throw new TypeError('Expected "' + token.name + '" to not repeat, but received `' + JSON.stringify(value) + '`')
792
- }
793
-
794
- if (value.length === 0) {
795
- if (token.optional) {
796
- continue
797
- } else {
798
- throw new TypeError('Expected "' + token.name + '" to not be empty')
799
- }
800
- }
801
-
802
- for (var j = 0; j < value.length; j++) {
803
- segment = encode(value[j]);
804
-
805
- if (!matches[i].test(segment)) {
806
- throw new TypeError('Expected all "' + token.name + '" to match "' + token.pattern + '", but received `' + JSON.stringify(segment) + '`')
807
- }
808
-
809
- path += (j === 0 ? token.prefix : token.delimiter) + segment;
810
- }
811
-
812
- continue
813
- }
814
-
815
- segment = token.asterisk ? encodeAsterisk(value) : encode(value);
816
-
817
- if (!matches[i].test(segment)) {
818
- throw new TypeError('Expected "' + token.name + '" to match "' + token.pattern + '", but received "' + segment + '"')
819
- }
820
-
821
- path += token.prefix + segment;
822
- }
823
-
824
- return path
825
- }
826
- }
827
-
828
- /**
829
- * Escape a regular expression string.
830
- *
831
- * @param {string} str
832
- * @return {string}
833
- */
834
- function escapeString (str) {
835
- return str.replace(/([.+*?=^!:${}()[\]|\/\\])/g, '\\$1')
836
- }
837
-
838
- /**
839
- * Escape the capturing group by escaping special characters and meaning.
840
- *
841
- * @param {string} group
842
- * @return {string}
843
- */
844
- function escapeGroup (group) {
845
- return group.replace(/([=!:$\/()])/g, '\\$1')
846
- }
847
-
848
- /**
849
- * Attach the keys as a property of the regexp.
850
- *
851
- * @param {!RegExp} re
852
- * @param {Array} keys
853
- * @return {!RegExp}
854
- */
855
- function attachKeys (re, keys) {
856
- re.keys = keys;
857
- return re
858
- }
859
-
860
- /**
861
- * Get the flags for a regexp from the options.
862
- *
863
- * @param {Object} options
864
- * @return {string}
865
- */
866
- function flags (options) {
867
- return options.sensitive ? '' : 'i'
868
- }
869
-
870
- /**
871
- * Pull out keys from a regexp.
872
- *
873
- * @param {!RegExp} path
874
- * @param {!Array} keys
875
- * @return {!RegExp}
876
- */
877
- function regexpToRegexp (path, keys) {
878
- // Use a negative lookahead to match only capturing groups.
879
- var groups = path.source.match(/\((?!\?)/g);
880
-
881
- if (groups) {
882
- for (var i = 0; i < groups.length; i++) {
883
- keys.push({
884
- name: i,
885
- prefix: null,
886
- delimiter: null,
887
- optional: false,
888
- repeat: false,
889
- partial: false,
890
- asterisk: false,
891
- pattern: null
892
- });
893
- }
894
- }
895
-
896
- return attachKeys(path, keys)
897
- }
898
-
899
- /**
900
- * Transform an array into a regexp.
901
- *
902
- * @param {!Array} path
903
- * @param {Array} keys
904
- * @param {!Object} options
905
- * @return {!RegExp}
906
- */
907
- function arrayToRegexp (path, keys, options) {
908
- var parts = [];
909
-
910
- for (var i = 0; i < path.length; i++) {
911
- parts.push(pathToRegexp(path[i], keys, options).source);
912
- }
913
-
914
- var regexp = new RegExp('(?:' + parts.join('|') + ')', flags(options));
915
-
916
- return attachKeys(regexp, keys)
917
- }
918
-
919
- /**
920
- * Create a path regexp from string input.
921
- *
922
- * @param {string} path
923
- * @param {!Array} keys
924
- * @param {!Object} options
925
- * @return {!RegExp}
926
- */
927
- function stringToRegexp (path, keys, options) {
928
- return tokensToRegExp(parse(path, options), keys, options)
929
- }
930
-
931
- /**
932
- * Expose a function for taking tokens and returning a RegExp.
933
- *
934
- * @param {!Array} tokens
935
- * @param {(Array|Object)=} keys
936
- * @param {Object=} options
937
- * @return {!RegExp}
938
- */
939
- function tokensToRegExp (tokens, keys, options) {
940
- if (!index$1(keys)) {
941
- options = /** @type {!Object} */ (keys || options);
942
- keys = [];
943
- }
944
-
945
- options = options || {};
946
-
947
- var strict = options.strict;
948
- var end = options.end !== false;
949
- var route = '';
950
-
951
- // Iterate over the tokens and create our regexp string.
952
- for (var i = 0; i < tokens.length; i++) {
953
- var token = tokens[i];
954
-
955
- if (typeof token === 'string') {
956
- route += escapeString(token);
957
- } else {
958
- var prefix = escapeString(token.prefix);
959
- var capture = '(?:' + token.pattern + ')';
960
-
961
- keys.push(token);
962
-
963
- if (token.repeat) {
964
- capture += '(?:' + prefix + capture + ')*';
965
- }
966
-
967
- if (token.optional) {
968
- if (!token.partial) {
969
- capture = '(?:' + prefix + '(' + capture + '))?';
970
- } else {
971
- capture = prefix + '(' + capture + ')?';
972
- }
973
- } else {
974
- capture = prefix + '(' + capture + ')';
975
- }
976
-
977
- route += capture;
978
- }
979
- }
980
-
981
- var delimiter = escapeString(options.delimiter || '/');
982
- var endsWithDelimiter = route.slice(-delimiter.length) === delimiter;
983
-
984
- // In non-strict mode we allow a slash at the end of match. If the path to
985
- // match already ends with a slash, we remove it for consistency. The slash
986
- // is valid at the end of a path match, not in the middle. This is important
987
- // in non-ending mode, where "/test/" shouldn't match "/test//route".
988
- if (!strict) {
989
- route = (endsWithDelimiter ? route.slice(0, -delimiter.length) : route) + '(?:' + delimiter + '(?=$))?';
990
- }
991
-
992
- if (end) {
993
- route += '$';
994
- } else {
995
- // In non-ending mode, we need the capturing groups to match as much as
996
- // possible by using a positive lookahead to the end or next path segment.
997
- route += strict && endsWithDelimiter ? '' : '(?=' + delimiter + '|$)';
998
- }
999
-
1000
- return attachKeys(new RegExp('^' + route, flags(options)), keys)
1001
- }
1002
-
1003
- /**
1004
- * Normalize the given path string, returning a regular expression.
1005
- *
1006
- * An empty array can be passed in for the keys, which will hold the
1007
- * placeholder key descriptions. For example, using `/user/:id`, `keys` will
1008
- * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`.
1009
- *
1010
- * @param {(string|RegExp|Array)} path
1011
- * @param {(Array|Object)=} keys
1012
- * @param {Object=} options
1013
- * @return {!RegExp}
1014
- */
1015
- function pathToRegexp (path, keys, options) {
1016
- if (!index$1(keys)) {
1017
- options = /** @type {!Object} */ (keys || options);
1018
- keys = [];
1019
- }
1020
-
1021
- options = options || {};
1022
-
1023
- if (path instanceof RegExp) {
1024
- return regexpToRegexp(path, /** @type {!Array} */ (keys))
1025
- }
1026
-
1027
- if (index$1(path)) {
1028
- return arrayToRegexp(/** @type {!Array} */ (path), /** @type {!Array} */ (keys), options)
1029
- }
1030
-
1031
- return stringToRegexp(/** @type {string} */ (path), /** @type {!Array} */ (keys), options)
1032
- }
1033
-
1034
- index.parse = parse_1;
1035
- index.compile = compile_1;
1036
- index.tokensToFunction = tokensToFunction_1;
1037
- index.tokensToRegExp = tokensToRegExp_1;
1038
-
1039
- /* */
1040
-
1041
- var regexpCompileCache = Object.create(null);
1042
-
1043
- function fillParams (
1044
- path,
1045
- params,
1046
- routeMsg
1047
- ) {
1048
- try {
1049
- var filler =
1050
- regexpCompileCache[path] ||
1051
- (regexpCompileCache[path] = index.compile(path));
1052
- return filler(params || {}, { pretty: true })
1053
- } catch (e) {
1054
- if (process.env.NODE_ENV !== 'production') {
1055
- warn(false, ("missing param for " + routeMsg + ": " + (e.message)));
1056
- }
1057
- return ''
1058
- }
1059
- }
1060
-
1061
- /* */
1062
-
1063
- function createRouteMap (
1064
- routes,
1065
- oldPathList,
1066
- oldPathMap,
1067
- oldNameMap
1068
- ) {
1069
- // the path list is used to control path matching priority
1070
- var pathList = oldPathList || [];
1071
- var pathMap = oldPathMap || Object.create(null);
1072
- var nameMap = oldNameMap || Object.create(null);
1073
-
1074
- routes.forEach(function (route) {
1075
- addRouteRecord(pathList, pathMap, nameMap, route);
1076
- });
1077
-
1078
- // ensure wildcard routes are always at the end
1079
- for (var i = 0, l = pathList.length; i < l; i++) {
1080
- if (pathList[i] === '*') {
1081
- pathList.push(pathList.splice(i, 1)[0]);
1082
- l--;
1083
- i--;
1084
- }
1085
- }
1086
-
1087
- return {
1088
- pathList: pathList,
1089
- pathMap: pathMap,
1090
- nameMap: nameMap
1091
- }
1092
- }
1093
-
1094
- function addRouteRecord (
1095
- pathList,
1096
- pathMap,
1097
- nameMap,
1098
- route,
1099
- parent,
1100
- matchAs
1101
- ) {
1102
- var path = route.path;
1103
- var name = route.name;
1104
- if (process.env.NODE_ENV !== 'production') {
1105
- assert(path != null, "\"path\" is required in a route configuration.");
1106
- assert(
1107
- typeof route.component !== 'string',
1108
- "route config \"component\" for path: " + (String(path || name)) + " cannot be a " +
1109
- "string id. Use an actual component instead."
1110
- );
1111
- }
1112
-
1113
- var normalizedPath = normalizePath(path, parent);
1114
- var pathToRegexpOptions = route.pathToRegexpOptions || {};
1115
-
1116
- if (typeof route.caseSensitive === 'boolean') {
1117
- pathToRegexpOptions.sensitive = route.caseSensitive;
1118
- }
1119
-
1120
- var record = {
1121
- path: normalizedPath,
1122
- regex: compileRouteRegex(normalizedPath, pathToRegexpOptions),
1123
- components: route.components || { default: route.component },
1124
- instances: {},
1125
- name: name,
1126
- parent: parent,
1127
- matchAs: matchAs,
1128
- redirect: route.redirect,
1129
- beforeEnter: route.beforeEnter,
1130
- meta: route.meta || {},
1131
- props: route.props == null
1132
- ? {}
1133
- : route.components
1134
- ? route.props
1135
- : { default: route.props }
1136
- };
1137
-
1138
- if (route.children) {
1139
- // Warn if route is named, does not redirect and has a default child route.
1140
- // If users navigate to this route by name, the default child will
1141
- // not be rendered (GH Issue #629)
1142
- if (process.env.NODE_ENV !== 'production') {
1143
- if (route.name && !route.redirect && route.children.some(function (child) { return /^\/?$/.test(child.path); })) {
1144
- warn(
1145
- false,
1146
- "Named Route '" + (route.name) + "' has a default child route. " +
1147
- "When navigating to this named route (:to=\"{name: '" + (route.name) + "'\"), " +
1148
- "the default child route will not be rendered. Remove the name from " +
1149
- "this route and use the name of the default child route for named " +
1150
- "links instead."
1151
- );
1152
- }
1153
- }
1154
- route.children.forEach(function (child) {
1155
- var childMatchAs = matchAs
1156
- ? cleanPath((matchAs + "/" + (child.path)))
1157
- : undefined;
1158
- addRouteRecord(pathList, pathMap, nameMap, child, record, childMatchAs);
1159
- });
1160
- }
1161
-
1162
- if (route.alias !== undefined) {
1163
- var aliases = Array.isArray(route.alias)
1164
- ? route.alias
1165
- : [route.alias];
1166
-
1167
- aliases.forEach(function (alias) {
1168
- var aliasRoute = {
1169
- path: alias,
1170
- children: route.children
1171
- };
1172
- addRouteRecord(
1173
- pathList,
1174
- pathMap,
1175
- nameMap,
1176
- aliasRoute,
1177
- parent,
1178
- record.path || '/' // matchAs
1179
- );
1180
- });
1181
- }
1182
-
1183
- if (!pathMap[record.path]) {
1184
- pathList.push(record.path);
1185
- pathMap[record.path] = record;
1186
- }
1187
-
1188
- if (name) {
1189
- if (!nameMap[name]) {
1190
- nameMap[name] = record;
1191
- } else if (process.env.NODE_ENV !== 'production' && !matchAs) {
1192
- warn(
1193
- false,
1194
- "Duplicate named routes definition: " +
1195
- "{ name: \"" + name + "\", path: \"" + (record.path) + "\" }"
1196
- );
1197
- }
1198
- }
1199
- }
1200
-
1201
- function compileRouteRegex (path, pathToRegexpOptions) {
1202
- var regex = index(path, [], pathToRegexpOptions);
1203
- if (process.env.NODE_ENV !== 'production') {
1204
- var keys = {};
1205
- regex.keys.forEach(function (key) {
1206
- warn(!keys[key.name], ("Duplicate param keys in route with path: \"" + path + "\""));
1207
- keys[key.name] = true;
1208
- });
1209
- }
1210
- return regex
1211
- }
1212
-
1213
- function normalizePath (path, parent) {
1214
- path = path.replace(/\/$/, '');
1215
- if (path[0] === '/') { return path }
1216
- if (parent == null) { return path }
1217
- return cleanPath(((parent.path) + "/" + path))
1218
- }
1219
-
1220
- /* */
1221
-
1222
-
1223
- function normalizeLocation (
1224
- raw,
1225
- current,
1226
- append,
1227
- router
1228
- ) {
1229
- var next = typeof raw === 'string' ? { path: raw } : raw;
1230
- // named target
1231
- if (next.name || next._normalized) {
1232
- return next
1233
- }
1234
-
1235
- // relative params
1236
- if (!next.path && next.params && current) {
1237
- next = assign({}, next);
1238
- next._normalized = true;
1239
- var params = assign(assign({}, current.params), next.params);
1240
- if (current.name) {
1241
- next.name = current.name;
1242
- next.params = params;
1243
- } else if (current.matched.length) {
1244
- var rawPath = current.matched[current.matched.length - 1].path;
1245
- next.path = fillParams(rawPath, params, ("path " + (current.path)));
1246
- } else if (process.env.NODE_ENV !== 'production') {
1247
- warn(false, "relative params navigation requires a current route.");
1248
- }
1249
- return next
1250
- }
1251
-
1252
- var parsedPath = parsePath(next.path || '');
1253
- var basePath = (current && current.path) || '/';
1254
- var path = parsedPath.path
1255
- ? resolvePath(parsedPath.path, basePath, append || next.append)
1256
- : basePath;
1257
-
1258
- var query = resolveQuery(
1259
- parsedPath.query,
1260
- next.query,
1261
- router && router.options.parseQuery
1262
- );
1263
-
1264
- var hash = next.hash || parsedPath.hash;
1265
- if (hash && hash.charAt(0) !== '#') {
1266
- hash = "#" + hash;
1267
- }
1268
-
1269
- return {
1270
- _normalized: true,
1271
- path: path,
1272
- query: query,
1273
- hash: hash
1274
- }
1275
- }
1276
-
1277
- function assign (a, b) {
1278
- for (var key in b) {
1279
- a[key] = b[key];
1280
- }
1281
- return a
1282
- }
1283
-
1284
- /* */
1285
-
1286
-
1287
- function createMatcher (
1288
- routes,
1289
- router
1290
- ) {
1291
- var ref = createRouteMap(routes);
1292
- var pathList = ref.pathList;
1293
- var pathMap = ref.pathMap;
1294
- var nameMap = ref.nameMap;
1295
-
1296
- function addRoutes (routes) {
1297
- createRouteMap(routes, pathList, pathMap, nameMap);
1298
- }
1299
-
1300
- function match (
1301
- raw,
1302
- currentRoute,
1303
- redirectedFrom
1304
- ) {
1305
- var location = normalizeLocation(raw, currentRoute, false, router);
1306
- var name = location.name;
1307
-
1308
- if (name) {
1309
- var record = nameMap[name];
1310
- if (process.env.NODE_ENV !== 'production') {
1311
- warn(record, ("Route with name '" + name + "' does not exist"));
1312
- }
1313
- if (!record) { return _createRoute(null, location) }
1314
- var paramNames = record.regex.keys
1315
- .filter(function (key) { return !key.optional; })
1316
- .map(function (key) { return key.name; });
1317
-
1318
- if (typeof location.params !== 'object') {
1319
- location.params = {};
1320
- }
1321
-
1322
- if (currentRoute && typeof currentRoute.params === 'object') {
1323
- for (var key in currentRoute.params) {
1324
- if (!(key in location.params) && paramNames.indexOf(key) > -1) {
1325
- location.params[key] = currentRoute.params[key];
1326
- }
1327
- }
1328
- }
1329
-
1330
- if (record) {
1331
- location.path = fillParams(record.path, location.params, ("named route \"" + name + "\""));
1332
- return _createRoute(record, location, redirectedFrom)
1333
- }
1334
- } else if (location.path) {
1335
- location.params = {};
1336
- for (var i = 0; i < pathList.length; i++) {
1337
- var path = pathList[i];
1338
- var record$1 = pathMap[path];
1339
- if (matchRoute(record$1.regex, location.path, location.params)) {
1340
- return _createRoute(record$1, location, redirectedFrom)
1341
- }
1342
- }
1343
- }
1344
- // no match
1345
- return _createRoute(null, location)
1346
- }
1347
-
1348
- function redirect (
1349
- record,
1350
- location
1351
- ) {
1352
- var originalRedirect = record.redirect;
1353
- var redirect = typeof originalRedirect === 'function'
1354
- ? originalRedirect(createRoute(record, location, null, router))
1355
- : originalRedirect;
1356
-
1357
- if (typeof redirect === 'string') {
1358
- redirect = { path: redirect };
1359
- }
1360
-
1361
- if (!redirect || typeof redirect !== 'object') {
1362
- if (process.env.NODE_ENV !== 'production') {
1363
- warn(
1364
- false, ("invalid redirect option: " + (JSON.stringify(redirect)))
1365
- );
1366
- }
1367
- return _createRoute(null, location)
1368
- }
1369
-
1370
- var re = redirect;
1371
- var name = re.name;
1372
- var path = re.path;
1373
- var query = location.query;
1374
- var hash = location.hash;
1375
- var params = location.params;
1376
- query = re.hasOwnProperty('query') ? re.query : query;
1377
- hash = re.hasOwnProperty('hash') ? re.hash : hash;
1378
- params = re.hasOwnProperty('params') ? re.params : params;
1379
-
1380
- if (name) {
1381
- // resolved named direct
1382
- var targetRecord = nameMap[name];
1383
- if (process.env.NODE_ENV !== 'production') {
1384
- assert(targetRecord, ("redirect failed: named route \"" + name + "\" not found."));
1385
- }
1386
- return match({
1387
- _normalized: true,
1388
- name: name,
1389
- query: query,
1390
- hash: hash,
1391
- params: params
1392
- }, undefined, location)
1393
- } else if (path) {
1394
- // 1. resolve relative redirect
1395
- var rawPath = resolveRecordPath(path, record);
1396
- // 2. resolve params
1397
- var resolvedPath = fillParams(rawPath, params, ("redirect route with path \"" + rawPath + "\""));
1398
- // 3. rematch with existing query and hash
1399
- return match({
1400
- _normalized: true,
1401
- path: resolvedPath,
1402
- query: query,
1403
- hash: hash
1404
- }, undefined, location)
1405
- } else {
1406
- if (process.env.NODE_ENV !== 'production') {
1407
- warn(false, ("invalid redirect option: " + (JSON.stringify(redirect))));
1408
- }
1409
- return _createRoute(null, location)
1410
- }
1411
- }
1412
-
1413
- function alias (
1414
- record,
1415
- location,
1416
- matchAs
1417
- ) {
1418
- var aliasedPath = fillParams(matchAs, location.params, ("aliased route with path \"" + matchAs + "\""));
1419
- var aliasedMatch = match({
1420
- _normalized: true,
1421
- path: aliasedPath
1422
- });
1423
- if (aliasedMatch) {
1424
- var matched = aliasedMatch.matched;
1425
- var aliasedRecord = matched[matched.length - 1];
1426
- location.params = aliasedMatch.params;
1427
- return _createRoute(aliasedRecord, location)
1428
- }
1429
- return _createRoute(null, location)
1430
- }
1431
-
1432
- function _createRoute (
1433
- record,
1434
- location,
1435
- redirectedFrom
1436
- ) {
1437
- if (record && record.redirect) {
1438
- return redirect(record, redirectedFrom || location)
1439
- }
1440
- if (record && record.matchAs) {
1441
- return alias(record, location, record.matchAs)
1442
- }
1443
- return createRoute(record, location, redirectedFrom, router)
1444
- }
1445
-
1446
- return {
1447
- match: match,
1448
- addRoutes: addRoutes
1449
- }
1450
- }
1451
-
1452
- function matchRoute (
1453
- regex,
1454
- path,
1455
- params
1456
- ) {
1457
- var m = path.match(regex);
1458
-
1459
- if (!m) {
1460
- return false
1461
- } else if (!params) {
1462
- return true
1463
- }
1464
-
1465
- for (var i = 1, len = m.length; i < len; ++i) {
1466
- var key = regex.keys[i - 1];
1467
- var val = typeof m[i] === 'string' ? decodeURIComponent(m[i]) : m[i];
1468
- if (key) {
1469
- params[key.name] = val;
1470
- }
1471
- }
1472
-
1473
- return true
1474
- }
1475
-
1476
- function resolveRecordPath (path, record) {
1477
- return resolvePath(path, record.parent ? record.parent.path : '/', true)
1478
- }
1479
-
1480
- /* */
1481
-
1482
-
1483
- var positionStore = Object.create(null);
1484
-
1485
- function setupScroll () {
1486
- window.addEventListener('popstate', function (e) {
1487
- saveScrollPosition();
1488
- if (e.state && e.state.key) {
1489
- setStateKey(e.state.key);
1490
- }
1491
- });
1492
- }
1493
-
1494
- function handleScroll (
1495
- router,
1496
- to,
1497
- from,
1498
- isPop
1499
- ) {
1500
- if (!router.app) {
1501
- return
1502
- }
1503
-
1504
- var behavior = router.options.scrollBehavior;
1505
- if (!behavior) {
1506
- return
1507
- }
1508
-
1509
- if (process.env.NODE_ENV !== 'production') {
1510
- assert(typeof behavior === 'function', "scrollBehavior must be a function");
1511
- }
1512
-
1513
- // wait until re-render finishes before scrolling
1514
- router.app.$nextTick(function () {
1515
- var position = getScrollPosition();
1516
- var shouldScroll = behavior(to, from, isPop ? position : null);
1517
- if (!shouldScroll) {
1518
- return
1519
- }
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
-
1534
- if (position) {
1535
- window.scrollTo(position.x, position.y);
1536
- }
1537
- });
1538
- }
1539
-
1540
- function saveScrollPosition () {
1541
- var key = getStateKey();
1542
- if (key) {
1543
- positionStore[key] = {
1544
- x: window.pageXOffset,
1545
- y: window.pageYOffset
1546
- };
1547
- }
1548
- }
1549
-
1550
- function getScrollPosition () {
1551
- var key = getStateKey();
1552
- if (key) {
1553
- return positionStore[key]
1554
- }
1555
- }
1556
-
1557
- function getElementPosition (el, offset) {
1558
- var docEl = document.documentElement;
1559
- var docRect = docEl.getBoundingClientRect();
1560
- var elRect = el.getBoundingClientRect();
1561
- return {
1562
- x: elRect.left - docRect.left - offset.x,
1563
- y: elRect.top - docRect.top - offset.y
1564
- }
1565
- }
1566
-
1567
- function isValidPosition (obj) {
1568
- return isNumber(obj.x) || isNumber(obj.y)
1569
- }
1570
-
1571
- function normalizePosition (obj) {
1572
- return {
1573
- x: isNumber(obj.x) ? obj.x : window.pageXOffset,
1574
- y: isNumber(obj.y) ? obj.y : window.pageYOffset
1575
- }
1576
- }
1577
-
1578
- function normalizeOffset (obj) {
1579
- return {
1580
- x: isNumber(obj.x) ? obj.x : 0,
1581
- y: isNumber(obj.y) ? obj.y : 0
1582
- }
1583
- }
1584
-
1585
- function isNumber (v) {
1586
- return typeof v === 'number'
1587
- }
1588
-
1589
- /* */
1590
-
1591
- var supportsPushState = inBrowser && (function () {
1592
- var ua = window.navigator.userAgent;
1593
-
1594
- if (
1595
- (ua.indexOf('Android 2.') !== -1 || ua.indexOf('Android 4.0') !== -1) &&
1596
- ua.indexOf('Mobile Safari') !== -1 &&
1597
- ua.indexOf('Chrome') === -1 &&
1598
- ua.indexOf('Windows Phone') === -1
1599
- ) {
1600
- return false
1601
- }
1602
-
1603
- return window.history && 'pushState' in window.history
1604
- })();
1605
-
1606
- // use User Timing api (if present) for more accurate key precision
1607
- var Time = inBrowser && window.performance && window.performance.now
1608
- ? window.performance
1609
- : Date;
1610
-
1611
- var _key = genKey();
1612
-
1613
- function genKey () {
1614
- return Time.now().toFixed(3)
1615
- }
1616
-
1617
- function getStateKey () {
1618
- return _key
1619
- }
1620
-
1621
- function setStateKey (key) {
1622
- _key = key;
1623
- }
1624
-
1625
- function pushState (url, replace) {
1626
- saveScrollPosition();
1627
- // try...catch the pushState call to get around Safari
1628
- // DOM Exception 18 where it limits to 100 pushState calls
1629
- var history = window.history;
1630
- try {
1631
- if (replace) {
1632
- history.replaceState({ key: _key }, '', url);
1633
- } else {
1634
- _key = genKey();
1635
- history.pushState({ key: _key }, '', url);
1636
- }
1637
- } catch (e) {
1638
- window.location[replace ? 'replace' : 'assign'](url);
1639
- }
1640
- }
1641
-
1642
- function replaceState (url) {
1643
- pushState(url, true);
1644
- }
1645
-
1646
- /* */
1647
-
1648
- function runQueue (queue, fn, cb) {
1649
- var step = function (index) {
1650
- if (index >= queue.length) {
1651
- cb();
1652
- } else {
1653
- if (queue[index]) {
1654
- fn(queue[index], function () {
1655
- step(index + 1);
1656
- });
1657
- } else {
1658
- step(index + 1);
1659
- }
1660
- }
1661
- };
1662
- step(0);
1663
- }
1664
-
1665
- /* */
1666
-
1667
- function resolveAsyncComponents (matched) {
1668
- return function (to, from, next) {
1669
- var hasAsync = false;
1670
- var pending = 0;
1671
- var error = null;
1672
-
1673
- flatMapComponents(matched, function (def, _, match, key) {
1674
- // if it's a function and doesn't have cid attached,
1675
- // assume it's an async component resolve function.
1676
- // we are not using Kdu's default async resolving mechanism because
1677
- // we want to halt the navigation until the incoming component has been
1678
- // resolved.
1679
- if (typeof def === 'function' && def.cid === undefined) {
1680
- hasAsync = true;
1681
- pending++;
1682
-
1683
- var resolve = once(function (resolvedDef) {
1684
- if (resolvedDef.__esModule && resolvedDef.default) {
1685
- resolvedDef = resolvedDef.default;
1686
- }
1687
- // save resolved on async factory in case it's used elsewhere
1688
- def.resolved = typeof resolvedDef === 'function'
1689
- ? resolvedDef
1690
- : _Kdu.extend(resolvedDef);
1691
- match.components[key] = resolvedDef;
1692
- pending--;
1693
- if (pending <= 0) {
1694
- next();
1695
- }
1696
- });
1697
-
1698
- var reject = once(function (reason) {
1699
- var msg = "Failed to resolve async component " + key + ": " + reason;
1700
- process.env.NODE_ENV !== 'production' && warn(false, msg);
1701
- if (!error) {
1702
- error = isError(reason)
1703
- ? reason
1704
- : new Error(msg);
1705
- next(error);
1706
- }
1707
- });
1708
-
1709
- var res;
1710
- try {
1711
- res = def(resolve, reject);
1712
- } catch (e) {
1713
- reject(e);
1714
- }
1715
- if (res) {
1716
- if (typeof res.then === 'function') {
1717
- res.then(resolve, reject);
1718
- } else {
1719
- // new syntax in Kdu
1720
- var comp = res.component;
1721
- if (comp && typeof comp.then === 'function') {
1722
- comp.then(resolve, reject);
1723
- }
1724
- }
1725
- }
1726
- }
1727
- });
1728
-
1729
- if (!hasAsync) { next(); }
1730
- }
1731
- }
1732
-
1733
- function flatMapComponents (
1734
- matched,
1735
- fn
1736
- ) {
1737
- return flatten(matched.map(function (m) {
1738
- return Object.keys(m.components).map(function (key) { return fn(
1739
- m.components[key],
1740
- m.instances[key],
1741
- m, key
1742
- ); })
1743
- }))
1744
- }
1745
-
1746
- function flatten (arr) {
1747
- return Array.prototype.concat.apply([], arr)
1748
- }
1749
-
1750
- // in Webpack 2, require.ensure now also returns a Promise
1751
- // so the resolve/reject functions may get called an extra time
1752
- // if the user uses an arrow function shorthand that happens to
1753
- // return that Promise.
1754
- function once (fn) {
1755
- var called = false;
1756
- return function () {
1757
- var args = [], len = arguments.length;
1758
- while ( len-- ) args[ len ] = arguments[ len ];
1759
-
1760
- if (called) { return }
1761
- called = true;
1762
- return fn.apply(this, args)
1763
- }
1764
- }
1765
-
1766
- /* */
1767
-
1768
- var History = function History (router, base) {
1769
- this.router = router;
1770
- this.base = normalizeBase(base);
1771
- // start with a route object that stands for "nowhere"
1772
- this.current = START;
1773
- this.pending = null;
1774
- this.ready = false;
1775
- this.readyCbs = [];
1776
- this.readyErrorCbs = [];
1777
- this.errorCbs = [];
1778
- };
1779
-
1780
- History.prototype.listen = function listen (cb) {
1781
- this.cb = cb;
1782
- };
1783
-
1784
- History.prototype.onReady = function onReady (cb, errorCb) {
1785
- if (this.ready) {
1786
- cb();
1787
- } else {
1788
- this.readyCbs.push(cb);
1789
- if (errorCb) {
1790
- this.readyErrorCbs.push(errorCb);
1791
- }
1792
- }
1793
- };
1794
-
1795
- History.prototype.onError = function onError (errorCb) {
1796
- this.errorCbs.push(errorCb);
1797
- };
1798
-
1799
- History.prototype.transitionTo = function transitionTo (location, onComplete, onAbort) {
1800
- var this$1 = this;
1801
-
1802
- var route = this.router.match(location, this.current);
1803
- this.confirmTransition(route, function () {
1804
- this$1.updateRoute(route);
1805
- onComplete && onComplete(route);
1806
- this$1.ensureURL();
1807
-
1808
- // fire ready cbs once
1809
- if (!this$1.ready) {
1810
- this$1.ready = true;
1811
- this$1.readyCbs.forEach(function (cb) { cb(route); });
1812
- }
1813
- }, function (err) {
1814
- if (onAbort) {
1815
- onAbort(err);
1816
- }
1817
- if (err && !this$1.ready) {
1818
- this$1.ready = true;
1819
- this$1.readyErrorCbs.forEach(function (cb) { cb(err); });
1820
- }
1821
- });
1822
- };
1823
-
1824
- History.prototype.confirmTransition = function confirmTransition (route, onComplete, onAbort) {
1825
- var this$1 = this;
1826
-
1827
- var current = this.current;
1828
- var abort = function (err) {
1829
- if (isError(err)) {
1830
- if (this$1.errorCbs.length) {
1831
- this$1.errorCbs.forEach(function (cb) { cb(err); });
1832
- } else {
1833
- warn(false, 'uncaught error during route navigation:');
1834
- console.error(err);
1835
- }
1836
- }
1837
- onAbort && onAbort(err);
1838
- };
1839
- if (
1840
- isSameRoute(route, current) &&
1841
- // in the case the route map has been dynamically appended to
1842
- route.matched.length === current.matched.length
1843
- ) {
1844
- this.ensureURL();
1845
- return abort()
1846
- }
1847
-
1848
- var ref = resolveQueue(this.current.matched, route.matched);
1849
- var updated = ref.updated;
1850
- var deactivated = ref.deactivated;
1851
- var activated = ref.activated;
1852
-
1853
- var queue = [].concat(
1854
- // in-component leave guards
1855
- extractLeaveGuards(deactivated),
1856
- // global before hooks
1857
- this.router.beforeHooks,
1858
- // in-component update hooks
1859
- extractUpdateHooks(updated),
1860
- // in-config enter guards
1861
- activated.map(function (m) { return m.beforeEnter; }),
1862
- // async components
1863
- resolveAsyncComponents(activated)
1864
- );
1865
-
1866
- this.pending = route;
1867
- var iterator = function (hook, next) {
1868
- if (this$1.pending !== route) {
1869
- return abort()
1870
- }
1871
- try {
1872
- hook(route, current, function (to) {
1873
- if (to === false || isError(to)) {
1874
- // next(false) -> abort navigation, ensure current URL
1875
- this$1.ensureURL(true);
1876
- abort(to);
1877
- } else if (
1878
- typeof to === 'string' ||
1879
- (typeof to === 'object' && (
1880
- typeof to.path === 'string' ||
1881
- typeof to.name === 'string'
1882
- ))
1883
- ) {
1884
- // next('/') or next({ path: '/' }) -> redirect
1885
- abort();
1886
- if (typeof to === 'object' && to.replace) {
1887
- this$1.replace(to);
1888
- } else {
1889
- this$1.push(to);
1890
- }
1891
- } else {
1892
- // confirm transition and pass on the value
1893
- next(to);
1894
- }
1895
- });
1896
- } catch (e) {
1897
- abort(e);
1898
- }
1899
- };
1900
-
1901
- runQueue(queue, iterator, function () {
1902
- var postEnterCbs = [];
1903
- var isValid = function () { return this$1.current === route; };
1904
- // wait until async components are resolved before
1905
- // extracting in-component enter guards
1906
- var enterGuards = extractEnterGuards(activated, postEnterCbs, isValid);
1907
- var queue = enterGuards.concat(this$1.router.resolveHooks);
1908
- runQueue(queue, iterator, function () {
1909
- if (this$1.pending !== route) {
1910
- return abort()
1911
- }
1912
- this$1.pending = null;
1913
- onComplete(route);
1914
- if (this$1.router.app) {
1915
- this$1.router.app.$nextTick(function () {
1916
- postEnterCbs.forEach(function (cb) { cb(); });
1917
- });
1918
- }
1919
- });
1920
- });
1921
- };
1922
-
1923
- History.prototype.updateRoute = function updateRoute (route) {
1924
- var prev = this.current;
1925
- this.current = route;
1926
- this.cb && this.cb(route);
1927
- this.router.afterHooks.forEach(function (hook) {
1928
- hook && hook(route, prev);
1929
- });
1930
- };
1931
-
1932
- function normalizeBase (base) {
1933
- if (!base) {
1934
- if (inBrowser) {
1935
- // respect <base> tag
1936
- var baseEl = document.querySelector('base');
1937
- base = (baseEl && baseEl.getAttribute('href')) || '/';
1938
- // strip full URL origin
1939
- base = base.replace(/^https?:\/\/[^\/]+/, '');
1940
- } else {
1941
- base = '/';
1942
- }
1943
- }
1944
- // make sure there's the starting slash
1945
- if (base.charAt(0) !== '/') {
1946
- base = '/' + base;
1947
- }
1948
- // remove trailing slash
1949
- return base.replace(/\/$/, '')
1950
- }
1951
-
1952
- function resolveQueue (
1953
- current,
1954
- next
1955
- ) {
1956
- var i;
1957
- var max = Math.max(current.length, next.length);
1958
- for (i = 0; i < max; i++) {
1959
- if (current[i] !== next[i]) {
1960
- break
1961
- }
1962
- }
1963
- return {
1964
- updated: next.slice(0, i),
1965
- activated: next.slice(i),
1966
- deactivated: current.slice(i)
1967
- }
1968
- }
1969
-
1970
- function extractGuards (
1971
- records,
1972
- name,
1973
- bind,
1974
- reverse
1975
- ) {
1976
- var guards = flatMapComponents(records, function (def, instance, match, key) {
1977
- var guard = extractGuard(def, name);
1978
- if (guard) {
1979
- return Array.isArray(guard)
1980
- ? guard.map(function (guard) { return bind(guard, instance, match, key); })
1981
- : bind(guard, instance, match, key)
1982
- }
1983
- });
1984
- return flatten(reverse ? guards.reverse() : guards)
1985
- }
1986
-
1987
- function extractGuard (
1988
- def,
1989
- key
1990
- ) {
1991
- if (typeof def !== 'function') {
1992
- // extend now so that global mixins are applied.
1993
- def = _Kdu.extend(def);
1994
- }
1995
- return def.options[key]
1996
- }
1997
-
1998
- function extractLeaveGuards (deactivated) {
1999
- return extractGuards(deactivated, 'beforeRouteLeave', bindGuard, true)
2000
- }
2001
-
2002
- function extractUpdateHooks (updated) {
2003
- return extractGuards(updated, 'beforeRouteUpdate', bindGuard)
2004
- }
2005
-
2006
- function bindGuard (guard, instance) {
2007
- if (instance) {
2008
- return function boundRouteGuard () {
2009
- return guard.apply(instance, arguments)
2010
- }
2011
- }
2012
- }
2013
-
2014
- function extractEnterGuards (
2015
- activated,
2016
- cbs,
2017
- isValid
2018
- ) {
2019
- return extractGuards(activated, 'beforeRouteEnter', function (guard, _, match, key) {
2020
- return bindEnterGuard(guard, match, key, cbs, isValid)
2021
- })
2022
- }
2023
-
2024
- function bindEnterGuard (
2025
- guard,
2026
- match,
2027
- key,
2028
- cbs,
2029
- isValid
2030
- ) {
2031
- return function routeEnterGuard (to, from, next) {
2032
- return guard(to, from, function (cb) {
2033
- next(cb);
2034
- if (typeof cb === 'function') {
2035
- cbs.push(function () {
2036
- // #750
2037
- // if a router-view is wrapped with an out-in transition,
2038
- // the instance may not have been registered at this time.
2039
- // we will need to poll for registration until current route
2040
- // is no longer valid.
2041
- poll(cb, match.instances, key, isValid);
2042
- });
2043
- }
2044
- })
2045
- }
2046
- }
2047
-
2048
- function poll (
2049
- cb, // somehow flow cannot infer this is a function
2050
- instances,
2051
- key,
2052
- isValid
2053
- ) {
2054
- if (instances[key]) {
2055
- cb(instances[key]);
2056
- } else if (isValid()) {
2057
- setTimeout(function () {
2058
- poll(cb, instances, key, isValid);
2059
- }, 16);
2060
- }
2061
- }
2062
-
2063
- /* */
2064
-
2065
-
2066
- var HTML5History = (function (History$$1) {
2067
- function HTML5History (router, base) {
2068
- var this$1 = this;
2069
-
2070
- History$$1.call(this, router, base);
2071
-
2072
- var expectScroll = router.options.scrollBehavior;
2073
-
2074
- if (expectScroll) {
2075
- setupScroll();
2076
- }
2077
-
2078
- window.addEventListener('popstate', function (e) {
2079
- var current = this$1.current;
2080
- this$1.transitionTo(getLocation(this$1.base), function (route) {
2081
- if (expectScroll) {
2082
- handleScroll(router, route, current, true);
2083
- }
2084
- });
2085
- });
2086
- }
2087
-
2088
- if ( History$$1 ) HTML5History.__proto__ = History$$1;
2089
- HTML5History.prototype = Object.create( History$$1 && History$$1.prototype );
2090
- HTML5History.prototype.constructor = HTML5History;
2091
-
2092
- HTML5History.prototype.go = function go (n) {
2093
- window.history.go(n);
2094
- };
2095
-
2096
- HTML5History.prototype.push = function push (location, onComplete, onAbort) {
2097
- var this$1 = this;
2098
-
2099
- var ref = this;
2100
- var fromRoute = ref.current;
2101
- this.transitionTo(location, function (route) {
2102
- pushState(cleanPath(this$1.base + route.fullPath));
2103
- handleScroll(this$1.router, route, fromRoute, false);
2104
- onComplete && onComplete(route);
2105
- }, onAbort);
2106
- };
2107
-
2108
- HTML5History.prototype.replace = function replace (location, onComplete, onAbort) {
2109
- var this$1 = this;
2110
-
2111
- var ref = this;
2112
- var fromRoute = ref.current;
2113
- this.transitionTo(location, function (route) {
2114
- replaceState(cleanPath(this$1.base + route.fullPath));
2115
- handleScroll(this$1.router, route, fromRoute, false);
2116
- onComplete && onComplete(route);
2117
- }, onAbort);
2118
- };
2119
-
2120
- HTML5History.prototype.ensureURL = function ensureURL (push) {
2121
- if (getLocation(this.base) !== this.current.fullPath) {
2122
- var current = cleanPath(this.base + this.current.fullPath);
2123
- push ? pushState(current) : replaceState(current);
2124
- }
2125
- };
2126
-
2127
- HTML5History.prototype.getCurrentLocation = function getCurrentLocation () {
2128
- return getLocation(this.base)
2129
- };
2130
-
2131
- return HTML5History;
2132
- }(History));
2133
-
2134
- function getLocation (base) {
2135
- var path = window.location.pathname;
2136
- if (base && path.indexOf(base) === 0) {
2137
- path = path.slice(base.length);
2138
- }
2139
- return (path || '/') + window.location.search + window.location.hash
2140
- }
2141
-
2142
- /* */
2143
-
2144
-
2145
- var HashHistory = (function (History$$1) {
2146
- function HashHistory (router, base, fallback) {
2147
- History$$1.call(this, router, base);
2148
- // check history fallback deeplinking
2149
- if (fallback && checkFallback(this.base)) {
2150
- return
2151
- }
2152
- ensureSlash();
2153
- }
2154
-
2155
- if ( History$$1 ) HashHistory.__proto__ = History$$1;
2156
- HashHistory.prototype = Object.create( History$$1 && History$$1.prototype );
2157
- HashHistory.prototype.constructor = HashHistory;
2158
-
2159
- // this is delayed until the app mounts
2160
- // to avoid the hashchange listener being fired too early
2161
- HashHistory.prototype.setupListeners = function setupListeners () {
2162
- var this$1 = this;
2163
-
2164
- window.addEventListener('hashchange', function () {
2165
- if (!ensureSlash()) {
2166
- return
2167
- }
2168
- this$1.transitionTo(getHash(), function (route) {
2169
- replaceHash(route.fullPath);
2170
- });
2171
- });
2172
- };
2173
-
2174
- HashHistory.prototype.push = function push (location, onComplete, onAbort) {
2175
- this.transitionTo(location, function (route) {
2176
- pushHash(route.fullPath);
2177
- onComplete && onComplete(route);
2178
- }, onAbort);
2179
- };
2180
-
2181
- HashHistory.prototype.replace = function replace (location, onComplete, onAbort) {
2182
- this.transitionTo(location, function (route) {
2183
- replaceHash(route.fullPath);
2184
- onComplete && onComplete(route);
2185
- }, onAbort);
2186
- };
2187
-
2188
- HashHistory.prototype.go = function go (n) {
2189
- window.history.go(n);
2190
- };
2191
-
2192
- HashHistory.prototype.ensureURL = function ensureURL (push) {
2193
- var current = this.current.fullPath;
2194
- if (getHash() !== current) {
2195
- push ? pushHash(current) : replaceHash(current);
2196
- }
2197
- };
2198
-
2199
- HashHistory.prototype.getCurrentLocation = function getCurrentLocation () {
2200
- return getHash()
2201
- };
2202
-
2203
- return HashHistory;
2204
- }(History));
2205
-
2206
- function checkFallback (base) {
2207
- var location = getLocation(base);
2208
- if (!/^\/#/.test(location)) {
2209
- window.location.replace(
2210
- cleanPath(base + '/#' + location)
2211
- );
2212
- return true
2213
- }
2214
- }
2215
-
2216
- function ensureSlash () {
2217
- var path = getHash();
2218
- if (path.charAt(0) === '/') {
2219
- return true
2220
- }
2221
- replaceHash('/' + path);
2222
- return false
2223
- }
2224
-
2225
- function getHash () {
2226
- // We can't use window.location.hash here because it's not
2227
- // consistent across browsers - Firefox will pre-decode it!
2228
- var href = window.location.href;
2229
- var index = href.indexOf('#');
2230
- return index === -1 ? '' : href.slice(index + 1)
2231
- }
2232
-
2233
- function pushHash (path) {
2234
- window.location.hash = path;
2235
- }
2236
-
2237
- 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));
2242
- }
2243
-
2244
- /* */
2245
-
2246
-
2247
- var AbstractHistory = (function (History$$1) {
2248
- function AbstractHistory (router, base) {
2249
- History$$1.call(this, router, base);
2250
- this.stack = [];
2251
- this.index = -1;
2252
- }
2253
-
2254
- if ( History$$1 ) AbstractHistory.__proto__ = History$$1;
2255
- AbstractHistory.prototype = Object.create( History$$1 && History$$1.prototype );
2256
- AbstractHistory.prototype.constructor = AbstractHistory;
2257
-
2258
- AbstractHistory.prototype.push = function push (location, onComplete, onAbort) {
2259
- var this$1 = this;
2260
-
2261
- this.transitionTo(location, function (route) {
2262
- this$1.stack = this$1.stack.slice(0, this$1.index + 1).concat(route);
2263
- this$1.index++;
2264
- onComplete && onComplete(route);
2265
- }, onAbort);
2266
- };
2267
-
2268
- AbstractHistory.prototype.replace = function replace (location, onComplete, onAbort) {
2269
- var this$1 = this;
2270
-
2271
- this.transitionTo(location, function (route) {
2272
- this$1.stack = this$1.stack.slice(0, this$1.index).concat(route);
2273
- onComplete && onComplete(route);
2274
- }, onAbort);
2275
- };
2276
-
2277
- AbstractHistory.prototype.go = function go (n) {
2278
- var this$1 = this;
2279
-
2280
- var targetIndex = this.index + n;
2281
- if (targetIndex < 0 || targetIndex >= this.stack.length) {
2282
- return
2283
- }
2284
- var route = this.stack[targetIndex];
2285
- this.confirmTransition(route, function () {
2286
- this$1.index = targetIndex;
2287
- this$1.updateRoute(route);
2288
- });
2289
- };
2290
-
2291
- AbstractHistory.prototype.getCurrentLocation = function getCurrentLocation () {
2292
- var current = this.stack[this.stack.length - 1];
2293
- return current ? current.fullPath : '/'
2294
- };
2295
-
2296
- AbstractHistory.prototype.ensureURL = function ensureURL () {
2297
- // noop
2298
- };
2299
-
2300
- return AbstractHistory;
2301
- }(History));
2302
-
2303
- /* */
2304
-
2305
- var KduRouter = function KduRouter (options) {
2306
- if ( options === void 0 ) options = {};
2307
-
2308
- this.app = null;
2309
- this.apps = [];
2310
- this.options = options;
2311
- this.beforeHooks = [];
2312
- this.resolveHooks = [];
2313
- this.afterHooks = [];
2314
- this.matcher = createMatcher(options.routes || [], this);
2315
-
2316
- var mode = options.mode || 'hash';
2317
- this.fallback = mode === 'history' && !supportsPushState && options.fallback !== false;
2318
- if (this.fallback) {
2319
- mode = 'hash';
2320
- }
2321
- if (!inBrowser) {
2322
- mode = 'abstract';
2323
- }
2324
- this.mode = mode;
2325
-
2326
- switch (mode) {
2327
- case 'history':
2328
- this.history = new HTML5History(this, options.base);
2329
- break
2330
- case 'hash':
2331
- this.history = new HashHistory(this, options.base, this.fallback);
2332
- break
2333
- case 'abstract':
2334
- this.history = new AbstractHistory(this, options.base);
2335
- break
2336
- default:
2337
- if (process.env.NODE_ENV !== 'production') {
2338
- assert(false, ("invalid mode: " + mode));
2339
- }
2340
- }
2341
- };
2342
-
2343
- var prototypeAccessors = { currentRoute: {} };
2344
-
2345
- KduRouter.prototype.match = function match (
2346
- raw,
2347
- current,
2348
- redirectedFrom
2349
- ) {
2350
- return this.matcher.match(raw, current, redirectedFrom)
2351
- };
2352
-
2353
- prototypeAccessors.currentRoute.get = function () {
2354
- return this.history && this.history.current
2355
- };
2356
-
2357
- KduRouter.prototype.init = function init (app /* Kdu component instance */) {
2358
- var this$1 = this;
2359
-
2360
- process.env.NODE_ENV !== 'production' && assert(
2361
- install.installed,
2362
- "not installed. Make sure to call `Kdu.use(KduRouter)` " +
2363
- "before creating root instance."
2364
- );
2365
-
2366
- this.apps.push(app);
2367
-
2368
- // main app already initialized.
2369
- if (this.app) {
2370
- return
2371
- }
2372
-
2373
- this.app = app;
2374
-
2375
- var history = this.history;
2376
-
2377
- if (history instanceof HTML5History) {
2378
- history.transitionTo(history.getCurrentLocation());
2379
- } else if (history instanceof HashHistory) {
2380
- var setupHashListener = function () {
2381
- history.setupListeners();
2382
- };
2383
- history.transitionTo(
2384
- history.getCurrentLocation(),
2385
- setupHashListener,
2386
- setupHashListener
2387
- );
2388
- }
2389
-
2390
- history.listen(function (route) {
2391
- this$1.apps.forEach(function (app) {
2392
- app._route = route;
2393
- });
2394
- });
2395
- };
2396
-
2397
- KduRouter.prototype.beforeEach = function beforeEach (fn) {
2398
- return registerHook(this.beforeHooks, fn)
2399
- };
2400
-
2401
- KduRouter.prototype.beforeResolve = function beforeResolve (fn) {
2402
- return registerHook(this.resolveHooks, fn)
2403
- };
2404
-
2405
- KduRouter.prototype.afterEach = function afterEach (fn) {
2406
- return registerHook(this.afterHooks, fn)
2407
- };
2408
-
2409
- KduRouter.prototype.onReady = function onReady (cb, errorCb) {
2410
- this.history.onReady(cb, errorCb);
2411
- };
2412
-
2413
- KduRouter.prototype.onError = function onError (errorCb) {
2414
- this.history.onError(errorCb);
2415
- };
2416
-
2417
- KduRouter.prototype.push = function push (location, onComplete, onAbort) {
2418
- this.history.push(location, onComplete, onAbort);
2419
- };
2420
-
2421
- KduRouter.prototype.replace = function replace (location, onComplete, onAbort) {
2422
- this.history.replace(location, onComplete, onAbort);
2423
- };
2424
-
2425
- KduRouter.prototype.go = function go (n) {
2426
- this.history.go(n);
2427
- };
2428
-
2429
- KduRouter.prototype.back = function back () {
2430
- this.go(-1);
2431
- };
2432
-
2433
- KduRouter.prototype.forward = function forward () {
2434
- this.go(1);
2435
- };
2436
-
2437
- KduRouter.prototype.getMatchedComponents = function getMatchedComponents (to) {
2438
- var route = to
2439
- ? to.matched
2440
- ? to
2441
- : this.resolve(to).route
2442
- : this.currentRoute;
2443
- if (!route) {
2444
- return []
2445
- }
2446
- return [].concat.apply([], route.matched.map(function (m) {
2447
- return Object.keys(m.components).map(function (key) {
2448
- return m.components[key]
2449
- })
2450
- }))
2451
- };
2452
-
2453
- KduRouter.prototype.resolve = function resolve (
2454
- to,
2455
- current,
2456
- append
2457
- ) {
2458
- var location = normalizeLocation(
2459
- to,
2460
- current || this.history.current,
2461
- append,
2462
- this
2463
- );
2464
- var route = this.match(location, current);
2465
- var fullPath = route.redirectedFrom || route.fullPath;
2466
- var base = this.history.base;
2467
- var href = createHref(base, fullPath, this.mode);
2468
- return {
2469
- location: location,
2470
- route: route,
2471
- href: href,
2472
- // for backwards compat
2473
- normalizedTo: location,
2474
- resolved: route
2475
- }
2476
- };
2477
-
2478
- KduRouter.prototype.addRoutes = function addRoutes (routes) {
2479
- this.matcher.addRoutes(routes);
2480
- if (this.history.current !== START) {
2481
- this.history.transitionTo(this.history.getCurrentLocation());
2482
- }
2483
- };
2484
-
2485
- Object.defineProperties( KduRouter.prototype, prototypeAccessors );
2486
-
2487
- function registerHook (list, fn) {
2488
- list.push(fn);
2489
- return function () {
2490
- var i = list.indexOf(fn);
2491
- if (i > -1) { list.splice(i, 1); }
2492
- }
2493
- }
2494
-
2495
- function createHref (base, fullPath, mode) {
2496
- var path = mode === 'hash' ? '#' + fullPath : fullPath;
2497
- return base ? cleanPath(base + '/' + path) : path
2498
- }
2499
-
2500
- KduRouter.install = install;
2501
- KduRouter.version = '2.7.0';
2502
-
2503
- if (inBrowser && window.Kdu) {
2504
- window.Kdu.use(KduRouter);
2505
- }
2506
-
2507
- module.exports = KduRouter;