vueonrails 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.md +21 -0
  3. data/README.md +7 -7
  4. data/lib/generators/generator_templates/forms/index.vue.erb +45 -0
  5. data/lib/generators/generator_templates/packs/index.js +13 -13
  6. data/lib/generators/generator_templates/packs/index.vue +3 -3
  7. data/lib/generators/generator_templates/packs/pack.js.erb +3 -3
  8. data/lib/generators/generator_templates/sfc/single-file-component.vue +3 -3
  9. data/lib/generators/generator_templates/tests/unit.test.js.erb +2 -2
  10. data/lib/generators/generator_templates/turbolinks/turbolinks-pack.js.erb +3 -3
  11. data/lib/generators/options/child.rb +6 -0
  12. data/lib/generators/options/click.rb +0 -1
  13. data/lib/generators/options/form.rb +1 -19
  14. data/lib/generators/options/list.rb +0 -1
  15. data/lib/generators/options/modal.rb +0 -1
  16. data/lib/generators/options/parent.rb +3 -0
  17. data/lib/generators/options/seperate.rb +0 -1
  18. data/lib/generators/options/single.rb +0 -1
  19. data/lib/generators/options/table.rb +0 -1
  20. data/lib/generators/options/test.rb +1 -2
  21. data/lib/generators/options/turbolinks-seperate.rb +0 -1
  22. data/lib/generators/options/turbolinks-single.rb +0 -1
  23. data/lib/generators/options/vuex.rb +0 -1
  24. data/lib/generators/vue/vue_generator.rb +76 -18
  25. data/lib/install/setup.rb +4 -5
  26. data/lib/install/spv.rb +0 -1
  27. data/lib/install/test.rb +0 -3
  28. data/lib/install/ui.rb +0 -3
  29. data/lib/vueonrails/post_message.rb +1 -1
  30. data/lib/vueonrails/version.rb +1 -1
  31. metadata +10 -23
  32. data/vendor/assets/javascripts/axios.js +0 -1545
  33. data/vendor/assets/javascripts/axios.map +0 -1
  34. data/vendor/assets/javascripts/element-ui.js +0 -12
  35. data/vendor/assets/javascripts/vue-resource.js +0 -1531
  36. data/vendor/assets/javascripts/vue-router.js +0 -2709
  37. data/vendor/assets/javascripts/vue-router2.js +0 -2284
  38. data/vendor/assets/javascripts/vue-validator.js +0 -910
  39. data/vendor/assets/javascripts/vue-validator2.js +0 -2615
  40. data/vendor/assets/javascripts/vue-validator3.js +0 -2054
  41. data/vendor/assets/javascripts/vue.js +0 -10237
  42. data/vendor/assets/javascripts/vue.min.js +0 -9
  43. data/vendor/assets/javascripts/vue2.js +0 -8568
  44. data/vendor/assets/javascripts/vue2.min.js +0 -8
  45. data/vendor/assets/javascripts/vueonrails.js +0 -39
  46. data/vendor/assets/javascripts/vuex.js +0 -722
  47. data/vendor/assets/javascripts/vuex2.js +0 -805
  48. data/vendor/assets/stylesheets/element-ui.css +0 -1
@@ -1,2709 +0,0 @@
1
- /*!
2
- * vue-router v0.7.13
3
- * (c) 2016 Evan You
4
- * Released under the MIT License.
5
- */
6
- (function (global, factory) {
7
- typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
8
- typeof define === 'function' && define.amd ? define(factory) :
9
- global.VueRouter = factory();
10
- }(this, function () { 'use strict';
11
-
12
- var babelHelpers = {};
13
-
14
- babelHelpers.classCallCheck = function (instance, Constructor) {
15
- if (!(instance instanceof Constructor)) {
16
- throw new TypeError("Cannot call a class as a function");
17
- }
18
- };
19
- function Target(path, matcher, delegate) {
20
- this.path = path;
21
- this.matcher = matcher;
22
- this.delegate = delegate;
23
- }
24
-
25
- Target.prototype = {
26
- to: function to(target, callback) {
27
- var delegate = this.delegate;
28
-
29
- if (delegate && delegate.willAddRoute) {
30
- target = delegate.willAddRoute(this.matcher.target, target);
31
- }
32
-
33
- this.matcher.add(this.path, target);
34
-
35
- if (callback) {
36
- if (callback.length === 0) {
37
- throw new Error("You must have an argument in the function passed to `to`");
38
- }
39
- this.matcher.addChild(this.path, target, callback, this.delegate);
40
- }
41
- return this;
42
- }
43
- };
44
-
45
- function Matcher(target) {
46
- this.routes = {};
47
- this.children = {};
48
- this.target = target;
49
- }
50
-
51
- Matcher.prototype = {
52
- add: function add(path, handler) {
53
- this.routes[path] = handler;
54
- },
55
-
56
- addChild: function addChild(path, target, callback, delegate) {
57
- var matcher = new Matcher(target);
58
- this.children[path] = matcher;
59
-
60
- var match = generateMatch(path, matcher, delegate);
61
-
62
- if (delegate && delegate.contextEntered) {
63
- delegate.contextEntered(target, match);
64
- }
65
-
66
- callback(match);
67
- }
68
- };
69
-
70
- function generateMatch(startingPath, matcher, delegate) {
71
- return function (path, nestedCallback) {
72
- var fullPath = startingPath + path;
73
-
74
- if (nestedCallback) {
75
- nestedCallback(generateMatch(fullPath, matcher, delegate));
76
- } else {
77
- return new Target(startingPath + path, matcher, delegate);
78
- }
79
- };
80
- }
81
-
82
- function addRoute(routeArray, path, handler) {
83
- var len = 0;
84
- for (var i = 0, l = routeArray.length; i < l; i++) {
85
- len += routeArray[i].path.length;
86
- }
87
-
88
- path = path.substr(len);
89
- var route = { path: path, handler: handler };
90
- routeArray.push(route);
91
- }
92
-
93
- function eachRoute(baseRoute, matcher, callback, binding) {
94
- var routes = matcher.routes;
95
-
96
- for (var path in routes) {
97
- if (routes.hasOwnProperty(path)) {
98
- var routeArray = baseRoute.slice();
99
- addRoute(routeArray, path, routes[path]);
100
-
101
- if (matcher.children[path]) {
102
- eachRoute(routeArray, matcher.children[path], callback, binding);
103
- } else {
104
- callback.call(binding, routeArray);
105
- }
106
- }
107
- }
108
- }
109
-
110
- function map (callback, addRouteCallback) {
111
- var matcher = new Matcher();
112
-
113
- callback(generateMatch("", matcher, this.delegate));
114
-
115
- eachRoute([], matcher, function (route) {
116
- if (addRouteCallback) {
117
- addRouteCallback(this, route);
118
- } else {
119
- this.add(route);
120
- }
121
- }, this);
122
- }
123
-
124
- var specials = ['/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\'];
125
-
126
- var escapeRegex = new RegExp('(\\' + specials.join('|\\') + ')', 'g');
127
-
128
- var noWarning = false;
129
- function warn(msg) {
130
- if (!noWarning && typeof console !== 'undefined') {
131
- console.error('[vue-router] ' + msg);
132
- }
133
- }
134
-
135
- function tryDecode(uri, asComponent) {
136
- try {
137
- return asComponent ? decodeURIComponent(uri) : decodeURI(uri);
138
- } catch (e) {
139
- warn('malformed URI' + (asComponent ? ' component: ' : ': ') + uri);
140
- }
141
- }
142
-
143
- function isArray(test) {
144
- return Object.prototype.toString.call(test) === "[object Array]";
145
- }
146
-
147
- // A Segment represents a segment in the original route description.
148
- // Each Segment type provides an `eachChar` and `regex` method.
149
- //
150
- // The `eachChar` method invokes the callback with one or more character
151
- // specifications. A character specification consumes one or more input
152
- // characters.
153
- //
154
- // The `regex` method returns a regex fragment for the segment. If the
155
- // segment is a dynamic of star segment, the regex fragment also includes
156
- // a capture.
157
- //
158
- // A character specification contains:
159
- //
160
- // * `validChars`: a String with a list of all valid characters, or
161
- // * `invalidChars`: a String with a list of all invalid characters
162
- // * `repeat`: true if the character specification can repeat
163
-
164
- function StaticSegment(string) {
165
- this.string = string;
166
- }
167
- StaticSegment.prototype = {
168
- eachChar: function eachChar(callback) {
169
- var string = this.string,
170
- ch;
171
-
172
- for (var i = 0, l = string.length; i < l; i++) {
173
- ch = string.charAt(i);
174
- callback({ validChars: ch });
175
- }
176
- },
177
-
178
- regex: function regex() {
179
- return this.string.replace(escapeRegex, '\\$1');
180
- },
181
-
182
- generate: function generate() {
183
- return this.string;
184
- }
185
- };
186
-
187
- function DynamicSegment(name) {
188
- this.name = name;
189
- }
190
- DynamicSegment.prototype = {
191
- eachChar: function eachChar(callback) {
192
- callback({ invalidChars: "/", repeat: true });
193
- },
194
-
195
- regex: function regex() {
196
- return "([^/]+)";
197
- },
198
-
199
- generate: function generate(params) {
200
- var val = params[this.name];
201
- return val == null ? ":" + this.name : val;
202
- }
203
- };
204
-
205
- function StarSegment(name) {
206
- this.name = name;
207
- }
208
- StarSegment.prototype = {
209
- eachChar: function eachChar(callback) {
210
- callback({ invalidChars: "", repeat: true });
211
- },
212
-
213
- regex: function regex() {
214
- return "(.+)";
215
- },
216
-
217
- generate: function generate(params) {
218
- var val = params[this.name];
219
- return val == null ? ":" + this.name : val;
220
- }
221
- };
222
-
223
- function EpsilonSegment() {}
224
- EpsilonSegment.prototype = {
225
- eachChar: function eachChar() {},
226
- regex: function regex() {
227
- return "";
228
- },
229
- generate: function generate() {
230
- return "";
231
- }
232
- };
233
-
234
- function parse(route, names, specificity) {
235
- // normalize route as not starting with a "/". Recognition will
236
- // also normalize.
237
- if (route.charAt(0) === "/") {
238
- route = route.substr(1);
239
- }
240
-
241
- var segments = route.split("/"),
242
- results = [];
243
-
244
- // A routes has specificity determined by the order that its different segments
245
- // appear in. This system mirrors how the magnitude of numbers written as strings
246
- // works.
247
- // Consider a number written as: "abc". An example would be "200". Any other number written
248
- // "xyz" will be smaller than "abc" so long as `a > z`. For instance, "199" is smaller
249
- // then "200", even though "y" and "z" (which are both 9) are larger than "0" (the value
250
- // of (`b` and `c`). This is because the leading symbol, "2", is larger than the other
251
- // leading symbol, "1".
252
- // The rule is that symbols to the left carry more weight than symbols to the right
253
- // when a number is written out as a string. In the above strings, the leading digit
254
- // represents how many 100's are in the number, and it carries more weight than the middle
255
- // number which represents how many 10's are in the number.
256
- // This system of number magnitude works well for route specificity, too. A route written as
257
- // `a/b/c` will be more specific than `x/y/z` as long as `a` is more specific than
258
- // `x`, irrespective of the other parts.
259
- // Because of this similarity, we assign each type of segment a number value written as a
260
- // string. We can find the specificity of compound routes by concatenating these strings
261
- // together, from left to right. After we have looped through all of the segments,
262
- // we convert the string to a number.
263
- specificity.val = '';
264
-
265
- for (var i = 0, l = segments.length; i < l; i++) {
266
- var segment = segments[i],
267
- match;
268
-
269
- if (match = segment.match(/^:([^\/]+)$/)) {
270
- results.push(new DynamicSegment(match[1]));
271
- names.push(match[1]);
272
- specificity.val += '3';
273
- } else if (match = segment.match(/^\*([^\/]+)$/)) {
274
- results.push(new StarSegment(match[1]));
275
- specificity.val += '2';
276
- names.push(match[1]);
277
- } else if (segment === "") {
278
- results.push(new EpsilonSegment());
279
- specificity.val += '1';
280
- } else {
281
- results.push(new StaticSegment(segment));
282
- specificity.val += '4';
283
- }
284
- }
285
-
286
- specificity.val = +specificity.val;
287
-
288
- return results;
289
- }
290
-
291
- // A State has a character specification and (`charSpec`) and a list of possible
292
- // subsequent states (`nextStates`).
293
- //
294
- // If a State is an accepting state, it will also have several additional
295
- // properties:
296
- //
297
- // * `regex`: A regular expression that is used to extract parameters from paths
298
- // that reached this accepting state.
299
- // * `handlers`: Information on how to convert the list of captures into calls
300
- // to registered handlers with the specified parameters
301
- // * `types`: How many static, dynamic or star segments in this route. Used to
302
- // decide which route to use if multiple registered routes match a path.
303
- //
304
- // Currently, State is implemented naively by looping over `nextStates` and
305
- // comparing a character specification against a character. A more efficient
306
- // implementation would use a hash of keys pointing at one or more next states.
307
-
308
- function State(charSpec) {
309
- this.charSpec = charSpec;
310
- this.nextStates = [];
311
- }
312
-
313
- State.prototype = {
314
- get: function get(charSpec) {
315
- var nextStates = this.nextStates;
316
-
317
- for (var i = 0, l = nextStates.length; i < l; i++) {
318
- var child = nextStates[i];
319
-
320
- var isEqual = child.charSpec.validChars === charSpec.validChars;
321
- isEqual = isEqual && child.charSpec.invalidChars === charSpec.invalidChars;
322
-
323
- if (isEqual) {
324
- return child;
325
- }
326
- }
327
- },
328
-
329
- put: function put(charSpec) {
330
- var state;
331
-
332
- // If the character specification already exists in a child of the current
333
- // state, just return that state.
334
- if (state = this.get(charSpec)) {
335
- return state;
336
- }
337
-
338
- // Make a new state for the character spec
339
- state = new State(charSpec);
340
-
341
- // Insert the new state as a child of the current state
342
- this.nextStates.push(state);
343
-
344
- // If this character specification repeats, insert the new state as a child
345
- // of itself. Note that this will not trigger an infinite loop because each
346
- // transition during recognition consumes a character.
347
- if (charSpec.repeat) {
348
- state.nextStates.push(state);
349
- }
350
-
351
- // Return the new state
352
- return state;
353
- },
354
-
355
- // Find a list of child states matching the next character
356
- match: function match(ch) {
357
- // DEBUG "Processing `" + ch + "`:"
358
- var nextStates = this.nextStates,
359
- child,
360
- charSpec,
361
- chars;
362
-
363
- // DEBUG " " + debugState(this)
364
- var returned = [];
365
-
366
- for (var i = 0, l = nextStates.length; i < l; i++) {
367
- child = nextStates[i];
368
-
369
- charSpec = child.charSpec;
370
-
371
- if (typeof (chars = charSpec.validChars) !== 'undefined') {
372
- if (chars.indexOf(ch) !== -1) {
373
- returned.push(child);
374
- }
375
- } else if (typeof (chars = charSpec.invalidChars) !== 'undefined') {
376
- if (chars.indexOf(ch) === -1) {
377
- returned.push(child);
378
- }
379
- }
380
- }
381
-
382
- return returned;
383
- }
384
-
385
- /** IF DEBUG
386
- , debug: function() {
387
- var charSpec = this.charSpec,
388
- debug = "[",
389
- chars = charSpec.validChars || charSpec.invalidChars;
390
- if (charSpec.invalidChars) { debug += "^"; }
391
- debug += chars;
392
- debug += "]";
393
- if (charSpec.repeat) { debug += "+"; }
394
- return debug;
395
- }
396
- END IF **/
397
- };
398
-
399
- /** IF DEBUG
400
- function debug(log) {
401
- console.log(log);
402
- }
403
-
404
- function debugState(state) {
405
- return state.nextStates.map(function(n) {
406
- if (n.nextStates.length === 0) { return "( " + n.debug() + " [accepting] )"; }
407
- return "( " + n.debug() + " <then> " + n.nextStates.map(function(s) { return s.debug() }).join(" or ") + " )";
408
- }).join(", ")
409
- }
410
- END IF **/
411
-
412
- // Sort the routes by specificity
413
- function sortSolutions(states) {
414
- return states.sort(function (a, b) {
415
- return b.specificity.val - a.specificity.val;
416
- });
417
- }
418
-
419
- function recognizeChar(states, ch) {
420
- var nextStates = [];
421
-
422
- for (var i = 0, l = states.length; i < l; i++) {
423
- var state = states[i];
424
-
425
- nextStates = nextStates.concat(state.match(ch));
426
- }
427
-
428
- return nextStates;
429
- }
430
-
431
- var oCreate = Object.create || function (proto) {
432
- function F() {}
433
- F.prototype = proto;
434
- return new F();
435
- };
436
-
437
- function RecognizeResults(queryParams) {
438
- this.queryParams = queryParams || {};
439
- }
440
- RecognizeResults.prototype = oCreate({
441
- splice: Array.prototype.splice,
442
- slice: Array.prototype.slice,
443
- push: Array.prototype.push,
444
- length: 0,
445
- queryParams: null
446
- });
447
-
448
- function findHandler(state, path, queryParams) {
449
- var handlers = state.handlers,
450
- regex = state.regex;
451
- var captures = path.match(regex),
452
- currentCapture = 1;
453
- var result = new RecognizeResults(queryParams);
454
-
455
- for (var i = 0, l = handlers.length; i < l; i++) {
456
- var handler = handlers[i],
457
- names = handler.names,
458
- params = {};
459
-
460
- for (var j = 0, m = names.length; j < m; j++) {
461
- params[names[j]] = captures[currentCapture++];
462
- }
463
-
464
- result.push({ handler: handler.handler, params: params, isDynamic: !!names.length });
465
- }
466
-
467
- return result;
468
- }
469
-
470
- function addSegment(currentState, segment) {
471
- segment.eachChar(function (ch) {
472
- var state;
473
-
474
- currentState = currentState.put(ch);
475
- });
476
-
477
- return currentState;
478
- }
479
-
480
- function decodeQueryParamPart(part) {
481
- // http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1
482
- part = part.replace(/\+/gm, '%20');
483
- return tryDecode(part, true);
484
- }
485
-
486
- // The main interface
487
-
488
- var RouteRecognizer = function RouteRecognizer() {
489
- this.rootState = new State();
490
- this.names = {};
491
- };
492
-
493
- RouteRecognizer.prototype = {
494
- add: function add(routes, options) {
495
- var currentState = this.rootState,
496
- regex = "^",
497
- specificity = {},
498
- handlers = [],
499
- allSegments = [],
500
- name;
501
-
502
- var isEmpty = true;
503
-
504
- for (var i = 0, l = routes.length; i < l; i++) {
505
- var route = routes[i],
506
- names = [];
507
-
508
- var segments = parse(route.path, names, specificity);
509
-
510
- allSegments = allSegments.concat(segments);
511
-
512
- for (var j = 0, m = segments.length; j < m; j++) {
513
- var segment = segments[j];
514
-
515
- if (segment instanceof EpsilonSegment) {
516
- continue;
517
- }
518
-
519
- isEmpty = false;
520
-
521
- // Add a "/" for the new segment
522
- currentState = currentState.put({ validChars: "/" });
523
- regex += "/";
524
-
525
- // Add a representation of the segment to the NFA and regex
526
- currentState = addSegment(currentState, segment);
527
- regex += segment.regex();
528
- }
529
-
530
- var handler = { handler: route.handler, names: names };
531
- handlers.push(handler);
532
- }
533
-
534
- if (isEmpty) {
535
- currentState = currentState.put({ validChars: "/" });
536
- regex += "/";
537
- }
538
-
539
- currentState.handlers = handlers;
540
- currentState.regex = new RegExp(regex + "$");
541
- currentState.specificity = specificity;
542
-
543
- if (name = options && options.as) {
544
- this.names[name] = {
545
- segments: allSegments,
546
- handlers: handlers
547
- };
548
- }
549
- },
550
-
551
- handlersFor: function handlersFor(name) {
552
- var route = this.names[name],
553
- result = [];
554
- if (!route) {
555
- throw new Error("There is no route named " + name);
556
- }
557
-
558
- for (var i = 0, l = route.handlers.length; i < l; i++) {
559
- result.push(route.handlers[i]);
560
- }
561
-
562
- return result;
563
- },
564
-
565
- hasRoute: function hasRoute(name) {
566
- return !!this.names[name];
567
- },
568
-
569
- generate: function generate(name, params) {
570
- var route = this.names[name],
571
- output = "";
572
- if (!route) {
573
- throw new Error("There is no route named " + name);
574
- }
575
-
576
- var segments = route.segments;
577
-
578
- for (var i = 0, l = segments.length; i < l; i++) {
579
- var segment = segments[i];
580
-
581
- if (segment instanceof EpsilonSegment) {
582
- continue;
583
- }
584
-
585
- output += "/";
586
- output += segment.generate(params);
587
- }
588
-
589
- if (output.charAt(0) !== '/') {
590
- output = '/' + output;
591
- }
592
-
593
- if (params && params.queryParams) {
594
- output += this.generateQueryString(params.queryParams);
595
- }
596
-
597
- return output;
598
- },
599
-
600
- generateQueryString: function generateQueryString(params) {
601
- var pairs = [];
602
- var keys = [];
603
- for (var key in params) {
604
- if (params.hasOwnProperty(key)) {
605
- keys.push(key);
606
- }
607
- }
608
- keys.sort();
609
- for (var i = 0, len = keys.length; i < len; i++) {
610
- key = keys[i];
611
- var value = params[key];
612
- if (value == null) {
613
- continue;
614
- }
615
- var pair = encodeURIComponent(key);
616
- if (isArray(value)) {
617
- for (var j = 0, l = value.length; j < l; j++) {
618
- var arrayPair = key + '[]' + '=' + encodeURIComponent(value[j]);
619
- pairs.push(arrayPair);
620
- }
621
- } else {
622
- pair += "=" + encodeURIComponent(value);
623
- pairs.push(pair);
624
- }
625
- }
626
-
627
- if (pairs.length === 0) {
628
- return '';
629
- }
630
-
631
- return "?" + pairs.join("&");
632
- },
633
-
634
- parseQueryString: function parseQueryString(queryString) {
635
- var pairs = queryString.split("&"),
636
- queryParams = {};
637
- for (var i = 0; i < pairs.length; i++) {
638
- var pair = pairs[i].split('='),
639
- key = decodeQueryParamPart(pair[0]),
640
- keyLength = key.length,
641
- isArray = false,
642
- value;
643
- if (pair.length === 1) {
644
- value = 'true';
645
- } else {
646
- //Handle arrays
647
- if (keyLength > 2 && key.slice(keyLength - 2) === '[]') {
648
- isArray = true;
649
- key = key.slice(0, keyLength - 2);
650
- if (!queryParams[key]) {
651
- queryParams[key] = [];
652
- }
653
- }
654
- value = pair[1] ? decodeQueryParamPart(pair[1]) : '';
655
- }
656
- if (isArray) {
657
- queryParams[key].push(value);
658
- } else {
659
- queryParams[key] = value;
660
- }
661
- }
662
- return queryParams;
663
- },
664
-
665
- recognize: function recognize(path, silent) {
666
- noWarning = silent;
667
- var states = [this.rootState],
668
- pathLen,
669
- i,
670
- l,
671
- queryStart,
672
- queryParams = {},
673
- isSlashDropped = false;
674
-
675
- queryStart = path.indexOf('?');
676
- if (queryStart !== -1) {
677
- var queryString = path.substr(queryStart + 1, path.length);
678
- path = path.substr(0, queryStart);
679
- if (queryString) {
680
- queryParams = this.parseQueryString(queryString);
681
- }
682
- }
683
-
684
- path = tryDecode(path);
685
- if (!path) return;
686
-
687
- // DEBUG GROUP path
688
-
689
- if (path.charAt(0) !== "/") {
690
- path = "/" + path;
691
- }
692
-
693
- pathLen = path.length;
694
- if (pathLen > 1 && path.charAt(pathLen - 1) === "/") {
695
- path = path.substr(0, pathLen - 1);
696
- isSlashDropped = true;
697
- }
698
-
699
- for (i = 0, l = path.length; i < l; i++) {
700
- states = recognizeChar(states, path.charAt(i));
701
- if (!states.length) {
702
- break;
703
- }
704
- }
705
-
706
- // END DEBUG GROUP
707
-
708
- var solutions = [];
709
- for (i = 0, l = states.length; i < l; i++) {
710
- if (states[i].handlers) {
711
- solutions.push(states[i]);
712
- }
713
- }
714
-
715
- states = sortSolutions(solutions);
716
-
717
- var state = solutions[0];
718
-
719
- if (state && state.handlers) {
720
- // if a trailing slash was dropped and a star segment is the last segment
721
- // specified, put the trailing slash back
722
- if (isSlashDropped && state.regex.source.slice(-5) === "(.+)$") {
723
- path = path + "/";
724
- }
725
- return findHandler(state, path, queryParams);
726
- }
727
- }
728
- };
729
-
730
- RouteRecognizer.prototype.map = map;
731
-
732
- var genQuery = RouteRecognizer.prototype.generateQueryString;
733
-
734
- // export default for holding the Vue reference
735
- var exports$1 = {};
736
- /**
737
- * Warn stuff.
738
- *
739
- * @param {String} msg
740
- */
741
-
742
- function warn$1(msg) {
743
- /* istanbul ignore next */
744
- if (typeof console !== 'undefined') {
745
- console.error('[vue-router] ' + msg);
746
- }
747
- }
748
-
749
- /**
750
- * Resolve a relative path.
751
- *
752
- * @param {String} base
753
- * @param {String} relative
754
- * @param {Boolean} append
755
- * @return {String}
756
- */
757
-
758
- function resolvePath(base, relative, append) {
759
- var query = base.match(/(\?.*)$/);
760
- if (query) {
761
- query = query[1];
762
- base = base.slice(0, -query.length);
763
- }
764
- // a query!
765
- if (relative.charAt(0) === '?') {
766
- return base + relative;
767
- }
768
- var stack = base.split('/');
769
- // remove trailing segment if:
770
- // - not appending
771
- // - appending to trailing slash (last segment is empty)
772
- if (!append || !stack[stack.length - 1]) {
773
- stack.pop();
774
- }
775
- // resolve relative path
776
- var segments = relative.replace(/^\//, '').split('/');
777
- for (var i = 0; i < segments.length; i++) {
778
- var segment = segments[i];
779
- if (segment === '.') {
780
- continue;
781
- } else if (segment === '..') {
782
- stack.pop();
783
- } else {
784
- stack.push(segment);
785
- }
786
- }
787
- // ensure leading slash
788
- if (stack[0] !== '') {
789
- stack.unshift('');
790
- }
791
- return stack.join('/');
792
- }
793
-
794
- /**
795
- * Forgiving check for a promise
796
- *
797
- * @param {Object} p
798
- * @return {Boolean}
799
- */
800
-
801
- function isPromise(p) {
802
- return p && typeof p.then === 'function';
803
- }
804
-
805
- /**
806
- * Retrive a route config field from a component instance
807
- * OR a component contructor.
808
- *
809
- * @param {Function|Vue} component
810
- * @param {String} name
811
- * @return {*}
812
- */
813
-
814
- function getRouteConfig(component, name) {
815
- var options = component && (component.$options || component.options);
816
- return options && options.route && options.route[name];
817
- }
818
-
819
- /**
820
- * Resolve an async component factory. Have to do a dirty
821
- * mock here because of Vue core's internal API depends on
822
- * an ID check.
823
- *
824
- * @param {Object} handler
825
- * @param {Function} cb
826
- */
827
-
828
- var resolver = undefined;
829
-
830
- function resolveAsyncComponent(handler, cb) {
831
- if (!resolver) {
832
- resolver = {
833
- resolve: exports$1.Vue.prototype._resolveComponent,
834
- $options: {
835
- components: {
836
- _: handler.component
837
- }
838
- }
839
- };
840
- } else {
841
- resolver.$options.components._ = handler.component;
842
- }
843
- resolver.resolve('_', function (Component) {
844
- handler.component = Component;
845
- cb(Component);
846
- });
847
- }
848
-
849
- /**
850
- * Map the dynamic segments in a path to params.
851
- *
852
- * @param {String} path
853
- * @param {Object} params
854
- * @param {Object} query
855
- */
856
-
857
- function mapParams(path, params, query) {
858
- if (params === undefined) params = {};
859
-
860
- path = path.replace(/:([^\/]+)/g, function (_, key) {
861
- var val = params[key];
862
- /* istanbul ignore if */
863
- if (!val) {
864
- warn$1('param "' + key + '" not found when generating ' + 'path for "' + path + '" with params ' + JSON.stringify(params));
865
- }
866
- return val || '';
867
- });
868
- if (query) {
869
- path += genQuery(query);
870
- }
871
- return path;
872
- }
873
-
874
- var hashRE = /#.*$/;
875
-
876
- var HTML5History = (function () {
877
- function HTML5History(_ref) {
878
- var root = _ref.root;
879
- var onChange = _ref.onChange;
880
- babelHelpers.classCallCheck(this, HTML5History);
881
-
882
- if (root && root !== '/') {
883
- // make sure there's the starting slash
884
- if (root.charAt(0) !== '/') {
885
- root = '/' + root;
886
- }
887
- // remove trailing slash
888
- this.root = root.replace(/\/$/, '');
889
- this.rootRE = new RegExp('^\\' + this.root);
890
- } else {
891
- this.root = null;
892
- }
893
- this.onChange = onChange;
894
- // check base tag
895
- var baseEl = document.querySelector('base');
896
- this.base = baseEl && baseEl.getAttribute('href');
897
- }
898
-
899
- HTML5History.prototype.start = function start() {
900
- var _this = this;
901
-
902
- this.listener = function (e) {
903
- var url = location.pathname + location.search;
904
- if (_this.root) {
905
- url = url.replace(_this.rootRE, '');
906
- }
907
- _this.onChange(url, e && e.state, location.hash);
908
- };
909
- window.addEventListener('popstate', this.listener);
910
- this.listener();
911
- };
912
-
913
- HTML5History.prototype.stop = function stop() {
914
- window.removeEventListener('popstate', this.listener);
915
- };
916
-
917
- HTML5History.prototype.go = function go(path, replace, append) {
918
- var url = this.formatPath(path, append);
919
- if (replace) {
920
- history.replaceState({}, '', url);
921
- } else {
922
- // record scroll position by replacing current state
923
- history.replaceState({
924
- pos: {
925
- x: window.pageXOffset,
926
- y: window.pageYOffset
927
- }
928
- }, '', location.href);
929
- // then push new state
930
- history.pushState({}, '', url);
931
- }
932
- var hashMatch = path.match(hashRE);
933
- var hash = hashMatch && hashMatch[0];
934
- path = url
935
- // strip hash so it doesn't mess up params
936
- .replace(hashRE, '')
937
- // remove root before matching
938
- .replace(this.rootRE, '');
939
- this.onChange(path, null, hash);
940
- };
941
-
942
- HTML5History.prototype.formatPath = function formatPath(path, append) {
943
- return path.charAt(0) === '/'
944
- // absolute path
945
- ? this.root ? this.root + '/' + path.replace(/^\//, '') : path : resolvePath(this.base || location.pathname, path, append);
946
- };
947
-
948
- return HTML5History;
949
- })();
950
-
951
- var HashHistory = (function () {
952
- function HashHistory(_ref) {
953
- var hashbang = _ref.hashbang;
954
- var onChange = _ref.onChange;
955
- babelHelpers.classCallCheck(this, HashHistory);
956
-
957
- this.hashbang = hashbang;
958
- this.onChange = onChange;
959
- }
960
-
961
- HashHistory.prototype.start = function start() {
962
- var self = this;
963
- this.listener = function () {
964
- var path = location.hash;
965
- var raw = path.replace(/^#!?/, '');
966
- // always
967
- if (raw.charAt(0) !== '/') {
968
- raw = '/' + raw;
969
- }
970
- var formattedPath = self.formatPath(raw);
971
- if (formattedPath !== path) {
972
- location.replace(formattedPath);
973
- return;
974
- }
975
- // determine query
976
- // note it's possible to have queries in both the actual URL
977
- // and the hash fragment itself.
978
- var query = location.search && path.indexOf('?') > -1 ? '&' + location.search.slice(1) : location.search;
979
- self.onChange(path.replace(/^#!?/, '') + query);
980
- };
981
- window.addEventListener('hashchange', this.listener);
982
- this.listener();
983
- };
984
-
985
- HashHistory.prototype.stop = function stop() {
986
- window.removeEventListener('hashchange', this.listener);
987
- };
988
-
989
- HashHistory.prototype.go = function go(path, replace, append) {
990
- path = this.formatPath(path, append);
991
- if (replace) {
992
- location.replace(path);
993
- } else {
994
- location.hash = path;
995
- }
996
- };
997
-
998
- HashHistory.prototype.formatPath = function formatPath(path, append) {
999
- var isAbsoloute = path.charAt(0) === '/';
1000
- var prefix = '#' + (this.hashbang ? '!' : '');
1001
- return isAbsoloute ? prefix + path : prefix + resolvePath(location.hash.replace(/^#!?/, ''), path, append);
1002
- };
1003
-
1004
- return HashHistory;
1005
- })();
1006
-
1007
- var AbstractHistory = (function () {
1008
- function AbstractHistory(_ref) {
1009
- var onChange = _ref.onChange;
1010
- babelHelpers.classCallCheck(this, AbstractHistory);
1011
-
1012
- this.onChange = onChange;
1013
- this.currentPath = '/';
1014
- }
1015
-
1016
- AbstractHistory.prototype.start = function start() {
1017
- this.onChange('/');
1018
- };
1019
-
1020
- AbstractHistory.prototype.stop = function stop() {
1021
- // noop
1022
- };
1023
-
1024
- AbstractHistory.prototype.go = function go(path, replace, append) {
1025
- path = this.currentPath = this.formatPath(path, append);
1026
- this.onChange(path);
1027
- };
1028
-
1029
- AbstractHistory.prototype.formatPath = function formatPath(path, append) {
1030
- return path.charAt(0) === '/' ? path : resolvePath(this.currentPath, path, append);
1031
- };
1032
-
1033
- return AbstractHistory;
1034
- })();
1035
-
1036
- /**
1037
- * Determine the reusability of an existing router view.
1038
- *
1039
- * @param {Directive} view
1040
- * @param {Object} handler
1041
- * @param {Transition} transition
1042
- */
1043
-
1044
- function canReuse(view, handler, transition) {
1045
- var component = view.childVM;
1046
- if (!component || !handler) {
1047
- return false;
1048
- }
1049
- // important: check view.Component here because it may
1050
- // have been changed in activate hook
1051
- if (view.Component !== handler.component) {
1052
- return false;
1053
- }
1054
- var canReuseFn = getRouteConfig(component, 'canReuse');
1055
- return typeof canReuseFn === 'boolean' ? canReuseFn : canReuseFn ? canReuseFn.call(component, {
1056
- to: transition.to,
1057
- from: transition.from
1058
- }) : true; // defaults to true
1059
- }
1060
-
1061
- /**
1062
- * Check if a component can deactivate.
1063
- *
1064
- * @param {Directive} view
1065
- * @param {Transition} transition
1066
- * @param {Function} next
1067
- */
1068
-
1069
- function canDeactivate(view, transition, next) {
1070
- var fromComponent = view.childVM;
1071
- var hook = getRouteConfig(fromComponent, 'canDeactivate');
1072
- if (!hook) {
1073
- next();
1074
- } else {
1075
- transition.callHook(hook, fromComponent, next, {
1076
- expectBoolean: true
1077
- });
1078
- }
1079
- }
1080
-
1081
- /**
1082
- * Check if a component can activate.
1083
- *
1084
- * @param {Object} handler
1085
- * @param {Transition} transition
1086
- * @param {Function} next
1087
- */
1088
-
1089
- function canActivate(handler, transition, next) {
1090
- resolveAsyncComponent(handler, function (Component) {
1091
- // have to check due to async-ness
1092
- if (transition.aborted) {
1093
- return;
1094
- }
1095
- // determine if this component can be activated
1096
- var hook = getRouteConfig(Component, 'canActivate');
1097
- if (!hook) {
1098
- next();
1099
- } else {
1100
- transition.callHook(hook, null, next, {
1101
- expectBoolean: true
1102
- });
1103
- }
1104
- });
1105
- }
1106
-
1107
- /**
1108
- * Call deactivate hooks for existing router-views.
1109
- *
1110
- * @param {Directive} view
1111
- * @param {Transition} transition
1112
- * @param {Function} next
1113
- */
1114
-
1115
- function deactivate(view, transition, next) {
1116
- var component = view.childVM;
1117
- var hook = getRouteConfig(component, 'deactivate');
1118
- if (!hook) {
1119
- next();
1120
- } else {
1121
- transition.callHooks(hook, component, next);
1122
- }
1123
- }
1124
-
1125
- /**
1126
- * Activate / switch component for a router-view.
1127
- *
1128
- * @param {Directive} view
1129
- * @param {Transition} transition
1130
- * @param {Number} depth
1131
- * @param {Function} [cb]
1132
- */
1133
-
1134
- function activate(view, transition, depth, cb, reuse) {
1135
- var handler = transition.activateQueue[depth];
1136
- if (!handler) {
1137
- saveChildView(view);
1138
- if (view._bound) {
1139
- view.setComponent(null);
1140
- }
1141
- cb && cb();
1142
- return;
1143
- }
1144
-
1145
- var Component = view.Component = handler.component;
1146
- var activateHook = getRouteConfig(Component, 'activate');
1147
- var dataHook = getRouteConfig(Component, 'data');
1148
- var waitForData = getRouteConfig(Component, 'waitForData');
1149
-
1150
- view.depth = depth;
1151
- view.activated = false;
1152
-
1153
- var component = undefined;
1154
- var loading = !!(dataHook && !waitForData);
1155
-
1156
- // "reuse" is a flag passed down when the parent view is
1157
- // either reused via keep-alive or as a child of a kept-alive view.
1158
- // of course we can only reuse if the current kept-alive instance
1159
- // is of the correct type.
1160
- reuse = reuse && view.childVM && view.childVM.constructor === Component;
1161
-
1162
- if (reuse) {
1163
- // just reuse
1164
- component = view.childVM;
1165
- component.$loadingRouteData = loading;
1166
- } else {
1167
- saveChildView(view);
1168
-
1169
- // unbuild current component. this step also destroys
1170
- // and removes all nested child views.
1171
- view.unbuild(true);
1172
-
1173
- // build the new component. this will also create the
1174
- // direct child view of the current one. it will register
1175
- // itself as view.childView.
1176
- component = view.build({
1177
- _meta: {
1178
- $loadingRouteData: loading
1179
- },
1180
- created: function created() {
1181
- this._routerView = view;
1182
- }
1183
- });
1184
-
1185
- // handle keep-alive.
1186
- // when a kept-alive child vm is restored, we need to
1187
- // add its cached child views into the router's view list,
1188
- // and also properly update current view's child view.
1189
- if (view.keepAlive) {
1190
- component.$loadingRouteData = loading;
1191
- var cachedChildView = component._keepAliveRouterView;
1192
- if (cachedChildView) {
1193
- view.childView = cachedChildView;
1194
- component._keepAliveRouterView = null;
1195
- }
1196
- }
1197
- }
1198
-
1199
- // cleanup the component in case the transition is aborted
1200
- // before the component is ever inserted.
1201
- var cleanup = function cleanup() {
1202
- component.$destroy();
1203
- };
1204
-
1205
- // actually insert the component and trigger transition
1206
- var insert = function insert() {
1207
- if (reuse) {
1208
- cb && cb();
1209
- return;
1210
- }
1211
- var router = transition.router;
1212
- if (router._rendered || router._transitionOnLoad) {
1213
- view.transition(component);
1214
- } else {
1215
- // no transition on first render, manual transition
1216
- /* istanbul ignore if */
1217
- if (view.setCurrent) {
1218
- // 0.12 compat
1219
- view.setCurrent(component);
1220
- } else {
1221
- // 1.0
1222
- view.childVM = component;
1223
- }
1224
- component.$before(view.anchor, null, false);
1225
- }
1226
- cb && cb();
1227
- };
1228
-
1229
- var afterData = function afterData() {
1230
- // activate the child view
1231
- if (view.childView) {
1232
- activate(view.childView, transition, depth + 1, null, reuse || view.keepAlive);
1233
- }
1234
- insert();
1235
- };
1236
-
1237
- // called after activation hook is resolved
1238
- var afterActivate = function afterActivate() {
1239
- view.activated = true;
1240
- if (dataHook && waitForData) {
1241
- // wait until data loaded to insert
1242
- loadData(component, transition, dataHook, afterData, cleanup);
1243
- } else {
1244
- // load data and insert at the same time
1245
- if (dataHook) {
1246
- loadData(component, transition, dataHook);
1247
- }
1248
- afterData();
1249
- }
1250
- };
1251
-
1252
- if (activateHook) {
1253
- transition.callHooks(activateHook, component, afterActivate, {
1254
- cleanup: cleanup,
1255
- postActivate: true
1256
- });
1257
- } else {
1258
- afterActivate();
1259
- }
1260
- }
1261
-
1262
- /**
1263
- * Reuse a view, just reload data if necessary.
1264
- *
1265
- * @param {Directive} view
1266
- * @param {Transition} transition
1267
- */
1268
-
1269
- function reuse(view, transition) {
1270
- var component = view.childVM;
1271
- var dataHook = getRouteConfig(component, 'data');
1272
- if (dataHook) {
1273
- loadData(component, transition, dataHook);
1274
- }
1275
- }
1276
-
1277
- /**
1278
- * Asynchronously load and apply data to component.
1279
- *
1280
- * @param {Vue} component
1281
- * @param {Transition} transition
1282
- * @param {Function} hook
1283
- * @param {Function} cb
1284
- * @param {Function} cleanup
1285
- */
1286
-
1287
- function loadData(component, transition, hook, cb, cleanup) {
1288
- component.$loadingRouteData = true;
1289
- transition.callHooks(hook, component, function () {
1290
- component.$loadingRouteData = false;
1291
- component.$emit('route-data-loaded', component);
1292
- cb && cb();
1293
- }, {
1294
- cleanup: cleanup,
1295
- postActivate: true,
1296
- processData: function processData(data) {
1297
- // handle promise sugar syntax
1298
- var promises = [];
1299
- if (isPlainObject(data)) {
1300
- Object.keys(data).forEach(function (key) {
1301
- var val = data[key];
1302
- if (isPromise(val)) {
1303
- promises.push(val.then(function (resolvedVal) {
1304
- component.$set(key, resolvedVal);
1305
- }));
1306
- } else {
1307
- component.$set(key, val);
1308
- }
1309
- });
1310
- }
1311
- if (promises.length) {
1312
- return promises[0].constructor.all(promises);
1313
- }
1314
- }
1315
- });
1316
- }
1317
-
1318
- /**
1319
- * Save the child view for a kept-alive view so that
1320
- * we can restore it when it is switched back to.
1321
- *
1322
- * @param {Directive} view
1323
- */
1324
-
1325
- function saveChildView(view) {
1326
- if (view.keepAlive && view.childVM && view.childView) {
1327
- view.childVM._keepAliveRouterView = view.childView;
1328
- }
1329
- view.childView = null;
1330
- }
1331
-
1332
- /**
1333
- * Check plain object.
1334
- *
1335
- * @param {*} val
1336
- */
1337
-
1338
- function isPlainObject(val) {
1339
- return Object.prototype.toString.call(val) === '[object Object]';
1340
- }
1341
-
1342
- /**
1343
- * A RouteTransition object manages the pipeline of a
1344
- * router-view switching process. This is also the object
1345
- * passed into user route hooks.
1346
- *
1347
- * @param {Router} router
1348
- * @param {Route} to
1349
- * @param {Route} from
1350
- */
1351
-
1352
- var RouteTransition = (function () {
1353
- function RouteTransition(router, to, from) {
1354
- babelHelpers.classCallCheck(this, RouteTransition);
1355
-
1356
- this.router = router;
1357
- this.to = to;
1358
- this.from = from;
1359
- this.next = null;
1360
- this.aborted = false;
1361
- this.done = false;
1362
- }
1363
-
1364
- /**
1365
- * Abort current transition and return to previous location.
1366
- */
1367
-
1368
- RouteTransition.prototype.abort = function abort() {
1369
- if (!this.aborted) {
1370
- this.aborted = true;
1371
- // if the root path throws an error during validation
1372
- // on initial load, it gets caught in an infinite loop.
1373
- var abortingOnLoad = !this.from.path && this.to.path === '/';
1374
- if (!abortingOnLoad) {
1375
- this.router.replace(this.from.path || '/');
1376
- }
1377
- }
1378
- };
1379
-
1380
- /**
1381
- * Abort current transition and redirect to a new location.
1382
- *
1383
- * @param {String} path
1384
- */
1385
-
1386
- RouteTransition.prototype.redirect = function redirect(path) {
1387
- if (!this.aborted) {
1388
- this.aborted = true;
1389
- if (typeof path === 'string') {
1390
- path = mapParams(path, this.to.params, this.to.query);
1391
- } else {
1392
- path.params = path.params || this.to.params;
1393
- path.query = path.query || this.to.query;
1394
- }
1395
- this.router.replace(path);
1396
- }
1397
- };
1398
-
1399
- /**
1400
- * A router view transition's pipeline can be described as
1401
- * follows, assuming we are transitioning from an existing
1402
- * <router-view> chain [Component A, Component B] to a new
1403
- * chain [Component A, Component C]:
1404
- *
1405
- * A A
1406
- * | => |
1407
- * B C
1408
- *
1409
- * 1. Reusablity phase:
1410
- * -> canReuse(A, A)
1411
- * -> canReuse(B, C)
1412
- * -> determine new queues:
1413
- * - deactivation: [B]
1414
- * - activation: [C]
1415
- *
1416
- * 2. Validation phase:
1417
- * -> canDeactivate(B)
1418
- * -> canActivate(C)
1419
- *
1420
- * 3. Activation phase:
1421
- * -> deactivate(B)
1422
- * -> activate(C)
1423
- *
1424
- * Each of these steps can be asynchronous, and any
1425
- * step can potentially abort the transition.
1426
- *
1427
- * @param {Function} cb
1428
- */
1429
-
1430
- RouteTransition.prototype.start = function start(cb) {
1431
- var transition = this;
1432
-
1433
- // determine the queue of views to deactivate
1434
- var deactivateQueue = [];
1435
- var view = this.router._rootView;
1436
- while (view) {
1437
- deactivateQueue.unshift(view);
1438
- view = view.childView;
1439
- }
1440
- var reverseDeactivateQueue = deactivateQueue.slice().reverse();
1441
-
1442
- // determine the queue of route handlers to activate
1443
- var activateQueue = this.activateQueue = toArray(this.to.matched).map(function (match) {
1444
- return match.handler;
1445
- });
1446
-
1447
- // 1. Reusability phase
1448
- var i = undefined,
1449
- reuseQueue = undefined;
1450
- for (i = 0; i < reverseDeactivateQueue.length; i++) {
1451
- if (!canReuse(reverseDeactivateQueue[i], activateQueue[i], transition)) {
1452
- break;
1453
- }
1454
- }
1455
- if (i > 0) {
1456
- reuseQueue = reverseDeactivateQueue.slice(0, i);
1457
- deactivateQueue = reverseDeactivateQueue.slice(i).reverse();
1458
- activateQueue = activateQueue.slice(i);
1459
- }
1460
-
1461
- // 2. Validation phase
1462
- transition.runQueue(deactivateQueue, canDeactivate, function () {
1463
- transition.runQueue(activateQueue, canActivate, function () {
1464
- transition.runQueue(deactivateQueue, deactivate, function () {
1465
- // 3. Activation phase
1466
-
1467
- // Update router current route
1468
- transition.router._onTransitionValidated(transition);
1469
-
1470
- // trigger reuse for all reused views
1471
- reuseQueue && reuseQueue.forEach(function (view) {
1472
- return reuse(view, transition);
1473
- });
1474
-
1475
- // the root of the chain that needs to be replaced
1476
- // is the top-most non-reusable view.
1477
- if (deactivateQueue.length) {
1478
- var _view = deactivateQueue[deactivateQueue.length - 1];
1479
- var depth = reuseQueue ? reuseQueue.length : 0;
1480
- activate(_view, transition, depth, cb);
1481
- } else {
1482
- cb();
1483
- }
1484
- });
1485
- });
1486
- });
1487
- };
1488
-
1489
- /**
1490
- * Asynchronously and sequentially apply a function to a
1491
- * queue.
1492
- *
1493
- * @param {Array} queue
1494
- * @param {Function} fn
1495
- * @param {Function} cb
1496
- */
1497
-
1498
- RouteTransition.prototype.runQueue = function runQueue(queue, fn, cb) {
1499
- var transition = this;
1500
- step(0);
1501
- function step(index) {
1502
- if (index >= queue.length) {
1503
- cb();
1504
- } else {
1505
- fn(queue[index], transition, function () {
1506
- step(index + 1);
1507
- });
1508
- }
1509
- }
1510
- };
1511
-
1512
- /**
1513
- * Call a user provided route transition hook and handle
1514
- * the response (e.g. if the user returns a promise).
1515
- *
1516
- * If the user neither expects an argument nor returns a
1517
- * promise, the hook is assumed to be synchronous.
1518
- *
1519
- * @param {Function} hook
1520
- * @param {*} [context]
1521
- * @param {Function} [cb]
1522
- * @param {Object} [options]
1523
- * - {Boolean} expectBoolean
1524
- * - {Boolean} postActive
1525
- * - {Function} processData
1526
- * - {Function} cleanup
1527
- */
1528
-
1529
- RouteTransition.prototype.callHook = function callHook(hook, context, cb) {
1530
- var _ref = arguments.length <= 3 || arguments[3] === undefined ? {} : arguments[3];
1531
-
1532
- var _ref$expectBoolean = _ref.expectBoolean;
1533
- var expectBoolean = _ref$expectBoolean === undefined ? false : _ref$expectBoolean;
1534
- var _ref$postActivate = _ref.postActivate;
1535
- var postActivate = _ref$postActivate === undefined ? false : _ref$postActivate;
1536
- var processData = _ref.processData;
1537
- var cleanup = _ref.cleanup;
1538
-
1539
- var transition = this;
1540
- var nextCalled = false;
1541
-
1542
- // abort the transition
1543
- var abort = function abort() {
1544
- cleanup && cleanup();
1545
- transition.abort();
1546
- };
1547
-
1548
- // handle errors
1549
- var onError = function onError(err) {
1550
- postActivate ? next() : abort();
1551
- if (err && !transition.router._suppress) {
1552
- warn$1('Uncaught error during transition: ');
1553
- throw err instanceof Error ? err : new Error(err);
1554
- }
1555
- };
1556
-
1557
- // since promise swallows errors, we have to
1558
- // throw it in the next tick...
1559
- var onPromiseError = function onPromiseError(err) {
1560
- try {
1561
- onError(err);
1562
- } catch (e) {
1563
- setTimeout(function () {
1564
- throw e;
1565
- }, 0);
1566
- }
1567
- };
1568
-
1569
- // advance the transition to the next step
1570
- var next = function next() {
1571
- if (nextCalled) {
1572
- warn$1('transition.next() should be called only once.');
1573
- return;
1574
- }
1575
- nextCalled = true;
1576
- if (transition.aborted) {
1577
- cleanup && cleanup();
1578
- return;
1579
- }
1580
- cb && cb();
1581
- };
1582
-
1583
- var nextWithBoolean = function nextWithBoolean(res) {
1584
- if (typeof res === 'boolean') {
1585
- res ? next() : abort();
1586
- } else if (isPromise(res)) {
1587
- res.then(function (ok) {
1588
- ok ? next() : abort();
1589
- }, onPromiseError);
1590
- } else if (!hook.length) {
1591
- next();
1592
- }
1593
- };
1594
-
1595
- var nextWithData = function nextWithData(data) {
1596
- var res = undefined;
1597
- try {
1598
- res = processData(data);
1599
- } catch (err) {
1600
- return onError(err);
1601
- }
1602
- if (isPromise(res)) {
1603
- res.then(next, onPromiseError);
1604
- } else {
1605
- next();
1606
- }
1607
- };
1608
-
1609
- // expose a clone of the transition object, so that each
1610
- // hook gets a clean copy and prevent the user from
1611
- // messing with the internals.
1612
- var exposed = {
1613
- to: transition.to,
1614
- from: transition.from,
1615
- abort: abort,
1616
- next: processData ? nextWithData : next,
1617
- redirect: function redirect() {
1618
- transition.redirect.apply(transition, arguments);
1619
- }
1620
- };
1621
-
1622
- // actually call the hook
1623
- var res = undefined;
1624
- try {
1625
- res = hook.call(context, exposed);
1626
- } catch (err) {
1627
- return onError(err);
1628
- }
1629
-
1630
- if (expectBoolean) {
1631
- // boolean hooks
1632
- nextWithBoolean(res);
1633
- } else if (isPromise(res)) {
1634
- // promise
1635
- if (processData) {
1636
- res.then(nextWithData, onPromiseError);
1637
- } else {
1638
- res.then(next, onPromiseError);
1639
- }
1640
- } else if (processData && isPlainOjbect(res)) {
1641
- // data promise sugar
1642
- nextWithData(res);
1643
- } else if (!hook.length) {
1644
- next();
1645
- }
1646
- };
1647
-
1648
- /**
1649
- * Call a single hook or an array of async hooks in series.
1650
- *
1651
- * @param {Array} hooks
1652
- * @param {*} context
1653
- * @param {Function} cb
1654
- * @param {Object} [options]
1655
- */
1656
-
1657
- RouteTransition.prototype.callHooks = function callHooks(hooks, context, cb, options) {
1658
- var _this = this;
1659
-
1660
- if (Array.isArray(hooks)) {
1661
- this.runQueue(hooks, function (hook, _, next) {
1662
- if (!_this.aborted) {
1663
- _this.callHook(hook, context, next, options);
1664
- }
1665
- }, cb);
1666
- } else {
1667
- this.callHook(hooks, context, cb, options);
1668
- }
1669
- };
1670
-
1671
- return RouteTransition;
1672
- })();
1673
-
1674
- function isPlainOjbect(val) {
1675
- return Object.prototype.toString.call(val) === '[object Object]';
1676
- }
1677
-
1678
- function toArray(val) {
1679
- return val ? Array.prototype.slice.call(val) : [];
1680
- }
1681
-
1682
- var internalKeysRE = /^(component|subRoutes|fullPath)$/;
1683
-
1684
- /**
1685
- * Route Context Object
1686
- *
1687
- * @param {String} path
1688
- * @param {Router} router
1689
- */
1690
-
1691
- var Route = function Route(path, router) {
1692
- var _this = this;
1693
-
1694
- babelHelpers.classCallCheck(this, Route);
1695
-
1696
- var matched = router._recognizer.recognize(path);
1697
- if (matched) {
1698
- // copy all custom fields from route configs
1699
- [].forEach.call(matched, function (match) {
1700
- for (var key in match.handler) {
1701
- if (!internalKeysRE.test(key)) {
1702
- _this[key] = match.handler[key];
1703
- }
1704
- }
1705
- });
1706
- // set query and params
1707
- this.query = matched.queryParams;
1708
- this.params = [].reduce.call(matched, function (prev, cur) {
1709
- if (cur.params) {
1710
- for (var key in cur.params) {
1711
- prev[key] = cur.params[key];
1712
- }
1713
- }
1714
- return prev;
1715
- }, {});
1716
- }
1717
- // expose path and router
1718
- this.path = path;
1719
- // for internal use
1720
- this.matched = matched || router._notFoundHandler;
1721
- // internal reference to router
1722
- Object.defineProperty(this, 'router', {
1723
- enumerable: false,
1724
- value: router
1725
- });
1726
- // Important: freeze self to prevent observation
1727
- Object.freeze(this);
1728
- };
1729
-
1730
- function applyOverride (Vue) {
1731
- var _Vue$util = Vue.util;
1732
- var extend = _Vue$util.extend;
1733
- var isArray = _Vue$util.isArray;
1734
- var defineReactive = _Vue$util.defineReactive;
1735
-
1736
- // override Vue's init and destroy process to keep track of router instances
1737
- var init = Vue.prototype._init;
1738
- Vue.prototype._init = function (options) {
1739
- options = options || {};
1740
- var root = options._parent || options.parent || this;
1741
- var router = root.$router;
1742
- var route = root.$route;
1743
- if (router) {
1744
- // expose router
1745
- this.$router = router;
1746
- router._children.push(this);
1747
- /* istanbul ignore if */
1748
- if (this._defineMeta) {
1749
- // 0.12
1750
- this._defineMeta('$route', route);
1751
- } else {
1752
- // 1.0
1753
- defineReactive(this, '$route', route);
1754
- }
1755
- }
1756
- init.call(this, options);
1757
- };
1758
-
1759
- var destroy = Vue.prototype._destroy;
1760
- Vue.prototype._destroy = function () {
1761
- if (!this._isBeingDestroyed && this.$router) {
1762
- this.$router._children.$remove(this);
1763
- }
1764
- destroy.apply(this, arguments);
1765
- };
1766
-
1767
- // 1.0 only: enable route mixins
1768
- var strats = Vue.config.optionMergeStrategies;
1769
- var hooksToMergeRE = /^(data|activate|deactivate)$/;
1770
-
1771
- if (strats) {
1772
- strats.route = function (parentVal, childVal) {
1773
- if (!childVal) return parentVal;
1774
- if (!parentVal) return childVal;
1775
- var ret = {};
1776
- extend(ret, parentVal);
1777
- for (var key in childVal) {
1778
- var a = ret[key];
1779
- var b = childVal[key];
1780
- // for data, activate and deactivate, we need to merge them into
1781
- // arrays similar to lifecycle hooks.
1782
- if (a && hooksToMergeRE.test(key)) {
1783
- ret[key] = (isArray(a) ? a : [a]).concat(b);
1784
- } else {
1785
- ret[key] = b;
1786
- }
1787
- }
1788
- return ret;
1789
- };
1790
- }
1791
- }
1792
-
1793
- function View (Vue) {
1794
-
1795
- var _ = Vue.util;
1796
- var componentDef =
1797
- // 0.12
1798
- Vue.directive('_component') ||
1799
- // 1.0
1800
- Vue.internalDirectives.component;
1801
- // <router-view> extends the internal component directive
1802
- var viewDef = _.extend({}, componentDef);
1803
-
1804
- // with some overrides
1805
- _.extend(viewDef, {
1806
-
1807
- _isRouterView: true,
1808
-
1809
- bind: function bind() {
1810
- var route = this.vm.$route;
1811
- /* istanbul ignore if */
1812
- if (!route) {
1813
- warn$1('<router-view> can only be used inside a ' + 'router-enabled app.');
1814
- return;
1815
- }
1816
- // force dynamic directive so v-component doesn't
1817
- // attempt to build right now
1818
- this._isDynamicLiteral = true;
1819
- // finally, init by delegating to v-component
1820
- componentDef.bind.call(this);
1821
-
1822
- // locate the parent view
1823
- var parentView = undefined;
1824
- var parent = this.vm;
1825
- while (parent) {
1826
- if (parent._routerView) {
1827
- parentView = parent._routerView;
1828
- break;
1829
- }
1830
- parent = parent.$parent;
1831
- }
1832
- if (parentView) {
1833
- // register self as a child of the parent view,
1834
- // instead of activating now. This is so that the
1835
- // child's activate hook is called after the
1836
- // parent's has resolved.
1837
- this.parentView = parentView;
1838
- parentView.childView = this;
1839
- } else {
1840
- // this is the root view!
1841
- var router = route.router;
1842
- router._rootView = this;
1843
- }
1844
-
1845
- // handle late-rendered view
1846
- // two possibilities:
1847
- // 1. root view rendered after transition has been
1848
- // validated;
1849
- // 2. child view rendered after parent view has been
1850
- // activated.
1851
- var transition = route.router._currentTransition;
1852
- if (!parentView && transition.done || parentView && parentView.activated) {
1853
- var depth = parentView ? parentView.depth + 1 : 0;
1854
- activate(this, transition, depth);
1855
- }
1856
- },
1857
-
1858
- unbind: function unbind() {
1859
- if (this.parentView) {
1860
- this.parentView.childView = null;
1861
- }
1862
- componentDef.unbind.call(this);
1863
- }
1864
- });
1865
-
1866
- Vue.elementDirective('router-view', viewDef);
1867
- }
1868
-
1869
- var trailingSlashRE = /\/$/;
1870
- var regexEscapeRE = /[-.*+?^${}()|[\]\/\\]/g;
1871
- var queryStringRE = /\?.*$/;
1872
-
1873
- // install v-link, which provides navigation support for
1874
- // HTML5 history mode
1875
- function Link (Vue) {
1876
- var _Vue$util = Vue.util;
1877
- var _bind = _Vue$util.bind;
1878
- var isObject = _Vue$util.isObject;
1879
- var addClass = _Vue$util.addClass;
1880
- var removeClass = _Vue$util.removeClass;
1881
-
1882
- var onPriority = Vue.directive('on').priority;
1883
- var LINK_UPDATE = '__vue-router-link-update__';
1884
-
1885
- var activeId = 0;
1886
-
1887
- Vue.directive('link-active', {
1888
- priority: 9999,
1889
- bind: function bind() {
1890
- var _this = this;
1891
-
1892
- var id = String(activeId++);
1893
- // collect v-links contained within this element.
1894
- // we need do this here before the parent-child relationship
1895
- // gets messed up by terminal directives (if, for, components)
1896
- var childLinks = this.el.querySelectorAll('[v-link]');
1897
- for (var i = 0, l = childLinks.length; i < l; i++) {
1898
- var link = childLinks[i];
1899
- var existingId = link.getAttribute(LINK_UPDATE);
1900
- var value = existingId ? existingId + ',' + id : id;
1901
- // leave a mark on the link element which can be persisted
1902
- // through fragment clones.
1903
- link.setAttribute(LINK_UPDATE, value);
1904
- }
1905
- this.vm.$on(LINK_UPDATE, this.cb = function (link, path) {
1906
- if (link.activeIds.indexOf(id) > -1) {
1907
- link.updateClasses(path, _this.el);
1908
- }
1909
- });
1910
- },
1911
- unbind: function unbind() {
1912
- this.vm.$off(LINK_UPDATE, this.cb);
1913
- }
1914
- });
1915
-
1916
- Vue.directive('link', {
1917
- priority: onPriority - 2,
1918
-
1919
- bind: function bind() {
1920
- var vm = this.vm;
1921
- /* istanbul ignore if */
1922
- if (!vm.$route) {
1923
- warn$1('v-link can only be used inside a router-enabled app.');
1924
- return;
1925
- }
1926
- this.router = vm.$route.router;
1927
- // update things when the route changes
1928
- this.unwatch = vm.$watch('$route', _bind(this.onRouteUpdate, this));
1929
- // check v-link-active ids
1930
- var activeIds = this.el.getAttribute(LINK_UPDATE);
1931
- if (activeIds) {
1932
- this.el.removeAttribute(LINK_UPDATE);
1933
- this.activeIds = activeIds.split(',');
1934
- }
1935
- // no need to handle click if link expects to be opened
1936
- // in a new window/tab.
1937
- /* istanbul ignore if */
1938
- if (this.el.tagName === 'A' && this.el.getAttribute('target') === '_blank') {
1939
- return;
1940
- }
1941
- // handle click
1942
- this.handler = _bind(this.onClick, this);
1943
- this.el.addEventListener('click', this.handler);
1944
- },
1945
-
1946
- update: function update(target) {
1947
- this.target = target;
1948
- if (isObject(target)) {
1949
- this.append = target.append;
1950
- this.exact = target.exact;
1951
- this.prevActiveClass = this.activeClass;
1952
- this.activeClass = target.activeClass;
1953
- }
1954
- this.onRouteUpdate(this.vm.$route);
1955
- },
1956
-
1957
- onClick: function onClick(e) {
1958
- // don't redirect with control keys
1959
- /* istanbul ignore if */
1960
- if (e.metaKey || e.ctrlKey || e.shiftKey) return;
1961
- // don't redirect when preventDefault called
1962
- /* istanbul ignore if */
1963
- if (e.defaultPrevented) return;
1964
- // don't redirect on right click
1965
- /* istanbul ignore if */
1966
- if (e.button !== 0) return;
1967
-
1968
- var target = this.target;
1969
- if (target) {
1970
- // v-link with expression, just go
1971
- e.preventDefault();
1972
- this.router.go(target);
1973
- } else {
1974
- // no expression, delegate for an <a> inside
1975
- var el = e.target;
1976
- while (el.tagName !== 'A' && el !== this.el) {
1977
- el = el.parentNode;
1978
- }
1979
- if (el.tagName === 'A' && sameOrigin(el)) {
1980
- e.preventDefault();
1981
- var path = el.pathname;
1982
- if (this.router.history.root) {
1983
- path = path.replace(this.router.history.rootRE, '');
1984
- }
1985
- this.router.go({
1986
- path: path,
1987
- replace: target && target.replace,
1988
- append: target && target.append
1989
- });
1990
- }
1991
- }
1992
- },
1993
-
1994
- onRouteUpdate: function onRouteUpdate(route) {
1995
- // router.stringifyPath is dependent on current route
1996
- // and needs to be called again whenver route changes.
1997
- var newPath = this.router.stringifyPath(this.target);
1998
- if (this.path !== newPath) {
1999
- this.path = newPath;
2000
- this.updateActiveMatch();
2001
- this.updateHref();
2002
- }
2003
- if (this.activeIds) {
2004
- this.vm.$emit(LINK_UPDATE, this, route.path);
2005
- } else {
2006
- this.updateClasses(route.path, this.el);
2007
- }
2008
- },
2009
-
2010
- updateActiveMatch: function updateActiveMatch() {
2011
- this.activeRE = this.path && !this.exact ? new RegExp('^' + this.path.replace(/\/$/, '').replace(queryStringRE, '').replace(regexEscapeRE, '\\$&') + '(\\/|$)') : null;
2012
- },
2013
-
2014
- updateHref: function updateHref() {
2015
- if (this.el.tagName !== 'A') {
2016
- return;
2017
- }
2018
- var path = this.path;
2019
- var router = this.router;
2020
- var isAbsolute = path.charAt(0) === '/';
2021
- // do not format non-hash relative paths
2022
- var href = path && (router.mode === 'hash' || isAbsolute) ? router.history.formatPath(path, this.append) : path;
2023
- if (href) {
2024
- this.el.href = href;
2025
- } else {
2026
- this.el.removeAttribute('href');
2027
- }
2028
- },
2029
-
2030
- updateClasses: function updateClasses(path, el) {
2031
- var activeClass = this.activeClass || this.router._linkActiveClass;
2032
- // clear old class
2033
- if (this.prevActiveClass && this.prevActiveClass !== activeClass) {
2034
- toggleClasses(el, this.prevActiveClass, removeClass);
2035
- }
2036
- // remove query string before matching
2037
- var dest = this.path.replace(queryStringRE, '');
2038
- path = path.replace(queryStringRE, '');
2039
- // add new class
2040
- if (this.exact) {
2041
- if (dest === path ||
2042
- // also allow additional trailing slash
2043
- dest.charAt(dest.length - 1) !== '/' && dest === path.replace(trailingSlashRE, '')) {
2044
- toggleClasses(el, activeClass, addClass);
2045
- } else {
2046
- toggleClasses(el, activeClass, removeClass);
2047
- }
2048
- } else {
2049
- if (this.activeRE && this.activeRE.test(path)) {
2050
- toggleClasses(el, activeClass, addClass);
2051
- } else {
2052
- toggleClasses(el, activeClass, removeClass);
2053
- }
2054
- }
2055
- },
2056
-
2057
- unbind: function unbind() {
2058
- this.el.removeEventListener('click', this.handler);
2059
- this.unwatch && this.unwatch();
2060
- }
2061
- });
2062
-
2063
- function sameOrigin(link) {
2064
- return link.protocol === location.protocol && link.hostname === location.hostname && link.port === location.port;
2065
- }
2066
-
2067
- // this function is copied from v-bind:class implementation until
2068
- // we properly expose it...
2069
- function toggleClasses(el, key, fn) {
2070
- key = key.trim();
2071
- if (key.indexOf(' ') === -1) {
2072
- fn(el, key);
2073
- return;
2074
- }
2075
- var keys = key.split(/\s+/);
2076
- for (var i = 0, l = keys.length; i < l; i++) {
2077
- fn(el, keys[i]);
2078
- }
2079
- }
2080
- }
2081
-
2082
- var historyBackends = {
2083
- abstract: AbstractHistory,
2084
- hash: HashHistory,
2085
- html5: HTML5History
2086
- };
2087
-
2088
- // late bind during install
2089
- var Vue = undefined;
2090
-
2091
- /**
2092
- * Router constructor
2093
- *
2094
- * @param {Object} [options]
2095
- */
2096
-
2097
- var Router = (function () {
2098
- function Router() {
2099
- var _this = this;
2100
-
2101
- var _ref = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
2102
-
2103
- var _ref$hashbang = _ref.hashbang;
2104
- var hashbang = _ref$hashbang === undefined ? true : _ref$hashbang;
2105
- var _ref$abstract = _ref.abstract;
2106
- var abstract = _ref$abstract === undefined ? false : _ref$abstract;
2107
- var _ref$history = _ref.history;
2108
- var history = _ref$history === undefined ? false : _ref$history;
2109
- var _ref$saveScrollPosition = _ref.saveScrollPosition;
2110
- var saveScrollPosition = _ref$saveScrollPosition === undefined ? false : _ref$saveScrollPosition;
2111
- var _ref$transitionOnLoad = _ref.transitionOnLoad;
2112
- var transitionOnLoad = _ref$transitionOnLoad === undefined ? false : _ref$transitionOnLoad;
2113
- var _ref$suppressTransitionError = _ref.suppressTransitionError;
2114
- var suppressTransitionError = _ref$suppressTransitionError === undefined ? false : _ref$suppressTransitionError;
2115
- var _ref$root = _ref.root;
2116
- var root = _ref$root === undefined ? null : _ref$root;
2117
- var _ref$linkActiveClass = _ref.linkActiveClass;
2118
- var linkActiveClass = _ref$linkActiveClass === undefined ? 'v-link-active' : _ref$linkActiveClass;
2119
- babelHelpers.classCallCheck(this, Router);
2120
-
2121
- /* istanbul ignore if */
2122
- if (!Router.installed) {
2123
- throw new Error('Please install the Router with Vue.use() before ' + 'creating an instance.');
2124
- }
2125
-
2126
- // Vue instances
2127
- this.app = null;
2128
- this._children = [];
2129
-
2130
- // route recognizer
2131
- this._recognizer = new RouteRecognizer();
2132
- this._guardRecognizer = new RouteRecognizer();
2133
-
2134
- // state
2135
- this._started = false;
2136
- this._startCb = null;
2137
- this._currentRoute = {};
2138
- this._currentTransition = null;
2139
- this._previousTransition = null;
2140
- this._notFoundHandler = null;
2141
- this._notFoundRedirect = null;
2142
- this._beforeEachHooks = [];
2143
- this._afterEachHooks = [];
2144
-
2145
- // trigger transition on initial render?
2146
- this._rendered = false;
2147
- this._transitionOnLoad = transitionOnLoad;
2148
-
2149
- // history mode
2150
- this._root = root;
2151
- this._abstract = abstract;
2152
- this._hashbang = hashbang;
2153
-
2154
- // check if HTML5 history is available
2155
- var hasPushState = typeof window !== 'undefined' && window.history && window.history.pushState;
2156
- this._history = history && hasPushState;
2157
- this._historyFallback = history && !hasPushState;
2158
-
2159
- // create history object
2160
- var inBrowser = Vue.util.inBrowser;
2161
- this.mode = !inBrowser || this._abstract ? 'abstract' : this._history ? 'html5' : 'hash';
2162
-
2163
- var History = historyBackends[this.mode];
2164
- this.history = new History({
2165
- root: root,
2166
- hashbang: this._hashbang,
2167
- onChange: function onChange(path, state, anchor) {
2168
- _this._match(path, state, anchor);
2169
- }
2170
- });
2171
-
2172
- // other options
2173
- this._saveScrollPosition = saveScrollPosition;
2174
- this._linkActiveClass = linkActiveClass;
2175
- this._suppress = suppressTransitionError;
2176
- }
2177
-
2178
- /**
2179
- * Allow directly passing components to a route
2180
- * definition.
2181
- *
2182
- * @param {String} path
2183
- * @param {Object} handler
2184
- */
2185
-
2186
- // API ===================================================
2187
-
2188
- /**
2189
- * Register a map of top-level paths.
2190
- *
2191
- * @param {Object} map
2192
- */
2193
-
2194
- Router.prototype.map = function map(_map) {
2195
- for (var route in _map) {
2196
- this.on(route, _map[route]);
2197
- }
2198
- return this;
2199
- };
2200
-
2201
- /**
2202
- * Register a single root-level path
2203
- *
2204
- * @param {String} rootPath
2205
- * @param {Object} handler
2206
- * - {String} component
2207
- * - {Object} [subRoutes]
2208
- * - {Boolean} [forceRefresh]
2209
- * - {Function} [before]
2210
- * - {Function} [after]
2211
- */
2212
-
2213
- Router.prototype.on = function on(rootPath, handler) {
2214
- if (rootPath === '*') {
2215
- this._notFound(handler);
2216
- } else {
2217
- this._addRoute(rootPath, handler, []);
2218
- }
2219
- return this;
2220
- };
2221
-
2222
- /**
2223
- * Set redirects.
2224
- *
2225
- * @param {Object} map
2226
- */
2227
-
2228
- Router.prototype.redirect = function redirect(map) {
2229
- for (var path in map) {
2230
- this._addRedirect(path, map[path]);
2231
- }
2232
- return this;
2233
- };
2234
-
2235
- /**
2236
- * Set aliases.
2237
- *
2238
- * @param {Object} map
2239
- */
2240
-
2241
- Router.prototype.alias = function alias(map) {
2242
- for (var path in map) {
2243
- this._addAlias(path, map[path]);
2244
- }
2245
- return this;
2246
- };
2247
-
2248
- /**
2249
- * Set global before hook.
2250
- *
2251
- * @param {Function} fn
2252
- */
2253
-
2254
- Router.prototype.beforeEach = function beforeEach(fn) {
2255
- this._beforeEachHooks.push(fn);
2256
- return this;
2257
- };
2258
-
2259
- /**
2260
- * Set global after hook.
2261
- *
2262
- * @param {Function} fn
2263
- */
2264
-
2265
- Router.prototype.afterEach = function afterEach(fn) {
2266
- this._afterEachHooks.push(fn);
2267
- return this;
2268
- };
2269
-
2270
- /**
2271
- * Navigate to a given path.
2272
- * The path can be an object describing a named path in
2273
- * the format of { name: '...', params: {}, query: {}}
2274
- * The path is assumed to be already decoded, and will
2275
- * be resolved against root (if provided)
2276
- *
2277
- * @param {String|Object} path
2278
- * @param {Boolean} [replace]
2279
- */
2280
-
2281
- Router.prototype.go = function go(path) {
2282
- var replace = false;
2283
- var append = false;
2284
- if (Vue.util.isObject(path)) {
2285
- replace = path.replace;
2286
- append = path.append;
2287
- }
2288
- path = this.stringifyPath(path);
2289
- if (path) {
2290
- this.history.go(path, replace, append);
2291
- }
2292
- };
2293
-
2294
- /**
2295
- * Short hand for replacing current path
2296
- *
2297
- * @param {String} path
2298
- */
2299
-
2300
- Router.prototype.replace = function replace(path) {
2301
- if (typeof path === 'string') {
2302
- path = { path: path };
2303
- }
2304
- path.replace = true;
2305
- this.go(path);
2306
- };
2307
-
2308
- /**
2309
- * Start the router.
2310
- *
2311
- * @param {VueConstructor} App
2312
- * @param {String|Element} container
2313
- * @param {Function} [cb]
2314
- */
2315
-
2316
- Router.prototype.start = function start(App, container, cb) {
2317
- /* istanbul ignore if */
2318
- if (this._started) {
2319
- warn$1('already started.');
2320
- return;
2321
- }
2322
- this._started = true;
2323
- this._startCb = cb;
2324
- if (!this.app) {
2325
- /* istanbul ignore if */
2326
- if (!App || !container) {
2327
- throw new Error('Must start vue-router with a component and a ' + 'root container.');
2328
- }
2329
- /* istanbul ignore if */
2330
- if (App instanceof Vue) {
2331
- throw new Error('Must start vue-router with a component, not a ' + 'Vue instance.');
2332
- }
2333
- this._appContainer = container;
2334
- var Ctor = this._appConstructor = typeof App === 'function' ? App : Vue.extend(App);
2335
- // give it a name for better debugging
2336
- Ctor.options.name = Ctor.options.name || 'RouterApp';
2337
- }
2338
-
2339
- // handle history fallback in browsers that do not
2340
- // support HTML5 history API
2341
- if (this._historyFallback) {
2342
- var _location = window.location;
2343
- var _history = new HTML5History({ root: this._root });
2344
- var path = _history.root ? _location.pathname.replace(_history.rootRE, '') : _location.pathname;
2345
- if (path && path !== '/') {
2346
- _location.assign((_history.root || '') + '/' + this.history.formatPath(path) + _location.search);
2347
- return;
2348
- }
2349
- }
2350
-
2351
- this.history.start();
2352
- };
2353
-
2354
- /**
2355
- * Stop listening to route changes.
2356
- */
2357
-
2358
- Router.prototype.stop = function stop() {
2359
- this.history.stop();
2360
- this._started = false;
2361
- };
2362
-
2363
- /**
2364
- * Normalize named route object / string paths into
2365
- * a string.
2366
- *
2367
- * @param {Object|String|Number} path
2368
- * @return {String}
2369
- */
2370
-
2371
- Router.prototype.stringifyPath = function stringifyPath(path) {
2372
- var generatedPath = '';
2373
- if (path && typeof path === 'object') {
2374
- if (path.name) {
2375
- var extend = Vue.util.extend;
2376
- var currentParams = this._currentTransition && this._currentTransition.to.params;
2377
- var targetParams = path.params || {};
2378
- var params = currentParams ? extend(extend({}, currentParams), targetParams) : targetParams;
2379
- generatedPath = encodeURI(this._recognizer.generate(path.name, params));
2380
- } else if (path.path) {
2381
- generatedPath = encodeURI(path.path);
2382
- }
2383
- if (path.query) {
2384
- // note: the generated query string is pre-URL-encoded by the recognizer
2385
- var query = this._recognizer.generateQueryString(path.query);
2386
- if (generatedPath.indexOf('?') > -1) {
2387
- generatedPath += '&' + query.slice(1);
2388
- } else {
2389
- generatedPath += query;
2390
- }
2391
- }
2392
- } else {
2393
- generatedPath = encodeURI(path ? path + '' : '');
2394
- }
2395
- return generatedPath;
2396
- };
2397
-
2398
- // Internal methods ======================================
2399
-
2400
- /**
2401
- * Add a route containing a list of segments to the internal
2402
- * route recognizer. Will be called recursively to add all
2403
- * possible sub-routes.
2404
- *
2405
- * @param {String} path
2406
- * @param {Object} handler
2407
- * @param {Array} segments
2408
- */
2409
-
2410
- Router.prototype._addRoute = function _addRoute(path, handler, segments) {
2411
- guardComponent(path, handler);
2412
- handler.path = path;
2413
- handler.fullPath = (segments.reduce(function (path, segment) {
2414
- return path + segment.path;
2415
- }, '') + path).replace('//', '/');
2416
- segments.push({
2417
- path: path,
2418
- handler: handler
2419
- });
2420
- this._recognizer.add(segments, {
2421
- as: handler.name
2422
- });
2423
- // add sub routes
2424
- if (handler.subRoutes) {
2425
- for (var subPath in handler.subRoutes) {
2426
- // recursively walk all sub routes
2427
- this._addRoute(subPath, handler.subRoutes[subPath],
2428
- // pass a copy in recursion to avoid mutating
2429
- // across branches
2430
- segments.slice());
2431
- }
2432
- }
2433
- };
2434
-
2435
- /**
2436
- * Set the notFound route handler.
2437
- *
2438
- * @param {Object} handler
2439
- */
2440
-
2441
- Router.prototype._notFound = function _notFound(handler) {
2442
- guardComponent('*', handler);
2443
- this._notFoundHandler = [{ handler: handler }];
2444
- };
2445
-
2446
- /**
2447
- * Add a redirect record.
2448
- *
2449
- * @param {String} path
2450
- * @param {String} redirectPath
2451
- */
2452
-
2453
- Router.prototype._addRedirect = function _addRedirect(path, redirectPath) {
2454
- if (path === '*') {
2455
- this._notFoundRedirect = redirectPath;
2456
- } else {
2457
- this._addGuard(path, redirectPath, this.replace);
2458
- }
2459
- };
2460
-
2461
- /**
2462
- * Add an alias record.
2463
- *
2464
- * @param {String} path
2465
- * @param {String} aliasPath
2466
- */
2467
-
2468
- Router.prototype._addAlias = function _addAlias(path, aliasPath) {
2469
- this._addGuard(path, aliasPath, this._match);
2470
- };
2471
-
2472
- /**
2473
- * Add a path guard.
2474
- *
2475
- * @param {String} path
2476
- * @param {String} mappedPath
2477
- * @param {Function} handler
2478
- */
2479
-
2480
- Router.prototype._addGuard = function _addGuard(path, mappedPath, _handler) {
2481
- var _this2 = this;
2482
-
2483
- this._guardRecognizer.add([{
2484
- path: path,
2485
- handler: function handler(match, query) {
2486
- var realPath = mapParams(mappedPath, match.params, query);
2487
- _handler.call(_this2, realPath);
2488
- }
2489
- }]);
2490
- };
2491
-
2492
- /**
2493
- * Check if a path matches any redirect records.
2494
- *
2495
- * @param {String} path
2496
- * @return {Boolean} - if true, will skip normal match.
2497
- */
2498
-
2499
- Router.prototype._checkGuard = function _checkGuard(path) {
2500
- var matched = this._guardRecognizer.recognize(path, true);
2501
- if (matched) {
2502
- matched[0].handler(matched[0], matched.queryParams);
2503
- return true;
2504
- } else if (this._notFoundRedirect) {
2505
- matched = this._recognizer.recognize(path);
2506
- if (!matched) {
2507
- this.replace(this._notFoundRedirect);
2508
- return true;
2509
- }
2510
- }
2511
- };
2512
-
2513
- /**
2514
- * Match a URL path and set the route context on vm,
2515
- * triggering view updates.
2516
- *
2517
- * @param {String} path
2518
- * @param {Object} [state]
2519
- * @param {String} [anchor]
2520
- */
2521
-
2522
- Router.prototype._match = function _match(path, state, anchor) {
2523
- var _this3 = this;
2524
-
2525
- if (this._checkGuard(path)) {
2526
- return;
2527
- }
2528
-
2529
- var currentRoute = this._currentRoute;
2530
- var currentTransition = this._currentTransition;
2531
-
2532
- if (currentTransition) {
2533
- if (currentTransition.to.path === path) {
2534
- // do nothing if we have an active transition going to the same path
2535
- return;
2536
- } else if (currentRoute.path === path) {
2537
- // We are going to the same path, but we also have an ongoing but
2538
- // not-yet-validated transition. Abort that transition and reset to
2539
- // prev transition.
2540
- currentTransition.aborted = true;
2541
- this._currentTransition = this._prevTransition;
2542
- return;
2543
- } else {
2544
- // going to a totally different path. abort ongoing transition.
2545
- currentTransition.aborted = true;
2546
- }
2547
- }
2548
-
2549
- // construct new route and transition context
2550
- var route = new Route(path, this);
2551
- var transition = new RouteTransition(this, route, currentRoute);
2552
-
2553
- // current transition is updated right now.
2554
- // however, current route will only be updated after the transition has
2555
- // been validated.
2556
- this._prevTransition = currentTransition;
2557
- this._currentTransition = transition;
2558
-
2559
- if (!this.app) {
2560
- (function () {
2561
- // initial render
2562
- var router = _this3;
2563
- _this3.app = new _this3._appConstructor({
2564
- el: _this3._appContainer,
2565
- created: function created() {
2566
- this.$router = router;
2567
- },
2568
- _meta: {
2569
- $route: route
2570
- }
2571
- });
2572
- })();
2573
- }
2574
-
2575
- // check global before hook
2576
- var beforeHooks = this._beforeEachHooks;
2577
- var startTransition = function startTransition() {
2578
- transition.start(function () {
2579
- _this3._postTransition(route, state, anchor);
2580
- });
2581
- };
2582
-
2583
- if (beforeHooks.length) {
2584
- transition.runQueue(beforeHooks, function (hook, _, next) {
2585
- if (transition === _this3._currentTransition) {
2586
- transition.callHook(hook, null, next, {
2587
- expectBoolean: true
2588
- });
2589
- }
2590
- }, startTransition);
2591
- } else {
2592
- startTransition();
2593
- }
2594
-
2595
- if (!this._rendered && this._startCb) {
2596
- this._startCb.call(null);
2597
- }
2598
-
2599
- // HACK:
2600
- // set rendered to true after the transition start, so
2601
- // that components that are acitvated synchronously know
2602
- // whether it is the initial render.
2603
- this._rendered = true;
2604
- };
2605
-
2606
- /**
2607
- * Set current to the new transition.
2608
- * This is called by the transition object when the
2609
- * validation of a route has succeeded.
2610
- *
2611
- * @param {Transition} transition
2612
- */
2613
-
2614
- Router.prototype._onTransitionValidated = function _onTransitionValidated(transition) {
2615
- // set current route
2616
- var route = this._currentRoute = transition.to;
2617
- // update route context for all children
2618
- if (this.app.$route !== route) {
2619
- this.app.$route = route;
2620
- this._children.forEach(function (child) {
2621
- child.$route = route;
2622
- });
2623
- }
2624
- // call global after hook
2625
- if (this._afterEachHooks.length) {
2626
- this._afterEachHooks.forEach(function (hook) {
2627
- return hook.call(null, {
2628
- to: transition.to,
2629
- from: transition.from
2630
- });
2631
- });
2632
- }
2633
- this._currentTransition.done = true;
2634
- };
2635
-
2636
- /**
2637
- * Handle stuff after the transition.
2638
- *
2639
- * @param {Route} route
2640
- * @param {Object} [state]
2641
- * @param {String} [anchor]
2642
- */
2643
-
2644
- Router.prototype._postTransition = function _postTransition(route, state, anchor) {
2645
- // handle scroll positions
2646
- // saved scroll positions take priority
2647
- // then we check if the path has an anchor
2648
- var pos = state && state.pos;
2649
- if (pos && this._saveScrollPosition) {
2650
- Vue.nextTick(function () {
2651
- window.scrollTo(pos.x, pos.y);
2652
- });
2653
- } else if (anchor) {
2654
- Vue.nextTick(function () {
2655
- var el = document.getElementById(anchor.slice(1));
2656
- if (el) {
2657
- window.scrollTo(window.scrollX, el.offsetTop);
2658
- }
2659
- });
2660
- }
2661
- };
2662
-
2663
- return Router;
2664
- })();
2665
-
2666
- function guardComponent(path, handler) {
2667
- var comp = handler.component;
2668
- if (Vue.util.isPlainObject(comp)) {
2669
- comp = handler.component = Vue.extend(comp);
2670
- }
2671
- /* istanbul ignore if */
2672
- if (typeof comp !== 'function') {
2673
- handler.component = null;
2674
- warn$1('invalid component for route "' + path + '".');
2675
- }
2676
- }
2677
-
2678
- /* Installation */
2679
-
2680
- Router.installed = false;
2681
-
2682
- /**
2683
- * Installation interface.
2684
- * Install the necessary directives.
2685
- */
2686
-
2687
- Router.install = function (externalVue) {
2688
- /* istanbul ignore if */
2689
- if (Router.installed) {
2690
- warn$1('already installed.');
2691
- return;
2692
- }
2693
- Vue = externalVue;
2694
- applyOverride(Vue);
2695
- View(Vue);
2696
- Link(Vue);
2697
- exports$1.Vue = Vue;
2698
- Router.installed = true;
2699
- };
2700
-
2701
- // auto install
2702
- /* istanbul ignore if */
2703
- if (typeof window !== 'undefined' && window.Vue) {
2704
- window.Vue.use(Router);
2705
- }
2706
-
2707
- return Router;
2708
-
2709
- }));